Add WifiStatus to UserAction metrics
(cherry-picked from c53ba0980a30bf07a73dc56743183315c0b70041)
Include a snapshot of latest wifi status in the UserActionEvent.
Updated-PDD: true
Bug: 165118962
Test: atest com.android.server.wifi
Change-Id: I21b617a520c11babfc39fa8d0103900fd78ea270
Merged-In: I21b617a520c11babfc39fa8d0103900fd78ea270
(cherry picked from commit 1eabbd9e0ae9082f804424017fccc5973558fea8)
diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java
index a71e2ee..e0c4bea 100644
--- a/service/java/com/android/server/wifi/WifiMetrics.java
+++ b/service/java/com/android/server/wifi/WifiMetrics.java
@@ -92,6 +92,7 @@
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkRequestApiLog;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiNetworkSuggestionApiLog.SuggestionAppCount;
+import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiStatus;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiToggleStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStats;
import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiUsabilityStatsEntry;
@@ -232,6 +233,7 @@
@VisibleForTesting static final int MAX_USER_ACTION_EVENTS = 200;
private LinkedList<StaEventWithTime> mStaEventList = new LinkedList<>();
private LinkedList<UserActionEventWithTime> mUserActionEventList = new LinkedList<>();
+ private WifiStatusBuilder mWifiStatusBuilder = new WifiStatusBuilder();
private int mLastPollRssi = -127;
private int mLastPollLinkSpeed = -1;
private int mLastPollRxLinkSpeed = -1;
@@ -754,6 +756,59 @@
}
}
+ class WifiStatusBuilder {
+ private int mNetworkId = WifiConfiguration.INVALID_NETWORK_ID;
+ private boolean mConnected;
+ private boolean mValidated;
+ private int mRssi;
+ private int mEstimatedTxKbps;
+ private int mEstimatedRxKbps;
+ private boolean mIsStuckDueToUserChoice;
+
+ public void setNetworkId(int networkId) {
+ mNetworkId = networkId;
+ }
+
+ public int getNetworkId() {
+ return mNetworkId;
+ }
+
+ public void setConnected(boolean connected) {
+ mConnected = connected;
+ }
+
+ public void setValidated(boolean validated) {
+ mValidated = validated;
+ }
+
+ public void setRssi(int rssi) {
+ mRssi = rssi;
+ }
+
+ public void setEstimatedTxKbps(int estimatedTxKbps) {
+ mEstimatedTxKbps = estimatedTxKbps;
+ }
+
+ public void setEstimatedRxKbps(int estimatedRxKbps) {
+ mEstimatedRxKbps = estimatedRxKbps;
+ }
+
+ public void setUserChoice(boolean userChoice) {
+ mIsStuckDueToUserChoice = userChoice;
+ }
+
+ public WifiStatus toProto() {
+ WifiStatus result = new WifiStatus();
+ result.isConnected = mConnected;
+ result.isValidated = mValidated;
+ result.lastRssi = mRssi;
+ result.estimatedTxKbps = mEstimatedTxKbps;
+ result.estimatedRxKbps = mEstimatedRxKbps;
+ result.isStuckDueToUserConnectChoice = mIsStuckDueToUserChoice;
+ return result;
+ }
+ }
+
class UserActionEventWithTime {
private UserActionEvent mUserActionEvent;
private long mWallClockTimeMs = 0; // wall clock time for debugging only
@@ -764,13 +819,11 @@
mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
mWallClockTimeMs = mClock.getWallClockMillis();
mUserActionEvent.targetNetworkInfo = targetNetworkInfo;
+ mUserActionEvent.wifiStatus = mWifiStatusBuilder.toProto();
}
UserActionEventWithTime(int eventType, int targetNetId) {
- mUserActionEvent = new UserActionEvent();
- mUserActionEvent.eventType = eventType;
- mUserActionEvent.startTimeMillis = mClock.getElapsedSinceBootMillis();
- mWallClockTimeMs = mClock.getWallClockMillis();
+ this(eventType, null);
if (targetNetId >= 0) {
WifiConfiguration config = mWifiConfigManager.getConfiguredNetwork(targetNetId);
if (config != null) {
@@ -836,6 +889,10 @@
sb.append(" isEphemeral=").append(networkInfo.isEphemeral);
sb.append(" isPasspoint=").append(networkInfo.isPasspoint);
}
+ WifiStatus wifiStatus = mUserActionEvent.wifiStatus;
+ if (wifiStatus != null) {
+ sb.append("\nWifiStatus=" + wifiStatus.toString());
+ }
return sb.toString();
}
@@ -1611,6 +1668,7 @@
if (!result) {
mScanResultRssiTimestampMillis = -1;
}
+ mWifiStatusBuilder.setConnected(result);
}
}
}
@@ -2088,6 +2146,8 @@
mLastPollRxLinkSpeed = wifiInfo.getRxLinkSpeedMbps();
incrementTxLinkSpeedBandCount(mLastPollLinkSpeed, mLastPollFreq);
incrementRxLinkSpeedBandCount(mLastPollRxLinkSpeed, mLastPollFreq);
+ mWifiStatusBuilder.setRssi(mLastPollRssi);
+ mWifiStatusBuilder.setNetworkId(wifiInfo.getNetworkId());
}
/**
@@ -2263,6 +2323,8 @@
mRxThroughputMbpsHistogramAbove2G.increment(rxThroughputKbps / 1000);
}
}
+ mWifiStatusBuilder.setEstimatedTxKbps(txThroughputKbps);
+ mWifiStatusBuilder.setEstimatedRxKbps(rxThroughputKbps);
}
}
@@ -4650,6 +4712,10 @@
mWifiState = wifiState;
mWifiWins = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
mWifiWinsUsabilityScore = (wifiState == WifiMetricsProto.WifiLog.WIFI_ASSOCIATED);
+ if (wifiState == WifiMetricsProto.WifiLog.WIFI_DISCONNECTED
+ || wifiState == WifiMetricsProto.WifiLog.WIFI_DISABLED) {
+ mWifiStatusBuilder = new WifiStatusBuilder();
+ }
}
}
@@ -4754,6 +4820,7 @@
case StaEvent.TYPE_CMD_START_ROAM:
case StaEvent.TYPE_CONNECT_NETWORK:
case StaEvent.TYPE_NETWORK_AGENT_VALID_NETWORK:
+ mWifiStatusBuilder.setValidated(true);
case StaEvent.TYPE_FRAMEWORK_DISCONNECT:
case StaEvent.TYPE_SCORE_BREACH:
case StaEvent.TYPE_MAC_CHANGE:
@@ -6170,6 +6237,13 @@
synchronized (mLock) {
if (networkId == WifiConfiguration.INVALID_NETWORK_ID) return;
mNetworkIdToNominatorId.put(networkId, nominatorId);
+
+ // user connect choice is preventing switcing off from the connected network
+ if (nominatorId
+ == WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE
+ && mWifiStatusBuilder.getNetworkId() == networkId) {
+ mWifiStatusBuilder.setUserChoice(true);
+ }
}
}
diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto
index 5556eff..e108f59 100644
--- a/service/proto/src/metrics.proto
+++ b/service/proto/src/metrics.proto
@@ -3176,6 +3176,29 @@
// Additional information on the target network for the action. This is not applicable and will
// be null for some actions such as EVENT_TOGGLE_WIFI_ON.
optional TargetNetworkInfo target_network_info = 3;
+
+ // Information about the currently connected network.
+ optional WifiStatus wifi_status = 4;
+}
+
+message WifiStatus {
+ // Wifi is connected.
+ optional bool is_connected = 1;
+
+ // Wifi is validated
+ optional bool is_validated = 2;
+
+ // The last observed RSSI
+ optional sint32 last_rssi = 3;
+
+ // Estimated TX
+ optional int32 estimated_tx_kbps = 4;
+
+ // Estimated RX
+ optional int32 estimated_rx_kbps = 5;
+
+ // There is another candidate with better score, but user connect choice is preventing the switch.
+ optional bool is_stuck_due_to_user_connect_choice = 6;
}
// Additional information on a network
diff --git a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
index 50d06b7..91a1037 100644
--- a/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
+++ b/service/tests/wifitests/src/com/android/server/wifi/WifiMetricsTest.java
@@ -2419,6 +2419,41 @@
}
/**
+ * Verify the WifiStatus field in a UserActionEvent is populated correctly.
+ * @throws Exception
+ */
+ @Test
+ public void testLogWifiStatusInUserActionEvent() throws Exception {
+ // setups WifiStatus for information
+ int expectedRssi = -55;
+ int testNetworkId = 1;
+ int expectedTx = 1234;
+ int expectedRx = 2345;
+
+ WifiInfo wifiInfo = mock(WifiInfo.class);
+ when(wifiInfo.getRssi()).thenReturn(expectedRssi);
+ when(wifiInfo.getNetworkId()).thenReturn(testNetworkId);
+ mWifiMetrics.handlePollResult(wifiInfo);
+ mWifiMetrics.incrementThroughputKbpsCount(expectedTx, expectedRx, RSSI_POLL_FREQUENCY);
+ mWifiMetrics.setNominatorForNetwork(testNetworkId,
+ WifiMetricsProto.ConnectionEvent.NOMINATOR_SAVED_USER_CONNECT_CHOICE);
+
+ // generate a user action event and then verify fields
+ int testEventType = WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI;
+ mWifiMetrics.logUserActionEvent(testEventType, testNetworkId);
+ dumpProtoAndDeserialize();
+
+ WifiMetricsProto.UserActionEvent[] userActionEvents = mDecodedProto.userActionEvents;
+ assertEquals(1, userActionEvents.length);
+ assertEquals(WifiMetricsProto.UserActionEvent.EVENT_FORGET_WIFI,
+ userActionEvents[0].eventType);
+ assertEquals(expectedRssi, userActionEvents[0].wifiStatus.lastRssi);
+ assertEquals(expectedTx, userActionEvents[0].wifiStatus.estimatedTxKbps);
+ assertEquals(expectedRx, userActionEvents[0].wifiStatus.estimatedRxKbps);
+ assertTrue(userActionEvents[0].wifiStatus.isStuckDueToUserConnectChoice);
+ }
+
+ /**
* Test the logging of UserActionEvent with invalid network ID
*/
@Test