summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxshu <xshu@google.com>2020-04-20 17:29:53 -0700
committerxshu <xshu@google.com>2020-04-30 17:50:00 -0700
commit7ab314bb0e004d138a11ef3e3e3dbfa7670cc4d8 (patch)
tree12f9ddaf2aa0c634a69920bc902faebe91f1af7d
parent11f1b3d49fc0c96e73eae0c993edda46228bba13 (diff)
Metered stats metrics
Count the number of saved and ephemeral networks observed as metered vs unmetered. Also, notice the metered status before network selection, when possible. Bug: 142322164 Test: com.android.server.wifi Change-Id: Ifeff1522720764d00967534317d431d40335fd5f
-rw-r--r--service/java/com/android/server/wifi/ClientModeImpl.java3
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java78
-rw-r--r--service/java/com/android/server/wifi/WifiNetworkSelector.java14
-rw-r--r--service/proto/src/metrics.proto21
-rw-r--r--tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java2
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java60
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java1
7 files changed, 175 insertions, 4 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java
index 7314bb853..00bae8a1e 100644
--- a/service/java/com/android/server/wifi/ClientModeImpl.java
+++ b/service/java/com/android/server/wifi/ClientModeImpl.java
@@ -3086,6 +3086,9 @@ public class ClientModeImpl extends StateMachine {
// Set meteredHint if DHCP result says network is metered
if (dhcpResults.vendorInfo != null && dhcpResults.vendorInfo.contains("ANDROID_METERED")) {
mWifiInfo.setMeteredHint(true);
+ mWifiMetrics.addMeteredStat(config, true);
+ } else {
+ mWifiMetrics.addMeteredStat(config, false);
}
updateCapabilities(config);
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index 4c0627af6..ca2e90552 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -71,6 +71,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.ExperimentProbeCounts;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.LinkProbeFailureReasonCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkSpeedCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.MeteredNetworkStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkSelectionExperimentDecisions;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProfileTypeCount;
import com.android.server.wifi.proto.nano.WifiMetricsProto.PasspointProvisionStats;
@@ -351,6 +352,8 @@ public class WifiMetrics {
private final IntHistogram mLinkProbeSuccessElapsedTimeMsHistogram = new IntHistogram(
LINK_PROBE_ELAPSED_TIME_MS_HISTOGRAM_BUCKETS);
private final IntCounter mLinkProbeFailureReasonCounts = new IntCounter();
+ private final MeteredNetworkStatsBuilder mMeteredNetworkStatsBuilder =
+ new MeteredNetworkStatsBuilder();
/**
* Maps a String link probe experiment ID to the number of link probes that were sent for this
@@ -3077,7 +3080,10 @@ public class WifiMetrics {
+ mWifiLogProto.numExternalForegroundAppOneshotScanRequestsThrottled);
pw.println("mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled="
+ mWifiLogProto.numExternalBackgroundAppOneshotScanRequestsThrottled);
-
+ pw.println("mWifiLogProto.meteredNetworkStatsSaved=");
+ pw.println(mMeteredNetworkStatsBuilder.toProto(false));
+ pw.println("mWifiLogProto.meteredNetworkStatsSuggestion=");
+ pw.println(mMeteredNetworkStatsBuilder.toProto(true));
pw.println("mScanReturnEntries:");
pw.println(" SCAN_UNKNOWN: " + getScanReturnEntry(
WifiMetricsProto.WifiLog.SCAN_UNKNOWN));
@@ -3701,6 +3707,7 @@ public class WifiMetrics {
mWifiLogProto.numNetworksAddedByApps = 0;
mWifiLogProto.numHiddenNetworks = 0;
mWifiLogProto.numPasspointNetworks = 0;
+
for (WifiConfiguration config : networks) {
if (config.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE)) {
mWifiLogProto.numOpenNetworks++;
@@ -4262,6 +4269,8 @@ public class WifiMetrics {
mRxThroughputMbpsHistogram2G.toProto();
mWifiLogProto.throughputMbpsHistogram.rxAbove2G =
mRxThroughputMbpsHistogramAbove2G.toProto();
+ mWifiLogProto.meteredNetworkStatsSaved = mMeteredNetworkStatsBuilder.toProto(false);
+ mWifiLogProto.meteredNetworkStatsSuggestion = mMeteredNetworkStatsBuilder.toProto(true);
InitPartialScanStats initialPartialScanStats = new InitPartialScanStats();
initialPartialScanStats.numScans = mInitPartialScanTotalCount;
@@ -4444,6 +4453,7 @@ public class WifiMetrics {
mProbeElapsedTimeSinceLastUpdateMs = -1;
mProbeMcsRateSinceLastUpdate = -1;
mScoreBreachLowTimeMillis = -1;
+ mMeteredNetworkStatsBuilder.clear();
mWifiConfigStoreReadDurationHistogram.clear();
mWifiConfigStoreWriteDurationHistogram.clear();
mLinkProbeSuccessRssiCounts.clear();
@@ -5078,6 +5088,72 @@ public class WifiMetrics {
}
return result;
}
+
+ static class MeteredNetworkStatsBuilder {
+ // A map from network identifier to MeteredDetail
+ Map<String, MeteredDetail> mNetworkMap = new ArrayMap<>();
+
+ void put(WifiConfiguration config, boolean detectedAsMetered) {
+ MeteredDetail meteredDetail = new MeteredDetail();
+ boolean isMetered = detectedAsMetered;
+ if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED) {
+ isMetered = true;
+ } else if (config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_NOT_METERED) {
+ isMetered = false;
+ }
+ meteredDetail.isMetered = isMetered;
+ meteredDetail.isMeteredOverrideSet = config.meteredOverride
+ != WifiConfiguration.METERED_OVERRIDE_NONE;
+ meteredDetail.isFromSuggestion = config.fromWifiNetworkSuggestion;
+ mNetworkMap.put(config.getKey(), meteredDetail);
+ }
+
+ void clear() {
+ mNetworkMap.clear();
+ }
+
+ MeteredNetworkStats toProto(boolean isFromSuggestion) {
+ MeteredNetworkStats result = new MeteredNetworkStats();
+ for (MeteredDetail meteredDetail : mNetworkMap.values()) {
+ if (meteredDetail.isFromSuggestion != isFromSuggestion) {
+ continue;
+ }
+ if (meteredDetail.isMetered) {
+ result.numMetered++;
+ } else {
+ result.numUnmetered++;
+ }
+ if (meteredDetail.isMeteredOverrideSet) {
+ if (meteredDetail.isMetered) {
+ result.numOverrideMetered++;
+ } else {
+ result.numOverrideUnmetered++;
+ }
+ }
+ }
+ return result;
+ }
+
+ static class MeteredDetail {
+ public boolean isMetered;
+ public boolean isMeteredOverrideSet;
+ public boolean isFromSuggestion;
+ }
+ }
+
+ /**
+ * Add metered information of this network.
+ * @param config WifiConfiguration representing the netework.
+ * @param detectedAsMetered is the network detected as metered.
+ */
+ public void addMeteredStat(WifiConfiguration config, boolean detectedAsMetered) {
+ synchronized (mLock) {
+ if (config == null) {
+ return;
+ }
+ mMeteredNetworkStatsBuilder.put(config, detectedAsMetered);
+ }
+ }
/**
* Logs a UserActionEvent without a target network.
* @param eventType the type of user action (one of WifiMetricsProto.UserActionEvent.EventType)
diff --git a/service/java/com/android/server/wifi/WifiNetworkSelector.java b/service/java/com/android/server/wifi/WifiNetworkSelector.java
index da583df65..7e95fba0b 100644
--- a/service/java/com/android/server/wifi/WifiNetworkSelector.java
+++ b/service/java/com/android/server/wifi/WifiNetworkSelector.java
@@ -676,16 +676,24 @@ public class WifiNetworkSelector {
* This is sticky to prevent continuous flip-flopping between networks, when the metered
* status is learned after association.
*/
- private boolean isEverMetered(@NonNull WifiConfiguration config, @Nullable WifiInfo info) {
+ private boolean isEverMetered(@NonNull WifiConfiguration config, @Nullable WifiInfo info,
+ @NonNull ScanDetail scanDetail) {
// If info does not match config, don't use it.
- // TODO(b/149988649) Metrics
if (info != null && info.getNetworkId() != config.networkId) info = null;
boolean metered = WifiConfiguration.isMetered(config, info);
+ NetworkDetail networkDetail = scanDetail.getNetworkDetail();
+ if (networkDetail != null
+ && networkDetail.getAnt()
+ == NetworkDetail.Ant.ChargeablePublic) {
+ metered = true;
+ }
+ mWifiMetrics.addMeteredStat(config, metered);
if (config.meteredOverride != WifiConfiguration.METERED_OVERRIDE_NONE) {
// User override is in effect; we should trust it
if (mKnownMeteredNetworkIds.remove(config.networkId)) {
localLog("KnownMeteredNetworkIds = " + mKnownMeteredNetworkIds);
}
+ metered = config.meteredOverride == WifiConfiguration.METERED_OVERRIDE_METERED;
} else if (mKnownMeteredNetworkIds.contains(config.networkId)) {
// Use the saved information
metered = true;
@@ -794,7 +802,7 @@ public class WifiNetworkSelector {
WifiCandidates.Key key = wifiCandidates.keyFromScanDetailAndConfig(
scanDetail, config);
if (key != null) {
- boolean metered = isEverMetered(config, wifiInfo);
+ boolean metered = isEverMetered(config, wifiInfo, scanDetail);
// TODO(b/151981920) Saved passpoint candidates are marked ephemeral
boolean added = wifiCandidates.add(key, config,
registeredNominator.getId(),
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index d2e769d8c..c57101f06 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -694,6 +694,12 @@ message WifiLog {
// Does the user have enhanced MAC randomization forced to on.
optional bool is_enhanced_mac_randomization_force_enabled = 194;
+
+ // Metered stats for saved networks.
+ optional MeteredNetworkStats metered_network_stats_saved = 195;
+
+ // Metered stats for suggestion networks.
+ optional MeteredNetworkStats metered_network_stats_suggestion = 196;
}
// Information that gets logged for every WiFi connection.
@@ -3055,6 +3061,21 @@ message PasspointProvisionStats {
}
}
+// Counts number of networks on the device that are metered.
+message MeteredNetworkStats {
+ // Number of networks that are set or detected as metered.
+ optional int32 num_metered = 1 [default = 0];
+
+ // Number of networks that are set or detected as unmetered.
+ optional int32 num_unmetered = 2;
+
+ // Number of networks that have meteredOverride set to metered.
+ optional int32 num_override_metered = 3;
+
+ // Number of networks that have meteredOverride set to unmetered.
+ optional int32 num_override_unmetered = 4;
+}
+
// An event capturing user action on wifi
message UserActionEvent {
enum EventType {
diff --git a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
index 8f36770e6..77f9bf910 100644
--- a/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/ClientModeImplTest.java
@@ -1028,6 +1028,8 @@ public class ClientModeImplTest extends WifiBaseTest {
injectDhcpSuccess(dhcpResults);
mLooper.dispatchAll();
+ // Verify WifiMetrics logging for metered metrics based on DHCP results
+ verify(mWifiMetrics).addMeteredStat(any(), anyBoolean());
WifiInfo wifiInfo = mCmi.getWifiInfo();
assertNotNull(wifiInfo);
assertEquals(sBSSID, wifiInfo.getBSSID());
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index d374dc9ce..d2c292221 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -4468,6 +4468,66 @@ public class WifiMetricsTest extends WifiBaseTest {
assertEquals(4, mDecodedProto.wifiToggleStats.numToggleOffNormal);
}
+ /**
+ * Verify metered stats are counted properly for saved and ephemeral networks.
+ */
+ @Test
+ public void testMeteredNetworkMetrics() throws Exception {
+ // Test without metered override
+ WifiConfiguration config = WifiConfigurationTestUtil.createPskNetwork();
+ WifiConfiguration config1 = WifiConfigurationTestUtil.createPskNetwork();
+ config.fromWifiNetworkSuggestion = false;
+ config1.fromWifiNetworkSuggestion = true;
+ mWifiMetrics.addMeteredStat(config, false);
+ mWifiMetrics.addMeteredStat(config1, true);
+ dumpProtoAndDeserialize();
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numMetered);
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
+
+ // Test with metered override
+ config = WifiConfigurationTestUtil.createPskNetwork();
+ config1 = WifiConfigurationTestUtil.createPskNetwork();
+ config.meteredOverride = WifiConfiguration.METERED_OVERRIDE_METERED;
+ config1.meteredOverride = WifiConfiguration.METERED_OVERRIDE_NOT_METERED;
+ mWifiMetrics.addMeteredStat(config, true);
+ mWifiMetrics.addMeteredStat(config1, true);
+ dumpProtoAndDeserialize();
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
+ }
+
+ /**
+ * Verify that the same network does not get counted twice
+ */
+ @Test
+ public void testMeteredNetworkMetricsNoDoubleCount() throws Exception {
+ WifiConfiguration config = new WifiConfiguration();
+ config.ephemeral = false;
+ mWifiMetrics.addMeteredStat(config, false);
+ mWifiMetrics.addMeteredStat(config, true);
+ mWifiMetrics.addMeteredStat(config, true);
+ dumpProtoAndDeserialize();
+ assertEquals(1, mDecodedProto.meteredNetworkStatsSaved.numMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSaved.numOverrideUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numUnmetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideMetered);
+ assertEquals(0, mDecodedProto.meteredNetworkStatsSuggestion.numOverrideUnmetered);
+ }
/**
* Create a test to verify data collection logic triggered by score breaching low
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
index 7c5ff1f3f..f8c47a2f6 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkSelectorTest.java
@@ -596,6 +596,7 @@ public class WifiNetworkSelectorTest extends WifiBaseTest {
verify(mWifiConfigManager, times(savedConfigs.length)).tryEnableNetwork(anyInt());
verify(mWifiConfigManager, times(savedConfigs.length))
.clearNetworkCandidateScanResult(anyInt());
+ verify(mWifiMetrics, atLeastOnce()).addMeteredStat(any(), anyBoolean());
}
/**