summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/server/wifi/BssidBlocklistMonitor.java17
-rw-r--r--service/java/com/android/server/wifi/WifiMetrics.java53
-rw-r--r--service/java/com/android/server/wifi/WifiServiceImpl.java11
-rw-r--r--service/java/com/android/server/wifi/util/MetricsUtils.java65
-rw-r--r--service/proto/src/metrics.proto55
-rw-r--r--tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java20
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java86
-rw-r--r--tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java3
8 files changed, 301 insertions, 9 deletions
diff --git a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
index bc41aa929..d96fdb39e 100644
--- a/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
+++ b/service/java/com/android/server/wifi/BssidBlocklistMonitor.java
@@ -37,6 +37,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -60,7 +61,7 @@ public class BssidBlocklistMonitor {
public static final int REASON_EAP_FAILURE = 3;
// Other association rejection failures
public static final int REASON_ASSOCIATION_REJECTION = 4;
- // Associated timeout failures, when the RSSI is good
+ // Association timeout failures.
public static final int REASON_ASSOCIATION_TIMEOUT = 5;
// Other authentication failures
public static final int REASON_AUTHENTICATION_FAILURE = 6;
@@ -528,6 +529,20 @@ public class BssidBlocklistMonitor {
}
/**
+ * Gets the list of block reasons for BSSIDs currently in the blocklist.
+ * @return The set of unique reasons for blocking BSSIDs with this SSID.
+ */
+ public Set<Integer> getFailureReasonsForSsid(@NonNull String ssid) {
+ if (ssid == null) {
+ return Collections.emptySet();
+ }
+ return mBssidStatusMap.values().stream()
+ .filter(entry -> entry.isInBlocklist && ssid.equals(entry.ssid))
+ .map(entry -> entry.blockReason)
+ .collect(Collectors.toSet());
+ }
+
+ /**
* Attempts to re-enable BSSIDs that likely experienced failures due to low RSSI.
* @param scanDetails
*/
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index a5771f7e3..1ac361ef3 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -29,6 +29,7 @@ import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -74,6 +75,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.LinkProbeStats.Experi
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.NetworkDisableReason;
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;
@@ -114,6 +116,7 @@ import org.json.JSONObject;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.BitSet;
import java.util.Calendar;
import java.util.HashMap;
@@ -808,6 +811,35 @@ public class WifiMetrics {
}
}
+ private NetworkDisableReason convertToNetworkDisableReason(
+ WifiConfiguration config, Set<Integer> bssidBlocklistReasons) {
+ NetworkSelectionStatus status = config.getNetworkSelectionStatus();
+ NetworkDisableReason result = new NetworkDisableReason();
+ if (config.allowAutojoin) {
+ if (!status.isNetworkEnabled()) {
+ result.disableReason =
+ MetricsUtils.convertNetworkSelectionDisableReasonToWifiProtoEnum(
+ status.getNetworkSelectionDisableReason());
+ if (status.isNetworkPermanentlyDisabled()) {
+ result.configPermanentlyDisabled = true;
+ } else {
+ result.configTemporarilyDisabled = true;
+ }
+ }
+ } else {
+ result.disableReason = NetworkDisableReason.REASON_AUTO_JOIN_DISABLED;
+ result.configPermanentlyDisabled = true;
+ }
+
+ int[] convertedBssidBlockReasons = bssidBlocklistReasons.stream()
+ .mapToInt(i -> MetricsUtils.convertBssidBlocklistReasonToWifiProtoEnum(i))
+ .toArray();
+ if (convertedBssidBlockReasons.length > 0) {
+ result.bssidDisableReasons = convertedBssidBlockReasons;
+ }
+ return result;
+ }
+
class UserActionEventWithTime {
private UserActionEvent mUserActionEvent;
private long mWallClockTimeMs = 0; // wall clock time for debugging only
@@ -830,6 +862,8 @@ public class WifiMetrics {
networkInfo.isEphemeral = config.isEphemeral();
networkInfo.isPasspoint = config.isPasspoint();
mUserActionEvent.targetNetworkInfo = networkInfo;
+ mUserActionEvent.networkDisableReason = convertToNetworkDisableReason(
+ config, mBssidBlocklistMonitor.getFailureReasonsForSsid(config.SSID));
}
}
}
@@ -890,7 +924,24 @@ public class WifiMetrics {
}
WifiStatus wifiStatus = mUserActionEvent.wifiStatus;
if (wifiStatus != null) {
- sb.append("\nWifiStatus=" + wifiStatus.toString());
+ sb.append("\nWifiStatus: isConnected=").append(wifiStatus.isConnected);
+ sb.append(" isValidated=").append(wifiStatus.isValidated);
+ sb.append(" lastRssi=").append(wifiStatus.lastRssi);
+ sb.append(" estimatedTxKbps=").append(wifiStatus.estimatedTxKbps);
+ sb.append(" estimatedRxKbps=").append(wifiStatus.estimatedRxKbps);
+ sb.append(" isStuckDueToUserConnectChoice=")
+ .append(wifiStatus.isStuckDueToUserConnectChoice);
+ }
+ NetworkDisableReason disableReason = mUserActionEvent.networkDisableReason;
+ if (disableReason != null) {
+ sb.append("\nNetworkDisableReason: DisableReason=")
+ .append(disableReason.disableReason);
+ sb.append(" configTemporarilyDisabled=")
+ .append(disableReason.configTemporarilyDisabled);
+ sb.append(" configPermanentlyDisabled=")
+ .append(disableReason.configPermanentlyDisabled);
+ sb.append(" bssidDisableReasons=")
+ .append(Arrays.toString(disableReason.bssidDisableReasons));
}
return sb.toString();
}
diff --git a/service/java/com/android/server/wifi/WifiServiceImpl.java b/service/java/com/android/server/wifi/WifiServiceImpl.java
index 20aea050a..5019f54e8 100644
--- a/service/java/com/android/server/wifi/WifiServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiServiceImpl.java
@@ -802,8 +802,13 @@ public class WifiServiceImpl extends BaseWifiService {
Binder.restoreCallingIdentity(ident);
}
if (mWifiPermissionsUtil.checkNetworkSettingsPermission(Binder.getCallingUid())) {
- mWifiMetrics.logUserActionEvent(enable ? UserActionEvent.EVENT_TOGGLE_WIFI_ON
- : UserActionEvent.EVENT_TOGGLE_WIFI_OFF);
+ if (enable) {
+ mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
+ } else {
+ WifiInfo wifiInfo = mClientModeImpl.syncRequestConnectionInfo();
+ mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF,
+ wifiInfo == null ? -1 : wifiInfo.getNetworkId());
+ }
}
mWifiMetrics.incrementNumWifiToggles(isPrivileged, enable);
mActiveModeWarden.wifiToggled();
@@ -4118,7 +4123,6 @@ public class WifiServiceImpl extends BaseWifiService {
throw new SecurityException(TAG + ": Permission denied");
}
mLog.info("connect uid=%").c(uid).flush();
- mClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid);
if (mWifiPermissionsUtil.checkNetworkSettingsPermission(uid)) {
if (config == null) {
mWifiMetrics.logUserActionEvent(UserActionEvent.EVENT_MANUAL_CONNECT, netId);
@@ -4127,6 +4131,7 @@ public class WifiServiceImpl extends BaseWifiService {
UserActionEvent.EVENT_ADD_OR_UPDATE_NETWORK, config.networkId);
}
}
+ mClientModeImpl.connect(config, netId, binder, callback, callbackIdentifier, uid);
}
/**
diff --git a/service/java/com/android/server/wifi/util/MetricsUtils.java b/service/java/com/android/server/wifi/util/MetricsUtils.java
index 2c9c7f741..4c87aa237 100644
--- a/service/java/com/android/server/wifi/util/MetricsUtils.java
+++ b/service/java/com/android/server/wifi/util/MetricsUtils.java
@@ -16,8 +16,12 @@
package com.android.server.wifi.util;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.util.SparseIntArray;
+import com.android.server.wifi.BssidBlocklistMonitor;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.NetworkDisableReason;
+
/**
* Utilities for Metrics collections.
*/
@@ -188,4 +192,65 @@ public class MetricsUtils {
return protoArray;
}
+
+ /**
+ * Converts NetworkSelectionStatus.NetworkSelectionDisableReason to
+ * WifiMetricsProto.NetworkDisableReason.DisableReason
+ */
+ public static int convertNetworkSelectionDisableReasonToWifiProtoEnum(int reason) {
+ switch (reason) {
+ case NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION:
+ return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE:
+ return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
+ case NetworkSelectionStatus.DISABLED_DHCP_FAILURE:
+ return NetworkDisableReason.REASON_DHCP_FAILURE;
+ case NetworkSelectionStatus.DISABLED_NO_INTERNET_TEMPORARY:
+ case NetworkSelectionStatus.DISABLED_NO_INTERNET_PERMANENT:
+ return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_CREDENTIALS:
+ return NetworkDisableReason.REASON_AUTHENTICATION_NO_CREDENTIALS;
+ case NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD:
+ return NetworkDisableReason.REASON_WRONG_PASSWORD;
+ case NetworkSelectionStatus.DISABLED_AUTHENTICATION_NO_SUBSCRIPTION:
+ return NetworkDisableReason.REASON_AUTHENTICATION_NO_SUBSCRIPTION;
+ default:
+ return NetworkDisableReason.REASON_UNKNOWN;
+ }
+ }
+
+ /**
+ * Converts BssidBlocklistMonitor.FailureReason to
+ * WifiMetricsProto.NetworkDisableReason.DisableReason
+ */
+ public static int convertBssidBlocklistReasonToWifiProtoEnum(int reason) {
+ switch (reason) {
+ case BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA:
+ return NetworkDisableReason.REASON_AP_UNABLE_TO_HANDLE_NEW_STA;
+ case BssidBlocklistMonitor.REASON_NETWORK_VALIDATION_FAILURE:
+ return NetworkDisableReason.REASON_NETWORK_VALIDATION_FAILURE;
+ case BssidBlocklistMonitor.REASON_WRONG_PASSWORD:
+ return NetworkDisableReason.REASON_WRONG_PASSWORD;
+ case BssidBlocklistMonitor.REASON_EAP_FAILURE:
+ return NetworkDisableReason.REASON_EAP_FAILURE;
+ case BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION:
+ return NetworkDisableReason.REASON_ASSOCIATION_REJECTION;
+ case BssidBlocklistMonitor.REASON_ASSOCIATION_TIMEOUT:
+ return NetworkDisableReason.REASON_ASSOCIATION_TIMEOUT;
+ case BssidBlocklistMonitor.REASON_AUTHENTICATION_FAILURE:
+ return NetworkDisableReason.REASON_AUTHENTICATION_FAILURE;
+ case BssidBlocklistMonitor.REASON_DHCP_FAILURE:
+ return NetworkDisableReason.REASON_DHCP_FAILURE;
+ case BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT:
+ return NetworkDisableReason.REASON_ABNORMAL_DISCONNECT;
+ case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_MBO_OCE:
+ return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_MBO_OCE;
+ case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT:
+ return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT;
+ case BssidBlocklistMonitor.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE:
+ return NetworkDisableReason.REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE;
+ default:
+ return NetworkDisableReason.REASON_UNKNOWN;
+ }
+ }
}
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index a9c759e7e..a7f706fb8 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -3172,6 +3172,11 @@ message UserActionEvent {
// Information about the currently connected network.
optional WifiStatus wifi_status = 4;
+
+ // Reasons why the network applicable for this user action is disabled.
+ // Normally this should be referring to the currently connected network.
+ // For a manual connection, this is referring to the user selected networks.
+ optional NetworkDisableReason network_disable_reason = 5;
}
message WifiStatus {
@@ -3203,6 +3208,56 @@ message TargetNetworkInfo {
optional bool is_passpoint = 2;
}
+// Reasons why a configuration or BSSID is disabled.
+message NetworkDisableReason {
+ enum DisableReason {
+ // Default value, should not be used.
+ REASON_UNKNOWN = 0;
+ // AP unable to accept more clients, a special kind of association rejection failure.
+ REASON_AP_UNABLE_TO_HANDLE_NEW_STA = 1;
+ // No internet
+ REASON_NETWORK_VALIDATION_FAILURE = 2;
+ // Password is incorrect, a special kind of authentication failure.
+ REASON_WRONG_PASSWORD = 3;
+ // Incorrect EAP credentials.
+ REASON_EAP_FAILURE = 4;
+ // Other association rejection failures.
+ REASON_ASSOCIATION_REJECTION = 5;
+ // Associated timeout failures.
+ REASON_ASSOCIATION_TIMEOUT = 6;
+ // Other authentication failures.
+ REASON_AUTHENTICATION_FAILURE = 7;
+ // DHCP failures.
+ REASON_DHCP_FAILURE = 8;
+ // Device disconnected shortly after connection.
+ REASON_ABNORMAL_DISCONNECT = 9;
+ // AP initiated disconnect for a given duration.
+ REASON_FRAMEWORK_DISCONNECT_MBO_OCE = 10;
+ // Avoid connecting to the failed AP when trying to reconnect on other available candidates.
+ REASON_FRAMEWORK_DISCONNECT_FAST_RECONNECT = 11;
+ // The connected scorer has disconnected this network.
+ REASON_FRAMEWORK_DISCONNECT_CONNECTED_SCORE = 12;
+ // The network is disabled due to absence of user credentials
+ REASON_AUTHENTICATION_NO_CREDENTIALS = 13;
+ // The network is disabled because service is not subscribed, a special kind of EAP failure.
+ REASON_AUTHENTICATION_NO_SUBSCRIPTION = 14;
+ // User disabled auto-join for this network.
+ REASON_AUTO_JOIN_DISABLED = 15;
+ }
+
+ // The reason for disabling a network.
+ optional DisableReason disable_reason = 1;
+
+ // The configuration is temporarily disabled.
+ optional bool config_temporarily_disabled = 2;
+
+ // The configuration is disabled until the user manually re-enables it.
+ optional bool config_permanently_disabled = 3;
+
+ // Reasons why 1 or more BSSIDs are temporarily disabled.
+ repeated DisableReason bssid_disable_reasons = 4;
+}
+
// Number of networks with a large change of connection/disconnection
// failure rate or high failure rate at high RSSI
message HealthMonitorFailureStats {
diff --git a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java b/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
index e3c8d52fa..d6333b363 100644
--- a/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/BssidBlocklistMonitorTest.java
@@ -776,4 +776,24 @@ public class BssidBlocklistMonitorTest {
simulateRssiUpdate(TEST_BSSID_1, TEST_SUFFICIENT_RSSI);
assertTrue(mBssidBlocklistMonitor.updateAndGetBssidBlocklist().contains(TEST_BSSID_1));
}
+
+ /**
+ * Verify the failure reasons for all blocked BSSIDs are retrieved.
+ */
+ @Test
+ public void testGetFailureReasonsForSsid() {
+ // Null input should not crash
+ mBssidBlocklistMonitor.getFailureReasonsForSsid(null).size();
+ assertEquals(0, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size());
+ mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_1, TEST_SSID_1, 1000,
+ BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA, TEST_GOOD_RSSI);
+ mBssidBlocklistMonitor.blockBssidForDurationMs(TEST_BSSID_2, TEST_SSID_1, 1000,
+ BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT, TEST_GOOD_RSSI);
+
+ assertEquals(2, mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1).size());
+ assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1)
+ .contains(BssidBlocklistMonitor.REASON_AP_UNABLE_TO_HANDLE_NEW_STA));
+ assertTrue(mBssidBlocklistMonitor.getFailureReasonsForSsid(TEST_SSID_1)
+ .contains(BssidBlocklistMonitor.REASON_ABNORMAL_DISCONNECT));
+ }
}
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 0a5a512b2..b4cd7592c 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -60,6 +60,7 @@ import android.net.wifi.SoftApCapability;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
import android.net.wifi.WifiEnterpriseConfig;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
@@ -98,6 +99,7 @@ import com.android.server.wifi.proto.nano.WifiMetricsProto.Int32Count;
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.NetworkDisableReason;
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;
@@ -129,9 +131,11 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -2399,9 +2403,8 @@ public class WifiMetricsTest extends WifiBaseTest {
int testNetworkId = 0;
long testStartTimeMillis = 123123L;
when(mClock.getElapsedSinceBootMillis()).thenReturn(testStartTimeMillis);
- WifiConfiguration config = mock(WifiConfiguration.class);
- when(config.isEphemeral()).thenReturn(true);
- when(config.isPasspoint()).thenReturn(true);
+ WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
+ config.ephemeral = true;
when(mWcm.getConfiguredNetwork(testNetworkId)).thenReturn(config);
mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
@@ -2414,6 +2417,13 @@ public class WifiMetricsTest extends WifiBaseTest {
assertEquals(testStartTimeMillis, userActionEvents[0].startTimeMillis);
assertEquals(true, userActionEvents[0].targetNetworkInfo.isEphemeral);
assertEquals(true, userActionEvents[0].targetNetworkInfo.isPasspoint);
+
+ // Verify that there are no disabled WifiConfiguration and BSSIDs
+ NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+ assertEquals(NetworkDisableReason.REASON_UNKNOWN, networkDisableReason.disableReason);
+ assertEquals(false, networkDisableReason.configTemporarilyDisabled);
+ assertEquals(false, networkDisableReason.configPermanentlyDisabled);
+ assertEquals(0, networkDisableReason.bssidDisableReasons.length);
}
/**
@@ -2452,6 +2462,76 @@ public class WifiMetricsTest extends WifiBaseTest {
}
/**
+ * verify NetworkDisableReason is populated properly when there exists a disabled
+ * WifiConfiguration and BSSID.
+ */
+ @Test
+ public void testNetworkDisableReasonInUserActionEvent() throws Exception {
+ // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
+ WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
+ NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
+ status.setNetworkSelectionStatus(
+ NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
+ status.setNetworkSelectionDisableReason(
+ NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
+ when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
+
+ // Also setup the same BSSID level failure
+ Set<Integer> testBssidBlocklistReasons = new HashSet<>();
+ testBssidBlocklistReasons.add(BssidBlocklistMonitor.REASON_ASSOCIATION_REJECTION);
+ when(mBssidBlocklistMonitor.getFailureReasonsForSsid(anyString()))
+ .thenReturn(testBssidBlocklistReasons);
+
+ // Logging the user action event
+ mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+ TEST_NETWORK_ID);
+ dumpProtoAndDeserialize();
+
+ WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+ assertEquals(1, userActionEvents.length);
+ assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+ userActionEvents[0].eventType);
+ NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+ assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
+ networkDisableReason.disableReason);
+ assertEquals(true, networkDisableReason.configTemporarilyDisabled);
+ assertEquals(false, networkDisableReason.configPermanentlyDisabled);
+ assertEquals(1, networkDisableReason.bssidDisableReasons.length);
+ assertEquals(NetworkDisableReason.REASON_ASSOCIATION_REJECTION,
+ networkDisableReason.bssidDisableReasons[0]);
+ }
+
+ /**
+ * verify that auto-join disable overrides any other disable reasons in NetworkDisableReason.
+ */
+ @Test
+ public void testNetworkDisableReasonDisableAutojoinInUserActionEvent() throws Exception {
+ // Setup a temporarily blocked config due to DISABLED_ASSOCIATION_REJECTION
+ WifiConfiguration testConfig = WifiConfigurationTestUtil.createOpenNetwork();
+ NetworkSelectionStatus status = testConfig.getNetworkSelectionStatus();
+ status.setNetworkSelectionStatus(
+ NetworkSelectionStatus.NETWORK_SELECTION_TEMPORARY_DISABLED);
+ status.setNetworkSelectionDisableReason(
+ NetworkSelectionStatus.DISABLED_ASSOCIATION_REJECTION);
+ when(mWcm.getConfiguredNetwork(TEST_NETWORK_ID)).thenReturn(testConfig);
+
+ // Disable autojoin
+ testConfig.allowAutojoin = false;
+
+ // Logging the user action event
+ mWifiMetrics.logUserActionEvent(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+ TEST_NETWORK_ID);
+ dumpProtoAndDeserialize();
+
+ WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+ NetworkDisableReason networkDisableReason = userActionEvents[0].networkDisableReason;
+ assertEquals(NetworkDisableReason.REASON_AUTO_JOIN_DISABLED,
+ networkDisableReason.disableReason);
+ assertEquals(false, networkDisableReason.configTemporarilyDisabled);
+ assertEquals(true, networkDisableReason.configPermanentlyDisabled);
+ }
+
+ /**
* Test the logging of UserActionEvent with invalid network ID
*/
@Test
diff --git a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
index 49ccf9bd3..22561a159 100644
--- a/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
+++ b/tests/wifitests/src/com/android/server/wifi/WifiServiceImplTest.java
@@ -571,7 +571,8 @@ public class WifiServiceImplTest extends WifiBaseTest {
assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_ON);
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(true));
- inorder.verify(mWifiMetrics).logUserActionEvent(UserActionEvent.EVENT_TOGGLE_WIFI_OFF);
+ inorder.verify(mWifiMetrics).logUserActionEvent(eq(UserActionEvent.EVENT_TOGGLE_WIFI_OFF),
+ anyInt());
inorder.verify(mWifiMetrics).incrementNumWifiToggles(eq(true), eq(false));
}