diff options
author | Kai Shi <kaishi@google.com> | 2020-02-19 18:43:58 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-02-19 18:43:58 +0000 |
commit | 56471f597e58543ef21c82b10b781b34a6ed5df6 (patch) | |
tree | d757f614d73e7d4812e81efcd111c450b30a9015 /service | |
parent | 29c1c28ab297ed0d629a5440b4c9cfa736923064 (diff) | |
parent | 4a2fb2b8eabb847a25df501e7faa7d5e0ab56ae1 (diff) |
Merge changes Ic92cadbd,I93dc5aa6
* changes:
add ConnectionDurationStats to WifiMetrics
Add isCellularDataAvailable() in WifiDataStall
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/server/wifi/ClientModeImpl.java | 2 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiDataStall.java | 109 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiInjector.java | 4 | ||||
-rw-r--r-- | service/java/com/android/server/wifi/WifiMetrics.java | 62 | ||||
-rw-r--r-- | service/proto/src/metrics.proto | 14 |
5 files changed, 169 insertions, 22 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 0577212a0..6bb0153ce 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -3449,6 +3449,7 @@ public class ClientModeImpl extends StateMachine { mWifiDiagnostics.startLogging(mInterfaceName); mMboOceController.enable(); + mWifiDataStall.enablePhoneStateListener(); /** * Enable bluetooth coexistence scan mode when bluetooth connection is active. @@ -3486,6 +3487,7 @@ public class ClientModeImpl extends StateMachine { mWifiDiagnostics.stopLogging(mInterfaceName); mMboOceController.disable(); + mWifiDataStall.disablePhoneStateListener(); if (mIpClient != null && mIpClient.shutdown()) { // Block to make sure IpClient has really shut down, lest cleanup // race with, say, bringup code over in tethering. diff --git a/service/java/com/android/server/wifi/WifiDataStall.java b/service/java/com/android/server/wifi/WifiDataStall.java index d7f3a61d9..b71aca921 100644 --- a/service/java/com/android/server/wifi/WifiDataStall.java +++ b/service/java/com/android/server/wifi/WifiDataStall.java @@ -18,12 +18,18 @@ package com.android.server.wifi; import static com.android.server.wifi.util.InformationElementUtil.BssLoad.CHANNEL_UTILIZATION_SCALE; +import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager.DeviceMobilityState; +import android.os.Handler; +import android.os.HandlerExecutor; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; import android.util.Log; import com.android.server.wifi.proto.nano.WifiMetricsProto.WifiIsUnusableEvent; import com.android.server.wifi.util.InformationElementUtil.BssLoad; +import com.android.wifi.resources.R; /** * Looks for Wifi data stalls @@ -32,7 +38,7 @@ public class WifiDataStall { private static final String TAG = "WifiDataStall"; private boolean mVerboseLoggingEnabled = false; // Maximum time gap between two WifiLinkLayerStats to trigger a data stall - public static final long MAX_MS_DELTA_FOR_DATA_STALL = 60 * 1000; // 1 minute + public static final int MAX_MS_DELTA_FOR_DATA_STALL = 60 * 1000; // 1 minute // Maximum time that a data stall start time stays valid. public static final long VALIDITY_PERIOD_OF_DATA_STALL_START_MS = 30 * 1000; // 0.5 minutes // Default Tx packet error rate when there is no Tx attempt @@ -42,11 +48,15 @@ public class WifiDataStall { public static final int DEFAULT_CCA_LEVEL_ABOVE_2G = CHANNEL_UTILIZATION_SCALE * 6 / 100; // Minimum time interval in ms between two link layer stats cache updates private static final int LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS = 6 * 1000; + // Maximum time margin between two link layer stats for connection duration update + public static final int MAX_TIME_MARGIN_LAST_TWO_POLLS_MS = 200; - FrameworkFacade mFacade; + private final FrameworkFacade mFacade; private final DeviceConfigFacade mDeviceConfigFacade; private final WifiMetrics mWifiMetrics; + private final Context mContext; private final WifiChannelUtilization mWifiChannelUtilization; + private TelephonyManager mTelephonyManager; private int mLastFrequency = -1; private String mLastBssid; @@ -57,17 +67,60 @@ public class WifiDataStall { private long mLastTxBytes; private long mLastRxBytes; private boolean mIsThroughputSufficient = true; + private boolean mIsCellularDataAvailable = false; + private final PhoneStateListener mPhoneStateListener; + private boolean mPhoneStateListenerEnabled = false; - public WifiDataStall(FrameworkFacade facade, WifiMetrics wifiMetrics, - DeviceConfigFacade deviceConfigFacade, - WifiChannelUtilization wifiChannelUtilization, Clock clock) { + public WifiDataStall(FrameworkFacade facade, WifiMetrics wifiMetrics, Context context, + DeviceConfigFacade deviceConfigFacade, WifiChannelUtilization wifiChannelUtilization, + Clock clock, Handler handler) { mFacade = facade; mDeviceConfigFacade = deviceConfigFacade; mWifiMetrics = wifiMetrics; + mContext = context; mClock = clock; mWifiChannelUtilization = wifiChannelUtilization; mWifiChannelUtilization.init(null); mWifiChannelUtilization.setCacheUpdateIntervalMs(LLSTATS_CACHE_UPDATE_INTERVAL_MIN_MS); + mPhoneStateListener = new PhoneStateListener(new HandlerExecutor(handler)) { + @Override + public void onDataConnectionStateChanged(int state, int networkType) { + if (state == TelephonyManager.DATA_CONNECTED) { + mIsCellularDataAvailable = true; + } else if (state == TelephonyManager.DATA_DISCONNECTED) { + mIsCellularDataAvailable = false; + } else { + Log.e(TAG, "onDataConnectionStateChanged unexpected State: " + state); + return; + } + logd("Cellular Data: " + mIsCellularDataAvailable); + } + }; + } + + /** + * Enable phone state listener + */ + public void enablePhoneStateListener() { + if (mTelephonyManager == null) { + mTelephonyManager = (TelephonyManager) mContext + .getSystemService(Context.TELEPHONY_SERVICE); + } + if (mTelephonyManager != null && !mPhoneStateListenerEnabled) { + mPhoneStateListenerEnabled = true; + mTelephonyManager.listen(mPhoneStateListener, + PhoneStateListener.LISTEN_DATA_CONNECTION_STATE); + } + } + + /** + * Disable phone state listener + */ + public void disablePhoneStateListener() { + if (mTelephonyManager != null && mPhoneStateListenerEnabled) { + mPhoneStateListenerEnabled = false; + mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_NONE); + } } /** @@ -96,8 +149,16 @@ public class WifiDataStall { } /** - * Checks for data stall and throughput sufficiency by looking at link layer stats and L3 - * byte counts + * Check if cellular data is available + * @return true if it is available and false otherwise + */ + public boolean isCellularDataAvailable() { + return mIsCellularDataAvailable; + } + + /** + * Update data stall detection, check throughput sufficiency and report wifi health stat + * with the latest link layer stats * @param oldStats second most recent WifiLinkLayerStats * @param newStats most recent WifiLinkLayerStats * @param wifiInfo WifiInfo for current connection @@ -130,14 +191,14 @@ public class WifiDataStall { + newStats.rxmpdu_vi + newStats.rxmpdu_vo) - (oldStats.rxmpdu_be + oldStats.rxmpdu_bk + oldStats.rxmpdu_vi + oldStats.rxmpdu_vo); - long timeMsDelta = newStats.timeStampInMs - oldStats.timeStampInMs; + int timeDeltaLastTwoPollsMs = (int) (newStats.timeStampInMs - oldStats.timeStampInMs); long totalTxDelta = txSuccessDelta + txRetriesDelta; boolean isTxTrafficHigh = (totalTxDelta * 1000) - > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeMsDelta); + > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeDeltaLastTwoPollsMs); boolean isRxTrafficHigh = (rxSuccessDelta * 1000) - > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeMsDelta); - if (timeMsDelta < 0 + > (mDeviceConfigFacade.getTxPktPerSecondThr() * timeDeltaLastTwoPollsMs); + if (timeDeltaLastTwoPollsMs < 0 || txSuccessDelta < 0 || txRetriesDelta < 0 || txBadDelta < 0 @@ -149,7 +210,7 @@ public class WifiDataStall { } mWifiMetrics.updateWifiIsUnusableLinkLayerStats(txSuccessDelta, txRetriesDelta, - txBadDelta, rxSuccessDelta, timeMsDelta); + txBadDelta, rxSuccessDelta, timeDeltaLastTwoPollsMs); int txLinkSpeedMbps = wifiInfo.getLinkSpeed(); int rxLinkSpeedMbps = wifiInfo.getRxLinkSpeedMbps(); @@ -187,7 +248,15 @@ public class WifiDataStall { } mIsThroughputSufficient = isThroughputSufficientInternal(txTputKbps, rxTputKbps, - isTxTrafficHigh, isRxTrafficHigh, timeMsDelta); + isTxTrafficHigh, isRxTrafficHigh, timeDeltaLastTwoPollsMs); + + int maxTimeDeltaMs = mContext.getResources().getInteger( + R.integer.config_wifiPollRssiIntervalMilliseconds) + + MAX_TIME_MARGIN_LAST_TWO_POLLS_MS; + if (timeDeltaLastTwoPollsMs > 0 && timeDeltaLastTwoPollsMs <= maxTimeDeltaMs) { + mWifiMetrics.incrementConnectionDuration(timeDeltaLastTwoPollsMs, + mIsThroughputSufficient, mIsCellularDataAvailable); + } boolean possibleDataStallTx = isTxTputLow || ccaLevel >= mDeviceConfigFacade.getDataStallCcaLevelThr() @@ -198,15 +267,15 @@ public class WifiDataStall { boolean dataStallTx = isTxTrafficHigh ? possibleDataStallTx : mDataStallTx; boolean dataStallRx = isRxTrafficHigh ? possibleDataStallRx : mDataStallRx; - return detectConsecutiveTwoDataStalls(timeMsDelta, dataStallTx, dataStallRx); + return detectConsecutiveTwoDataStalls(timeDeltaLastTwoPollsMs, dataStallTx, dataStallRx); } // Data stall event is triggered if there are consecutive Tx and/or Rx data stalls // 1st data stall should be preceded by no data stall // Reset mDataStallStartTimeMs to -1 if currently there is no Tx or Rx data stall - private int detectConsecutiveTwoDataStalls(long timeMsDelta, + private int detectConsecutiveTwoDataStalls(int timeDeltaLastTwoPollsMs, boolean dataStallTx, boolean dataStallRx) { - if (timeMsDelta >= MAX_MS_DELTA_FOR_DATA_STALL) { + if (timeDeltaLastTwoPollsMs >= MAX_MS_DELTA_FOR_DATA_STALL) { return WifiIsUnusableEvent.TYPE_UNKNOWN; } @@ -271,18 +340,18 @@ public class WifiDataStall { } private boolean isThroughputSufficientInternal(int l2TxTputKbps, int l2RxTputKbps, - boolean isTxTrafficHigh, boolean isRxTrafficHigh, long timeMsDelta) { + boolean isTxTrafficHigh, boolean isRxTrafficHigh, int timeDeltaLastTwoPollsMs) { long txBytes = mFacade.getTotalTxBytes() - mFacade.getMobileTxBytes(); long rxBytes = mFacade.getTotalRxBytes() - mFacade.getMobileRxBytes(); - if (timeMsDelta > MAX_MS_DELTA_FOR_DATA_STALL + if (timeDeltaLastTwoPollsMs > MAX_MS_DELTA_FOR_DATA_STALL || mLastTxBytes == 0 || mLastRxBytes == 0) { mLastTxBytes = txBytes; mLastRxBytes = rxBytes; return true; } - int l3TxTputKbps = (int) ((txBytes - mLastTxBytes) * 8 / timeMsDelta); - int l3RxTputKbps = (int) ((rxBytes - mLastRxBytes) * 8 / timeMsDelta); + int l3TxTputKbps = (int) ((txBytes - mLastTxBytes) * 8 / timeDeltaLastTwoPollsMs); + int l3RxTputKbps = (int) ((rxBytes - mLastRxBytes) * 8 / timeDeltaLastTwoPollsMs); mLastTxBytes = txBytes; mLastRxBytes = rxBytes; diff --git a/service/java/com/android/server/wifi/WifiInjector.java b/service/java/com/android/server/wifi/WifiInjector.java index e6dcb6368..71f8b7073 100644 --- a/service/java/com/android/server/wifi/WifiInjector.java +++ b/service/java/com/android/server/wifi/WifiInjector.java @@ -317,8 +317,8 @@ public class WifiInjector { mContext, this, mWifiNative, mBuildProperties, new LastMileLogger(this), mClock); mWifiChannelUtilizationConnected = new WifiChannelUtilization(mClock); - mWifiDataStall = new WifiDataStall(mFrameworkFacade, mWifiMetrics, mDeviceConfigFacade, - mWifiChannelUtilizationConnected, mClock); + mWifiDataStall = new WifiDataStall(mFrameworkFacade, mWifiMetrics, mContext, + mDeviceConfigFacade, mWifiChannelUtilizationConnected, mClock, wifiHandler); mWifiMetrics.setWifiDataStall(mWifiDataStall); mLinkProbeManager = new LinkProbeManager(mClock, mWifiNative, mWifiMetrics, mFrameworkFacade, wifiHandler, mContext); diff --git a/service/java/com/android/server/wifi/WifiMetrics.java b/service/java/com/android/server/wifi/WifiMetrics.java index e6c5058be..688857a70 100644 --- a/service/java/com/android/server/wifi/WifiMetrics.java +++ b/service/java/com/android/server/wifi/WifiMetrics.java @@ -439,6 +439,9 @@ public class WifiMetrics { /** Mapping of failure code to the respective passpoint provision failure count. */ private final IntCounter mPasspointProvisionFailureCounts = new IntCounter(); + // Connection duration stats collected while link layer stats reports are on + private final ConnectionDurationStats mConnectionDurationStats = new ConnectionDurationStats(); + @VisibleForTesting static class NetworkSelectionExperimentResults { public static final int MAX_CHOICES = 10; @@ -531,6 +534,49 @@ public class WifiMetrics { } } + class ConnectionDurationStats { + private int mConnectionDurationCellularDataOffMs; + private int mConnectionDurationSufficientThroughputMs; + private int mConnectionDurationInSufficientThroughputMs; + + public WifiMetricsProto.ConnectionDurationStats toProto() { + WifiMetricsProto.ConnectionDurationStats proto = + new WifiMetricsProto.ConnectionDurationStats(); + proto.totalTimeSufficientThroughputMs = mConnectionDurationSufficientThroughputMs; + proto.totalTimeInsufficientThroughputMs = mConnectionDurationInSufficientThroughputMs; + proto.totalTimeCellularDataOffMs = mConnectionDurationCellularDataOffMs; + return proto; + } + public void clear() { + mConnectionDurationCellularDataOffMs = 0; + mConnectionDurationSufficientThroughputMs = 0; + mConnectionDurationInSufficientThroughputMs = 0; + } + public void incrementDurationCount(int timeDeltaLastTwoPollsMs, + boolean isThroughputSufficient, boolean isCellularDataAvailable) { + if (!isCellularDataAvailable) { + mConnectionDurationCellularDataOffMs += timeDeltaLastTwoPollsMs; + } else { + if (isThroughputSufficient) { + mConnectionDurationSufficientThroughputMs += timeDeltaLastTwoPollsMs; + } else { + mConnectionDurationInSufficientThroughputMs += timeDeltaLastTwoPollsMs; + } + } + } + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("connectionDurationSufficientThroughputMs=") + .append(mConnectionDurationSufficientThroughputMs) + .append(", connectionDurationInSufficientThroughputMs=") + .append(mConnectionDurationInSufficientThroughputMs) + .append(", connectionDurationCellularDataOffMs=") + .append(mConnectionDurationCellularDataOffMs); + return sb.toString(); + } + } + /** * Log event, tracking the start time, end time and result of a wireless connection attempt. */ @@ -2897,6 +2943,8 @@ public class WifiMetrics { pw.println("mWifiLogProto.rxLinkSpeedCount5gHigh=" + mRxLinkSpeedCount5gHigh); pw.println("mWifiLogProto.numIpRenewalFailure=" + mWifiLogProto.numIpRenewalFailure); + pw.println("mWifiLogProto.connectionDurationStats=" + + mConnectionDurationStats.toString()); } } } @@ -3458,6 +3506,7 @@ public class WifiMetrics { mWifiLogProto.healthMonitorMetrics = healthMonitorMetrics; } mWifiLogProto.bssidBlocklistStats = mBssidBlocklistStats.toProto(); + mWifiLogProto.connectionDurationStats = mConnectionDurationStats.toProto(); } } @@ -3653,6 +3702,8 @@ public class WifiMetrics { mPasspointProvisionFailureCounts.clear(); mNumProvisionSuccess = 0; mBssidBlocklistStats = new BssidBlocklistStats(); + mConnectionDurationStats.clear(); + } } @@ -5210,4 +5261,15 @@ public class WifiMetrics { mExperimentValues.dataStallCcaLevelThr = ccaLevel; } } + + /** + * Increment connection duration while link layer stats report are on + */ + public void incrementConnectionDuration(int timeDeltaLastTwoPollsMs, + boolean isThroughputSufficient, boolean isCellularDataAvailable) { + synchronized (mLock) { + mConnectionDurationStats.incrementDurationCount(timeDeltaLastTwoPollsMs, + isThroughputSufficient, isCellularDataAvailable); + } + } } diff --git a/service/proto/src/metrics.proto b/service/proto/src/metrics.proto index 8989b3bfa..10f61965f 100644 --- a/service/proto/src/metrics.proto +++ b/service/proto/src/metrics.proto @@ -582,6 +582,9 @@ message WifiLog { // Metrics related to the BssidBlocklistMonitor optional BssidBlocklistStats bssid_blocklist_stats = 159; + + // Connection duration under various health conditions + optional ConnectionDurationStats connection_duration_stats = 160; } // Information that gets logged for every WiFi connection. @@ -2785,3 +2788,14 @@ message HealthMonitorMetrics { // Number of networks with sufficient connection attempts for both current and previous builds optional int32 num_network_sufficient_recent_prev_stats = 5; } + +// Connection duration statistics collected under various health conditions +// while Wifi link layer stats report are on +message ConnectionDurationStats { + // Total time with sufficient Wifi throughput and with cellular data on + optional int32 total_time_sufficient_throughput_ms = 1; + // Total time with insufficient Wifi throughput and with cellular data on + optional int32 total_time_insufficient_throughput_ms = 2; + // Total time with cellular data off + optional int32 total_time_cellular_data_off_ms = 3; +} |