From da1b2e9ed28829fd434cd2bedd5932961696e479 Mon Sep 17 00:00:00 2001 From: xshu Date: Wed, 19 Aug 2020 17:07:03 -0700 Subject: Adding network disabled status to user action metrics (cherry-picked from acd5659d05dacf1de79489c7740c87e95cbf5b03) When a user action is triggered, take note of the reasons WifiConfigurations and BSSIDs are disabled. This information will be used to gain insight why we did not auto-connect to manaually selected networks. Updated-PDD: true Bug: 165118962 Test: com.android.server.wifi Test: Manual verification with dumpsys log Change-Id: I7d3a0a933e4f9f45b20019ace3013e1661212fad Merged-In: I7d3a0a933e4f9f45b20019ace3013e1661212fad --- .../android/server/wifi/BssidBlocklistMonitor.java | 17 +++++- .../java/com/android/server/wifi/WifiMetrics.java | 53 +++++++++++++++++- .../com/android/server/wifi/WifiServiceImpl.java | 11 +++- .../com/android/server/wifi/util/MetricsUtils.java | 65 ++++++++++++++++++++++ service/proto/src/metrics.proto | 55 ++++++++++++++++++ 5 files changed, 196 insertions(+), 5 deletions(-) (limited to 'service') 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; @@ -527,6 +528,20 @@ public class BssidBlocklistMonitor { .collect(Collectors.toSet()); } + /** + * 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 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 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 { -- cgit v1.2.3