diff options
author | android-build-team Robot <android-build-team-robot@google.com> | 2020-09-09 23:05:41 +0000 |
---|---|---|
committer | android-build-team Robot <android-build-team-robot@google.com> | 2020-09-09 23:05:41 +0000 |
commit | c006242c5f4156f479f395339012586d46288775 (patch) | |
tree | 642792a27a4a5bcb5cea48fafef86e52a064a2b0 | |
parent | 94f943259578467bc1143e515f9ec190da714cca (diff) | |
parent | 3f749b85c6608dc23b9bfc4a6b8a0392587df7bc (diff) |
Snap for 6823548 from 3f749b85c6608dc23b9bfc4a6b8a0392587df7bc to rvc-qpr1-release
Change-Id: I426cb5ac9d00e994b1a2475e30e62c2b7dd18748
5 files changed, 364 insertions, 32 deletions
diff --git a/service/java/com/android/server/wifi/ClientModeImpl.java b/service/java/com/android/server/wifi/ClientModeImpl.java index 9f4c41f83..e7371a9f1 100644 --- a/service/java/com/android/server/wifi/ClientModeImpl.java +++ b/service/java/com/android/server/wifi/ClientModeImpl.java @@ -812,7 +812,7 @@ public class ClientModeImpl extends StateMachine { mWifiScoreReport = new WifiScoreReport(mWifiInjector.getScoringParams(), mClock, mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, mWifiInjector.getWifiThreadRunner(), mWifiInjector.getDeviceConfigFacade(), - mContext); + mContext, looper, mFacade); mNetworkCapabilitiesFilter = new NetworkCapabilities.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) @@ -3441,6 +3441,7 @@ public class ClientModeImpl extends StateMachine { break; case CMD_INITIALIZE: mWifiNative.initialize(); + mWifiScoreReport.initialize(); break; case CMD_BOOT_COMPLETED: // get other services that we need to manage diff --git a/service/java/com/android/server/wifi/WifiNetworkFactory.java b/service/java/com/android/server/wifi/WifiNetworkFactory.java index 9dc89addc..d1f9fbb1f 100644 --- a/service/java/com/android/server/wifi/WifiNetworkFactory.java +++ b/service/java/com/android/server/wifi/WifiNetworkFactory.java @@ -65,6 +65,7 @@ import com.android.server.wifi.util.WifiPermissionsUtil; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -74,6 +75,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; /** * Network factory to handle trusted wifi network requests. @@ -128,20 +130,23 @@ public class WifiNetworkFactory extends NetworkFactory { private WifiScanner mWifiScanner; private CompanionDeviceManager mCompanionDeviceManager; // Temporary approval set by shell commands. - private String mApprovedApp = null; + @Nullable private String mApprovedApp = null; private int mGenericConnectionReqCount = 0; // Request that is being actively processed. All new requests start out as an "active" request // because we're processing it & handling all the user interactions associated with it. Once we // successfully connect to the network, we transition that request to "connected". - private NetworkRequest mActiveSpecificNetworkRequest; - private WifiNetworkSpecifier mActiveSpecificNetworkRequestSpecifier; + @Nullable private NetworkRequest mActiveSpecificNetworkRequest; + @Nullable private WifiNetworkSpecifier mActiveSpecificNetworkRequestSpecifier; // Request corresponding to the the network that the device is currently connected to. - private NetworkRequest mConnectedSpecificNetworkRequest; - private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier; - private WifiConfiguration mUserSelectedNetwork; + @Nullable private NetworkRequest mConnectedSpecificNetworkRequest; + @Nullable private WifiNetworkSpecifier mConnectedSpecificNetworkRequestSpecifier; + @Nullable private WifiConfiguration mUserSelectedNetwork; private int mUserSelectedNetworkConnectRetryCount; - private List<ScanResult> mActiveMatchedScanResults; + // Map of bssid to latest scan results for all scan results matching a request. Will be + // - null, if there are no active requests. + // - empty, if there are no matching scan results received for the active request. + @Nullable private Map<String, ScanResult> mActiveMatchedScanResults; // Verbose logging flag. private boolean mVerboseLoggingEnabled = false; private boolean mPeriodicScanTimerSet = false; @@ -237,7 +242,10 @@ public class WifiNetworkFactory extends NetworkFactory { Log.v(TAG, "Received " + scanResults.length + " scan results"); } handleScanResults(scanResults); - sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults); + if (mActiveMatchedScanResults != null) { + sendNetworkRequestMatchCallbacksForActiveRequest( + mActiveMatchedScanResults.values()); + } scheduleNextPeriodicScan(); } @@ -432,7 +440,10 @@ public class WifiNetworkFactory extends NetworkFactory { // If we are already in the midst of processing a request, send matching callbacks // immediately on registering the callback. - sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults); + if (mActiveMatchedScanResults != null) { + sendNetworkRequestMatchCallbacksForActiveRequest( + mActiveMatchedScanResults.values()); + } } /** @@ -610,8 +621,11 @@ public class WifiNetworkFactory extends NetworkFactory { if (mVerboseLoggingEnabled) { Log.v(TAG, "Using cached " + cachedScanResults.length + " scan results"); } - handleScanResults(cachedScanResults); - sendNetworkRequestMatchCallbacksForActiveRequest(mActiveMatchedScanResults); + handleScanResults(cachedScanResults); + if (mActiveMatchedScanResults != null) { + sendNetworkRequestMatchCallbacksForActiveRequest( + mActiveMatchedScanResults.values()); + } startPeriodicScans(); } } @@ -1163,8 +1177,8 @@ public class WifiNetworkFactory extends NetworkFactory { } private void sendNetworkRequestMatchCallbacksForActiveRequest( - @Nullable List<ScanResult> matchedScanResults) { - if (matchedScanResults == null || matchedScanResults.isEmpty()) return; + @NonNull Collection<ScanResult> matchedScanResults) { + if (matchedScanResults.isEmpty()) return; if (mRegisteredCallbacks.getNumCallbacks() == 0) { Log.e(TAG, "No callback registered for sending network request matches. " + "Ignoring..."); @@ -1172,7 +1186,7 @@ public class WifiNetworkFactory extends NetworkFactory { } for (INetworkRequestMatchCallback callback : mRegisteredCallbacks.getCallbacks()) { try { - callback.onMatch(matchedScanResults); + callback.onMatch(new ArrayList<>(matchedScanResults)); } catch (RemoteException e) { Log.e(TAG, "Unable to invoke network request match callback " + callback, e); } @@ -1265,6 +1279,7 @@ public class WifiNetworkFactory extends NetworkFactory { if (mActiveSpecificNetworkRequestSpecifier == null || mActiveMatchedScanResults == null) return null; ScanResult selectedScanResult = mActiveMatchedScanResults + .values() .stream() .filter(scanResult -> Objects.equals( ScanResultMatchInfo.fromScanResult(scanResult), @@ -1354,7 +1369,7 @@ public class WifiNetworkFactory extends NetworkFactory { ScanResultMatchInfo fromWifiConfiguration = ScanResultMatchInfo.fromWifiConfiguration(network); - for (ScanResult scanResult : mActiveMatchedScanResults) { + for (ScanResult scanResult : mActiveMatchedScanResults.values()) { ScanResultMatchInfo fromScanResult = ScanResultMatchInfo.fromScanResult(scanResult); if (fromScanResult.equals(fromWifiConfiguration)) { AccessPoint approvedAccessPoint = @@ -1433,7 +1448,19 @@ public class WifiNetworkFactory extends NetworkFactory { mWifiMetrics.incrementNetworkRequestApiMatchSizeHistogram( matchedScanResults.size()); } - mActiveMatchedScanResults = matchedScanResults; + // First set of scan results for this request. + if (mActiveMatchedScanResults == null) mActiveMatchedScanResults = new HashMap<>(); + // Coalesce the new set of scan results with previous scan results received for request. + mActiveMatchedScanResults.putAll(matchedScanResults + .stream() + .collect(Collectors.toMap( + scanResult -> scanResult.BSSID, scanResult -> scanResult))); + // Weed out any stale cached scan results. + long currentTimeInMillis = mClock.getElapsedSinceBootMillis(); + mActiveMatchedScanResults.entrySet().removeIf( + e -> ((currentTimeInMillis - (e.getValue().timestamp / 1000)) + >= CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS)); + } /** diff --git a/service/java/com/android/server/wifi/WifiScoreReport.java b/service/java/com/android/server/wifi/WifiScoreReport.java index 89f0445cb..381be7f2b 100644 --- a/service/java/com/android/server/wifi/WifiScoreReport.java +++ b/service/java/com/android/server/wifi/WifiScoreReport.java @@ -17,16 +17,22 @@ package com.android.server.wifi; import android.content.Context; +import android.database.ContentObserver; import android.net.Network; import android.net.NetworkAgent; +import android.net.Uri; import android.net.wifi.IScoreUpdateObserver; import android.net.wifi.IWifiConnectedNetworkScorer; import android.net.wifi.WifiInfo; import android.net.wifi.nl80211.WifiNl80211Manager; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; +import android.provider.Settings; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; import com.android.wifi.resources.R; import java.io.FileDescriptor; @@ -57,6 +63,15 @@ public class WifiScoreReport { private static final long DURATION_TO_BLOCKLIST_BSSID_AFTER_FIRST_EXITING_MILLIS = 30000; private static final long INVALID_WALL_CLOCK_MILLIS = -1; + /** + * Copy of the settings string. Can't directly use the constant because it is @hide. + * See {@link android.provider.Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED}. + * TODO(b/167709538) remove this hardcoded string and create new API in Wifi mainline. + */ + @VisibleForTesting + public static final String SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED = + "adaptive_connectivity_enabled"; + // Cache of the last score private int mScore = ConnectedScore.WIFI_MAX_SCORE; @@ -78,6 +93,8 @@ public class WifiScoreReport { WifiNative mWifiNative; WifiThreadRunner mWifiThreadRunner; DeviceConfigFacade mDeviceConfigFacade; + Handler mHandler; + FrameworkFacade mFrameworkFacade; /** * Callback proxy. See {@link android.net.wifi.WifiManager.ScoreUpdateObserver}. @@ -200,6 +217,10 @@ public class WifiScoreReport { return; } } + // Stay a notch above the transition score if adaptive connectivity is disabled. + if (!mAdaptiveConnectivityEnabled) { + score = ConnectedScore.WIFI_TRANSITION_SCORE + 1; + } mNetworkAgent.sendNetworkScore(score); } @@ -286,10 +307,50 @@ public class WifiScoreReport { private WifiConnectedNetworkScorerHolder mWifiConnectedNetworkScorerHolder; + /** + * Observer for adaptive connectivity enable settings changes. + * This is enabled by default. Will be toggled off via adb command or a settings + * toggle by the user to disable adaptive connectivity. + */ + private class AdaptiveConnectivityEnabledSettingObserver extends ContentObserver { + AdaptiveConnectivityEnabledSettingObserver(Handler handler) { + super(handler); + } + + @Override + public void onChange(boolean selfChange) { + super.onChange(selfChange); + mAdaptiveConnectivityEnabled = getValue(); + Log.d(TAG, "Adaptive connectivity status changed: " + mAdaptiveConnectivityEnabled); + } + + /** + * Register settings change observer. + */ + public void initialize() { + Uri uri = Settings.Secure.getUriFor(SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED); + if (uri == null) { + Log.e(TAG, "Adaptive connectivity user toggle does not exist in Settings"); + return; + } + mFrameworkFacade.registerContentObserver(mContext, uri, true, this); + mAdaptiveConnectivityEnabled = mAdaptiveConnectivityEnabledSettingObserver.getValue(); + } + + public boolean getValue() { + return mFrameworkFacade.getIntegerSetting( + mContext, SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED, 1) == 1; + } + } + + private final AdaptiveConnectivityEnabledSettingObserver + mAdaptiveConnectivityEnabledSettingObserver; + private boolean mAdaptiveConnectivityEnabled = true; + WifiScoreReport(ScoringParams scoringParams, Clock clock, WifiMetrics wifiMetrics, WifiInfo wifiInfo, WifiNative wifiNative, BssidBlocklistMonitor bssidBlocklistMonitor, WifiThreadRunner wifiThreadRunner, DeviceConfigFacade deviceConfigFacade, - Context context) { + Context context, Looper looper, FrameworkFacade frameworkFacade) { mScoringParams = scoringParams; mClock = clock; mAggressiveConnectedScore = new AggressiveConnectedScore(scoringParams, clock); @@ -301,6 +362,10 @@ public class WifiScoreReport { mWifiThreadRunner = wifiThreadRunner; mDeviceConfigFacade = deviceConfigFacade; mContext = context; + mFrameworkFacade = frameworkFacade; + mHandler = new Handler(looper); + mAdaptiveConnectivityEnabledSettingObserver = + new AdaptiveConnectivityEnabledSettingObserver(mHandler); } /** @@ -463,6 +528,10 @@ public class WifiScoreReport { * @return true to indicate that an IP reachability check is recommended */ public boolean shouldCheckIpLayer() { + // Don't recommend if adaptive connectivity is disabled. + if (!mAdaptiveConnectivityEnabled) { + return false; + } int nud = mScoringParams.getNudKnob(); if (nud == 0) { return false; @@ -703,4 +772,11 @@ public class WifiScoreReport { mWifiConnectedNetworkScorerHolder = null; mWifiMetrics.setIsExternalWifiScorerOn(false); } + + /** + * Initialize WifiScoreReport + */ + public void initialize() { + mAdaptiveConnectivityEnabledSettingObserver.initialize(); + } } diff --git a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java index 5f9e0333e..f6621a698 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiNetworkFactoryTest.java @@ -52,6 +52,7 @@ import android.net.wifi.WifiNetworkSpecifier; import android.net.wifi.WifiScanner; import android.net.wifi.WifiScanner.ScanListener; import android.net.wifi.WifiScanner.ScanSettings; +import android.net.wifi.WifiSsid; import android.os.Binder; import android.os.IBinder; import android.os.Message; @@ -1122,9 +1123,7 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { verify(mWifiMetrics).setNominatorForNetwork(anyInt(), eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); - verify(mClientModeImpl).disconnectCommand(); - verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), - mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); + } /** @@ -1333,6 +1332,134 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { } /** + * Verify handling of user selection to trigger connection to a network when the selected bssid + * is no longer seen in scan results within the cache expiry duration. Ensure we fill up the + * BSSID field. + */ + @Test + public void + testNetworkSpecifierHandleUserSelectionConnectToNetworkMissingBssidInLatest() + throws Exception { + WifiScanner.ScanData[] scanDatas1 = + ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); + setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK, + TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); + // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult. + WifiScanner.ScanData[] scanDatas2 = + ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); + setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK, + TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); + + // Make a specific AP request. + ScanResult matchingScanResult = scanDatas1[0].getResults()[0]; + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); + Pair<MacAddress, MacAddress> bssidPatternMatch = + Pair.create(MacAddress.fromString(matchingScanResult.BSSID), + MacAddress.BROADCAST_ADDRESS); + WifiConfiguration wifiConfiguration = new WifiConfiguration(); + wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; + attachWifiNetworkSpecifierAndAppInfo( + ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, + TEST_PACKAGE_NAME_1); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, + TEST_CALLBACK_IDENTIFIER); + verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( + mNetworkRequestUserSelectionCallback.capture()); + verifyPeriodicScans( + 0L, + new PeriodicScanParams(0, scanDatas1), + new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2)); + + // Now trigger user selection to the network. + mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); + mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; + INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = + mNetworkRequestUserSelectionCallback.getValue(); + assertNotNull(networkRequestUserSelectionCallback); + sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); + mLooper.dispatchAll(); + + // Verify WifiConfiguration params. + validateConnectParams(mSelectedNetwork.SSID, matchingScanResult.BSSID); + verify(mWifiMetrics).setNominatorForNetwork(anyInt(), + eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); + + verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), + mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); + } + + /** + * Verify handling of user selection to trigger connection to a network when the selected bssid + * is no longer seen in scan results beyond the cache expiry duration. Ensure we don't fill up + * the BSSID field. + */ + @Test + public void + testNetworkSpecifierHandleUserSelectionConnectToNetworkStaleMissingBssidInLatest() + throws Exception { + WifiScanner.ScanData[] scanDatas1 = + ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); + setupScanData(scanDatas1, SCAN_RESULT_TYPE_WPA_PSK, + TEST_SSID_1, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); + // Modify the next set of scan results to simulate missing |TEST_SSID_1| ScanResult. + WifiScanner.ScanData[] scanDatas2 = + ScanTestUtil.createScanDatas(new int[][]{ { 2417, 2427, 5180, 5170 }}); + setupScanData(scanDatas2, SCAN_RESULT_TYPE_WPA_PSK, + TEST_SSID_2, TEST_SSID_2, TEST_SSID_3, TEST_SSID_4); + + // Make a specific AP request. + ScanResult matchingScanResult = scanDatas1[0].getResults()[0]; + PatternMatcher ssidPatternMatch = + new PatternMatcher(TEST_SSID_1, PatternMatcher.PATTERN_LITERAL); + Pair<MacAddress, MacAddress> bssidPatternMatch = + Pair.create(MacAddress.fromString(matchingScanResult.BSSID), + MacAddress.BROADCAST_ADDRESS); + WifiConfiguration wifiConfiguration = new WifiConfiguration(); + wifiConfiguration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + wifiConfiguration.preSharedKey = TEST_WPA_PRESHARED_KEY; + attachWifiNetworkSpecifierAndAppInfo( + ssidPatternMatch, bssidPatternMatch, wifiConfiguration, TEST_UID_1, + TEST_PACKAGE_NAME_1); + mWifiNetworkFactory.needNetworkFor(mNetworkRequest, 0); + mWifiNetworkFactory.addCallback(mAppBinder, mNetworkRequestMatchCallback, + TEST_CALLBACK_IDENTIFIER); + verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration( + mNetworkRequestUserSelectionCallback.capture()); + + long nowMs = WifiNetworkFactory.CACHED_SCAN_RESULTS_MAX_AGE_IN_MILLIS + 1; + scanDatas2[0].getResults()[0].timestamp = nowMs; + scanDatas2[0].getResults()[1].timestamp = nowMs; + scanDatas2[0].getResults()[2].timestamp = nowMs; + scanDatas2[0].getResults()[3].timestamp = nowMs; + verifyPeriodicScans( + nowMs, + new PeriodicScanParams(0, scanDatas1), + new PeriodicScanParams(PERIODIC_SCAN_INTERVAL_MS, scanDatas2)); + + // Now trigger user selection to the network. + mSelectedNetwork = ScanResultUtil.createNetworkFromScanResult(matchingScanResult); + mSelectedNetwork.SSID = "\"" + matchingScanResult.SSID + "\""; + INetworkRequestUserSelectionCallback networkRequestUserSelectionCallback = + mNetworkRequestUserSelectionCallback.getValue(); + assertNotNull(networkRequestUserSelectionCallback); + sendUserSelectionSelect(networkRequestUserSelectionCallback, mSelectedNetwork); + mLooper.dispatchAll(); + + // Verify WifiConfiguration params. + validateConnectParams(mSelectedNetwork.SSID, null); + verify(mWifiMetrics).setNominatorForNetwork(anyInt(), + eq(WifiMetricsProto.ConnectionEvent.NOMINATOR_SPECIFIER)); + + verify(mClientModeImpl).disconnectCommand(); + verify(mClientModeImpl).connect(eq(null), eq(TEST_NETWORK_ID_1), any(Binder.class), + mConnectListenerArgumentCaptor.capture(), anyInt(), anyInt()); + } + + /** * Verify handling of user selection to reject the request. */ @Test @@ -2669,13 +2796,33 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { verify(mNetworkRequestMatchCallback, atLeastOnce()).onMatch(anyList()); } + private void verifyPeriodicScans(long...expectedIntervalsInSeconds) { + PeriodicScanParams[] periodicScanParams = + new PeriodicScanParams[expectedIntervalsInSeconds.length]; + for (int i = 0; i < expectedIntervalsInSeconds.length; i++) { + periodicScanParams[i] = + new PeriodicScanParams(expectedIntervalsInSeconds[i], mTestScanDatas); + } + verifyPeriodicScans(0L, periodicScanParams); + } + + private static class PeriodicScanParams { + public final long expectedIntervalInSeconds; + public final WifiScanner.ScanData[] scanDatas; + + PeriodicScanParams(long expectedIntervalInSeconds, WifiScanner.ScanData[] scanDatas) { + this.expectedIntervalInSeconds = expectedIntervalInSeconds; + this.scanDatas = scanDatas; + } + } + // Simulates the periodic scans performed to find a matching network. // a) Start scan // b) Scan results received. // c) Set alarm for next scan at the expected interval. // d) Alarm fires, go to step a) again and repeat. - private void verifyPeriodicScans(long...expectedIntervalsInSeconds) { - when(mClock.getElapsedSinceBootMillis()).thenReturn(0L); + private void verifyPeriodicScans(long nowMs, PeriodicScanParams... scanParams) { + when(mClock.getElapsedSinceBootMillis()).thenReturn(nowMs); OnAlarmListener alarmListener = null; ScanListener scanListener = null; @@ -2685,9 +2832,9 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { // Before we start scans, ensure that we look at the latest cached scan results. mInOrder.verify(mWifiScanner).getSingleScanResults(); - for (int i = 0; i < expectedIntervalsInSeconds.length - 1; i++) { - long expectedCurrentIntervalInMs = expectedIntervalsInSeconds[i]; - long expectedNextIntervalInMs = expectedIntervalsInSeconds[i + 1]; + for (int i = 0; i < scanParams.length - 1; i++) { + long expectedCurrentIntervalInMs = scanParams[i].expectedIntervalInSeconds; + long expectedNextIntervalInMs = scanParams[i + 1].expectedIntervalInSeconds; // First scan is immediately fired, so need for the alarm to fire. if (expectedCurrentIntervalInMs != 0) { @@ -2700,10 +2847,10 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { assertNotNull(scanListener); // Now trigger the scan results callback and verify the alarm set for the next scan. - scanListener.onResults(mTestScanDatas); + scanListener.onResults(scanParams[i].scanDatas); mInOrder.verify(mAlarmManager).set(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), - eq(expectedNextIntervalInMs), any(), + eq(expectedNextIntervalInMs + nowMs), any(), mPeriodicScanListenerArgumentCaptor.capture(), any()); alarmListener = mPeriodicScanListenerArgumentCaptor.getValue(); assertNotNull(alarmListener); @@ -2770,30 +2917,39 @@ public class WifiNetworkFactoryTest extends WifiBaseTest { return ""; } - // Helper method to setup the scan data for verifying the matching algo. private void setupScanData(int scanResultType, String ssid1, String ssid2, String ssid3, String ssid4) { + setupScanData(mTestScanDatas, scanResultType, ssid1, ssid2, ssid3, ssid4); + } + + // Helper method to setup the scan data for verifying the matching algo. + private void setupScanData(WifiScanner.ScanData[] testScanDatas, int scanResultType, + String ssid1, String ssid2, String ssid3, String ssid4) { // 4 scan results, - assertEquals(1, mTestScanDatas.length); - ScanResult[] scanResults = mTestScanDatas[0].getResults(); + assertEquals(1, testScanDatas.length); + ScanResult[] scanResults = testScanDatas[0].getResults(); assertEquals(4, scanResults.length); String caps = getScanResultCapsForType(scanResultType); // Scan results have increasing RSSI. scanResults[0].SSID = ssid1; + scanResults[0].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid1); scanResults[0].BSSID = TEST_BSSID_1; scanResults[0].capabilities = caps; scanResults[0].level = -45; scanResults[1].SSID = ssid2; + scanResults[1].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid2); scanResults[1].BSSID = TEST_BSSID_2; scanResults[1].capabilities = caps; scanResults[1].level = -35; scanResults[2].SSID = ssid3; + scanResults[2].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid3); scanResults[2].BSSID = TEST_BSSID_3; scanResults[2].capabilities = caps; scanResults[2].level = -25; scanResults[3].SSID = ssid4; + scanResults[3].wifiSsid = WifiSsid.createFromAsciiEncoded(ssid4); scanResults[3].BSSID = TEST_BSSID_4; scanResults[3].capabilities = caps; scanResults[3].level = -15; diff --git a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java index 82dbbe941..cf83fbee3 100644 --- a/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java +++ b/tests/wifitests/src/com/android/server/wifi/WifiScoreReportTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.AdditionalAnswers.answerVoid; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.anyLong; @@ -38,6 +39,7 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; +import android.database.ContentObserver; import android.net.ConnectivityManager; import android.net.LinkProperties; import android.net.Network; @@ -50,6 +52,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiInfo; import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.RemoteException; import android.os.test.TestLooper; @@ -60,6 +63,7 @@ import com.android.wifi.resources.R; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -102,6 +106,8 @@ public class WifiScoreReportTest extends WifiBaseTest { @Mock BssidBlocklistMonitor mBssidBlocklistMonitor; @Mock Network mNetwork; @Mock DeviceConfigFacade mDeviceConfigFacade; + @Mock Looper mWifiLooper; + @Mock FrameworkFacade mFrameworkFacade; private TestLooper mLooper; public class WifiConnectedNetworkScorerImpl extends IWifiConnectedNetworkScorer.Stub { @@ -200,10 +206,14 @@ public class WifiScoreReportTest extends WifiBaseTest { mClock = new FakeClock(); mScoringParams = new ScoringParams(); mWifiThreadRunner = new WifiThreadRunner(new Handler(mLooper.getLooper())); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(1); mWifiScoreReport = new WifiScoreReport(mScoringParams, mClock, mWifiMetrics, mWifiInfo, mWifiNative, mBssidBlocklistMonitor, mWifiThreadRunner, - mDeviceConfigFacade, mContext); + mDeviceConfigFacade, mContext, mWifiLooper, mFrameworkFacade); mWifiScoreReport.setNetworkAgent(mNetworkAgent); + mWifiScoreReport.initialize(); when(mDeviceConfigFacade.getMinConfirmationDurationSendLowScoreMs()).thenReturn( DeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS); when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn( @@ -999,4 +1009,66 @@ public class WifiScoreReportTest extends WifiBaseTest { mLooper.dispatchAll(); verify(mNetworkAgent).sendNetworkScore(53); } + + /** + * Verify NUD check is not recommended and the score of 51 is sent to connectivity service + * when adaptive connectivity is disabled for AOSP scorer. + */ + @Test + public void verifyNudCheckAndScoreIfToggleOffForAospScorer() throws Exception { + mWifiInfo.setFrequency(5220); + mWifiInfo.setRssi(-85); + ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); + verify(mFrameworkFacade).registerContentObserver( + any(), any(), eq(true), observer.capture()); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(0); + observer.getValue().onChange(true); + mWifiScoreReport.calculateAndReportScore(); + assertFalse(mWifiScoreReport.shouldCheckIpLayer()); + verify(mNetworkAgent).sendNetworkScore(51); + } + + /** + * Verify NUD check is not recommended and the score of 51 is sent to connectivity service + * when adaptive connectivity is disabled for external Wi-Fi scorer. + */ + @Test + public void verifyNudCheckAndScoreIfToggleOffForExternalScorer() throws Exception { + WifiConnectedNetworkScorerImpl scorerImpl = new WifiConnectedNetworkScorerImpl(); + // Register Client for verification. + mWifiScoreReport.setWifiConnectedNetworkScorer(mAppBinder, scorerImpl); + when(mNetwork.getNetId()).thenReturn(TEST_NETWORK_ID); + mWifiScoreReport.startConnectedNetworkScorer(TEST_NETWORK_ID); + mClock.mStepMillis = 0; + when(mContext.getResources().getBoolean( + R.bool.config_wifiMinConfirmationDurationSendNetworkScoreEnabled)).thenReturn(true); + when(mDeviceConfigFacade.getMinConfirmationDurationSendHighScoreMs()).thenReturn(4000); + + ArgumentCaptor<ContentObserver> observer = ArgumentCaptor.forClass(ContentObserver.class); + verify(mFrameworkFacade).registerContentObserver( + any(), any(), eq(true), observer.capture()); + when(mFrameworkFacade.getIntegerSetting(any(Context.class), + eq(WifiScoreReport.SETTINGS_SECURE_ADAPTIVE_CONNECTIVITY_ENABLED), eq(1))) + .thenReturn(0); + observer.getValue().onChange(true); + + mClock.mWallClockMillis = 10; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 49); + mLooper.dispatchAll(); + verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); + assertFalse(mWifiScoreReport.shouldCheckIpLayer()); + + mClock.mWallClockMillis = 10 + + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS - 1; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 48); + mLooper.dispatchAll(); + verify(mNetworkAgent, never()).sendNetworkScore(anyInt()); + mClock.mWallClockMillis = 10 + + mDeviceConfigFacade.DEFAULT_MIN_CONFIRMATION_DURATION_SEND_LOW_SCORE_MS; + scorerImpl.mScoreUpdateObserver.notifyScoreUpdate(scorerImpl.mSessionId, 47); + mLooper.dispatchAll(); + verify(mNetworkAgent).sendNetworkScore(51); + } } |