1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wifi; 18 19 import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL; 20 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED; 21 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING; 22 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED; 23 24 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; 25 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; 26 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; 27 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 28 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; 29 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; 30 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; 31 import static com.android.server.wifi.ActiveModeWarden.INTERNAL_REQUESTOR_WS; 32 import static com.android.server.wifi.WifiSettingsConfigStore.WIFI_NATIVE_SUPPORTED_STA_BANDS; 33 34 import static com.google.common.truth.Truth.assertThat; 35 import static com.google.common.truth.Truth.assertWithMessage; 36 37 import static org.junit.Assert.assertEquals; 38 import static org.junit.Assert.assertFalse; 39 import static org.junit.Assert.assertNull; 40 import static org.junit.Assert.assertTrue; 41 import static org.junit.Assert.fail; 42 import static org.junit.Assume.assumeTrue; 43 import static org.mockito.ArgumentMatchers.anyBoolean; 44 import static org.mockito.ArgumentMatchers.argThat; 45 import static org.mockito.Mockito.any; 46 import static org.mockito.Mockito.anyInt; 47 import static org.mockito.Mockito.anyString; 48 import static org.mockito.Mockito.atLeastOnce; 49 import static org.mockito.Mockito.clearInvocations; 50 import static org.mockito.Mockito.doAnswer; 51 import static org.mockito.Mockito.doThrow; 52 import static org.mockito.Mockito.eq; 53 import static org.mockito.Mockito.inOrder; 54 import static org.mockito.Mockito.mock; 55 import static org.mockito.Mockito.mockingDetails; 56 import static org.mockito.Mockito.never; 57 import static org.mockito.Mockito.reset; 58 import static org.mockito.Mockito.times; 59 import static org.mockito.Mockito.verify; 60 import static org.mockito.Mockito.verifyNoMoreInteractions; 61 import static org.mockito.Mockito.verifyZeroInteractions; 62 import static org.mockito.Mockito.when; 63 64 import android.annotation.Nullable; 65 import android.content.BroadcastReceiver; 66 import android.content.Context; 67 import android.content.Intent; 68 import android.content.pm.PackageManager; 69 import android.content.res.Resources; 70 import android.location.LocationManager; 71 import android.net.MacAddress; 72 import android.net.Network; 73 import android.net.wifi.ISubsystemRestartCallback; 74 import android.net.wifi.IWifiConnectedNetworkScorer; 75 import android.net.wifi.IWifiNetworkStateChangedListener; 76 import android.net.wifi.SoftApCapability; 77 import android.net.wifi.SoftApConfiguration; 78 import android.net.wifi.SoftApConfiguration.Builder; 79 import android.net.wifi.SoftApInfo; 80 import android.net.wifi.SoftApState; 81 import android.net.wifi.WifiClient; 82 import android.net.wifi.WifiConfiguration; 83 import android.net.wifi.WifiManager; 84 import android.net.wifi.WifiScanner; 85 import android.os.BatteryStatsManager; 86 import android.os.Build; 87 import android.os.IBinder; 88 import android.os.Process; 89 import android.os.RemoteException; 90 import android.os.UserManager; 91 import android.os.WorkSource; 92 import android.os.test.TestLooper; 93 import android.telephony.TelephonyManager; 94 import android.util.LocalLog; 95 import android.util.Log; 96 97 import androidx.test.filters.SmallTest; 98 99 import com.android.modules.utils.build.SdkLevel; 100 import com.android.server.wifi.ActiveModeManager.ClientConnectivityRole; 101 import com.android.server.wifi.ActiveModeManager.Listener; 102 import com.android.server.wifi.ActiveModeManager.SoftApRole; 103 import com.android.server.wifi.ActiveModeWarden.ExternalClientModeManagerRequestListener; 104 import com.android.server.wifi.util.GeneralUtil.Mutable; 105 import com.android.server.wifi.util.LastCallerInfoManager; 106 import com.android.server.wifi.util.WifiPermissionsUtil; 107 import com.android.wifi.resources.R; 108 109 import org.junit.After; 110 import org.junit.Before; 111 import org.junit.Test; 112 import org.mockito.ArgumentCaptor; 113 import org.mockito.InOrder; 114 import org.mockito.Mock; 115 import org.mockito.Mockito; 116 import org.mockito.MockitoAnnotations; 117 import org.mockito.invocation.InvocationOnMock; 118 import org.mockito.stubbing.Answer; 119 120 import java.io.ByteArrayOutputStream; 121 import java.io.PrintWriter; 122 import java.util.Collection; 123 import java.util.HashMap; 124 import java.util.List; 125 import java.util.Map; 126 import java.util.Set; 127 import java.util.stream.Collectors; 128 129 /** 130 * Unit tests for {@link com.android.server.wifi.ActiveModeWarden}. 131 */ 132 @SmallTest 133 public class ActiveModeWardenTest extends WifiBaseTest { 134 public static final String TAG = "WifiActiveModeWardenTest"; 135 136 private static final String ENABLED_STATE_STRING = "EnabledState"; 137 private static final String DISABLED_STATE_STRING = "DisabledState"; 138 private static final String TEST_SSID_1 = "\"Ssid12345\""; 139 private static final String TEST_SSID_2 = "\"Ssid45678\""; 140 private static final String TEST_SSID_3 = "\"Ssid98765\""; 141 private static final String TEST_BSSID_1 = "01:12:23:34:45:56"; 142 private static final String TEST_BSSID_2 = "10:21:32:43:54:65"; 143 private static final String TEST_BSSID_3 = "11:22:33:44:55:66"; 144 145 private static final String WIFI_IFACE_NAME = "mockWlan"; 146 private static final String WIFI_IFACE_NAME_1 = "mockWlan1"; 147 private static final int TEST_WIFI_RECOVERY_DELAY_MS = 2000; 148 private static final int TEST_AP_FREQUENCY = 2412; 149 private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; 150 private static final int TEST_UID = 435546654; 151 private static final long TEST_FEATURE_SET = 0xAB3DEF; 152 private static final String TEST_PACKAGE = "com.test"; 153 private static final String TEST_COUNTRYCODE = "US"; 154 private static final WorkSource TEST_WORKSOURCE = new WorkSource(TEST_UID, TEST_PACKAGE); 155 private static final WorkSource SETTINGS_WORKSOURCE = 156 new WorkSource(Process.SYSTEM_UID, "system-service"); 157 private static final int TEST_SUPPORTED_BANDS = 15; 158 159 TestLooper mLooper; 160 @Mock WifiInjector mWifiInjector; 161 @Mock Context mContext; 162 @Mock Resources mResources; 163 @Mock WifiNative mWifiNative; 164 @Mock WifiApConfigStore mWifiApConfigStore; 165 @Mock ConcreteClientModeManager mClientModeManager; 166 @Mock SoftApManager mSoftApManager; 167 @Mock DefaultClientModeManager mDefaultClientModeManager; 168 @Mock BatteryStatsManager mBatteryStats; 169 @Mock SelfRecovery mSelfRecovery; 170 @Mock WifiDiagnostics mWifiDiagnostics; 171 @Mock ScanRequestProxy mScanRequestProxy; 172 @Mock FrameworkFacade mFacade; 173 @Mock WifiSettingsStore mSettingsStore; 174 @Mock WifiPermissionsUtil mWifiPermissionsUtil; 175 @Mock SoftApCapability mSoftApCapability; 176 @Mock ActiveModeWarden.ModeChangeCallback mModeChangeCallback; 177 @Mock ActiveModeWarden.PrimaryClientModeManagerChangedCallback mPrimaryChangedCallback; 178 @Mock WifiMetrics mWifiMetrics; 179 @Mock ISubsystemRestartCallback mSubsystemRestartCallback; 180 @Mock ExternalScoreUpdateObserverProxy mExternalScoreUpdateObserverProxy; 181 @Mock DppManager mDppManager; 182 @Mock SarManager mSarManager; 183 @Mock HalDeviceManager mHalDeviceManager; 184 @Mock UserManager mUserManager; 185 @Mock PackageManager mPackageManager; 186 @Mock Network mNetwork; 187 @Mock LocalLog mLocalLog; 188 @Mock WifiSettingsConfigStore mSettingsConfigStore; 189 @Mock LastCallerInfoManager mLastCallerInfoManager; 190 @Mock WifiGlobals mWifiGlobals; 191 @Mock WifiConnectivityManager mWifiConnectivityManager; 192 @Mock WifiConfigManager mWifiConfigManager; 193 194 Listener<ConcreteClientModeManager> mClientListener; 195 Listener<SoftApManager> mSoftApListener; 196 WifiServiceImpl.SoftApCallbackInternal mSoftApManagerCallback; 197 SoftApModeConfiguration mSoftApConfig; 198 @Mock WifiServiceImpl.SoftApCallbackInternal mSoftApStateMachineCallback; 199 @Mock WifiServiceImpl.SoftApCallbackInternal mLohsStateMachineCallback; 200 WifiNative.StatusListener mWifiNativeStatusListener; 201 ActiveModeWarden mActiveModeWarden; 202 private SoftApInfo mTestSoftApInfo; 203 204 final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = 205 ArgumentCaptor.forClass(WifiNative.StatusListener.class); 206 207 private BroadcastReceiver mEmergencyCallbackModeChangedBr; 208 private BroadcastReceiver mEmergencyCallStateChangedBr; 209 210 /** 211 * Set up the test environment. 212 */ 213 @Before setUp()214 public void setUp() throws Exception { 215 Log.d(TAG, "Setting up ..."); 216 217 MockitoAnnotations.initMocks(this); 218 mLooper = new TestLooper(); 219 220 when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); 221 when(mWifiInjector.getSarManager()).thenReturn(mSarManager); 222 when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager); 223 when(mWifiInjector.getUserManager()).thenReturn(mUserManager); 224 when(mWifiInjector.getWifiHandlerLocalLog()).thenReturn(mLocalLog); 225 when(mWifiInjector.getWifiConnectivityManager()).thenReturn(mWifiConnectivityManager); 226 when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager); 227 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 228 when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); 229 when(mContext.getResources()).thenReturn(mResources); 230 when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); 231 232 when(mResources.getString(R.string.wifi_localhotspot_configure_ssid_default)) 233 .thenReturn("AndroidShare"); 234 when(mResources.getInteger(R.integer.config_wifi_framework_recovery_timeout_delay)) 235 .thenReturn(TEST_WIFI_RECOVERY_DELAY_MS); 236 when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) 237 .thenReturn(false); 238 when(mResources.getBoolean(R.bool.config_wifi_turn_off_during_emergency_call)) 239 .thenReturn(true); 240 241 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 242 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 243 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 244 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 245 when(mFacade.getSettingsWorkSource(mContext)).thenReturn(SETTINGS_WORKSOURCE); 246 when(mContext.getPackageManager()).thenReturn(mPackageManager); 247 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(true); 248 when(mWifiInjector.getSettingsConfigStore()).thenReturn(mSettingsConfigStore); 249 when(mWifiInjector.getLastCallerInfoManager()).thenReturn(mLastCallerInfoManager); 250 when(mSettingsConfigStore.get( 251 eq(WIFI_NATIVE_SUPPORTED_STA_BANDS))).thenReturn( 252 TEST_SUPPORTED_BANDS); 253 // Default force that WPA Personal is deprecated since the feature set is opposite to the 254 // API value. 255 when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(true); 256 doAnswer(new Answer<ClientModeManager>() { 257 public ClientModeManager answer(InvocationOnMock invocation) { 258 Object[] args = invocation.getArguments(); 259 mClientListener = (Listener<ConcreteClientModeManager>) args[0]; 260 return mClientModeManager; 261 } 262 }).when(mWifiInjector).makeClientModeManager( 263 any(Listener.class), any(), any(), anyBoolean()); 264 doAnswer(new Answer<SoftApManager>() { 265 public SoftApManager answer(InvocationOnMock invocation) { 266 Object[] args = invocation.getArguments(); 267 mSoftApListener = (Listener<SoftApManager>) args[0]; 268 mSoftApManagerCallback = (WifiServiceImpl.SoftApCallbackInternal) args[1]; 269 mSoftApConfig = (SoftApModeConfiguration) args[2]; 270 return mSoftApManager; 271 } 272 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 273 any(WifiServiceImpl.SoftApCallbackInternal.class), any(), any(), any(), 274 anyBoolean()); 275 when(mWifiNative.initialize()).thenReturn(true); 276 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(true); 277 278 mActiveModeWarden = createActiveModeWarden(); 279 mActiveModeWarden.start(); 280 mLooper.dispatchAll(); 281 282 verify(mWifiMetrics).noteWifiEnabledDuringBoot(false); 283 verify(mWifiGlobals).setD2dStaConcurrencySupported(false); 284 verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); 285 verify(mWifiNative).initialize(); 286 mWifiNativeStatusListener = mStatusListenerCaptor.getValue(); 287 288 mActiveModeWarden.registerSoftApCallback(mSoftApStateMachineCallback); 289 mActiveModeWarden.registerLohsCallback(mLohsStateMachineCallback); 290 mActiveModeWarden.registerModeChangeCallback(mModeChangeCallback); 291 mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback(mPrimaryChangedCallback); 292 when(mSubsystemRestartCallback.asBinder()).thenReturn(Mockito.mock(IBinder.class)); 293 mActiveModeWarden.registerSubsystemRestartCallback(mSubsystemRestartCallback); 294 mTestSoftApInfo = new SoftApInfo(); 295 mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY); 296 mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); 297 298 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 299 ArgumentCaptor.forClass(BroadcastReceiver.class); 300 verify(mContext).registerReceiver( 301 bcastRxCaptor.capture(), 302 argThat(filter -> 303 filter.hasAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED))); 304 mEmergencyCallbackModeChangedBr = bcastRxCaptor.getValue(); 305 306 verify(mContext).registerReceiver( 307 bcastRxCaptor.capture(), 308 argThat(filter -> 309 filter.hasAction(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED))); 310 mEmergencyCallStateChangedBr = bcastRxCaptor.getValue(); 311 } 312 createActiveModeWarden()313 private ActiveModeWarden createActiveModeWarden() { 314 ActiveModeWarden warden = new ActiveModeWarden( 315 mWifiInjector, 316 mLooper.getLooper(), 317 mWifiNative, 318 mDefaultClientModeManager, 319 mBatteryStats, 320 mWifiDiagnostics, 321 mContext, 322 mSettingsStore, 323 mFacade, 324 mWifiPermissionsUtil, 325 mWifiMetrics, 326 mExternalScoreUpdateObserverProxy, 327 mDppManager, 328 mWifiGlobals); 329 // SelfRecovery is created in WifiInjector after ActiveModeWarden, so getSelfRecovery() 330 // returns null when constructing ActiveModeWarden. 331 when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); 332 when(mContext.getPackageManager()).thenReturn(mPackageManager); 333 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn(true); 334 warden.setWifiStateForApiCalls(WIFI_STATE_ENABLED); 335 return warden; 336 } 337 338 /** 339 * Clean up after tests - explicitly set tested object to null. 340 */ 341 @After cleanUp()342 public void cleanUp() throws Exception { 343 mActiveModeWarden = null; 344 mLooper.dispatchAll(); 345 } 346 emergencyCallbackModeChanged(boolean enabled)347 private void emergencyCallbackModeChanged(boolean enabled) { 348 Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 349 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, enabled); 350 mEmergencyCallbackModeChangedBr.onReceive(mContext, intent); 351 } 352 emergencyCallStateChanged(boolean enabled)353 private void emergencyCallStateChanged(boolean enabled) { 354 Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED); 355 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, enabled); 356 mEmergencyCallStateChangedBr.onReceive(mContext, intent); 357 } 358 enterClientModeActiveState()359 private void enterClientModeActiveState() throws Exception { 360 enterClientModeActiveState(false); 361 } 362 363 /** 364 * Helper method to enter the EnabledState and set ClientModeManager in ConnectMode. 365 * @param isClientModeSwitch true if switching from another mode, false if creating a new one 366 */ enterClientModeActiveState(boolean isClientModeSwitch)367 private void enterClientModeActiveState(boolean isClientModeSwitch) throws Exception { 368 enterClientModeActiveState(isClientModeSwitch, TEST_FEATURE_SET); 369 } 370 371 /** 372 * Helper method with tested feature set to enter the EnabledState and set ClientModeManager 373 * in ConnectMode. 374 * 375 * @param isClientModeSwitch true if switching from another mode, false if creating a new one 376 * @param testFeatureSet a customized feature set to test 377 */ enterClientModeActiveState(boolean isClientModeSwitch, long testFeatureSet)378 private void enterClientModeActiveState(boolean isClientModeSwitch, long testFeatureSet) 379 throws Exception { 380 String fromState = mActiveModeWarden.getCurrentMode(); 381 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 382 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 383 mLooper.dispatchAll(); 384 assertNull(mActiveModeWarden.getCurrentNetwork()); 385 386 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 387 when(mClientModeManager.getCurrentNetwork()).thenReturn(mNetwork); 388 when(mWifiNative.getSupportedFeatureSet(WIFI_IFACE_NAME)).thenReturn(testFeatureSet); 389 // ClientModeManager starts in SCAN_ONLY role. 390 mClientListener.onRoleChanged(mClientModeManager); 391 mLooper.dispatchAll(); 392 393 assertInEnabledState(); 394 if (!isClientModeSwitch) { 395 verify(mWifiInjector).makeClientModeManager( 396 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 397 } else { 398 verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY, SETTINGS_WORKSOURCE); 399 } 400 verify(mScanRequestProxy, times(1)).enableScanning(true, true); 401 if (fromState.equals(DISABLED_STATE_STRING)) { 402 verify(mBatteryStats).reportWifiOn(); 403 } 404 for (int i = 0; i < 3; i++) { 405 mActiveModeWarden.updateClientScanModeAfterCountryCodeUpdate(TEST_COUNTRYCODE); 406 } 407 verify(mClientModeManager, atLeastOnce()).getInterfaceName(); 408 verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(WIFI_IFACE_NAME); 409 assertEquals(testFeatureSet, mActiveModeWarden.getSupportedFeatureSet()); 410 verify(mScanRequestProxy, times(4)).enableScanning(true, true); 411 assertEquals(mClientModeManager, mActiveModeWarden.getPrimaryClientModeManager()); 412 verify(mModeChangeCallback).onActiveModeManagerRoleChanged(mClientModeManager); 413 assertEquals(mNetwork, mActiveModeWarden.getCurrentNetwork()); 414 } 415 enterScanOnlyModeActiveState()416 private void enterScanOnlyModeActiveState() throws Exception { 417 enterScanOnlyModeActiveState(false); 418 } 419 420 /** 421 * Helper method to enter the EnabledState and set ClientModeManager in ScanOnlyMode. 422 */ enterScanOnlyModeActiveState(boolean isClientModeSwitch)423 private void enterScanOnlyModeActiveState(boolean isClientModeSwitch) throws Exception { 424 String fromState = mActiveModeWarden.getCurrentMode(); 425 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 426 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 427 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 428 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 429 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 430 mLooper.dispatchAll(); 431 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 432 when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); 433 when(mClientModeManager.getCurrentNetwork()).thenReturn(null); 434 when(mWifiNative.getSupportedFeatureSet(null)).thenReturn(TEST_FEATURE_SET); 435 if (!isClientModeSwitch) { 436 mClientListener.onStarted(mClientModeManager); 437 mLooper.dispatchAll(); 438 verify(mWifiInjector).makeClientModeManager( 439 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 440 verify(mModeChangeCallback).onActiveModeManagerAdded(mClientModeManager); 441 } else { 442 mClientListener.onRoleChanged(mClientModeManager); 443 mLooper.dispatchAll(); 444 verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY, INTERNAL_REQUESTOR_WS); 445 // If switching from client mode back to scan only mode, role change would have been 446 // called once before when transitioning from scan only mode to client mode. 447 // Verify that it was called again. 448 verify(mModeChangeCallback, times(2)) 449 .onActiveModeManagerRoleChanged(mClientModeManager); 450 verify(mWifiNative, atLeastOnce()).getSupportedFeatureSet(null); 451 assertEquals(TEST_FEATURE_SET, mActiveModeWarden.getSupportedFeatureSet()); 452 } 453 assertInEnabledState(); 454 verify(mScanRequestProxy).enableScanning(true, false); 455 if (fromState.equals(DISABLED_STATE_STRING)) { 456 verify(mBatteryStats).reportWifiOn(); 457 } 458 verify(mBatteryStats).reportWifiState(BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); 459 assertEquals(mClientModeManager, mActiveModeWarden.getScanOnlyClientModeManager()); 460 } 461 enterSoftApActiveMode()462 private void enterSoftApActiveMode() throws Exception { 463 enterSoftApActiveMode( 464 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 465 mSoftApCapability, TEST_COUNTRYCODE, null)); 466 } 467 468 private int mTimesCreatedSoftApManager = 1; 469 470 /** 471 * Helper method to activate SoftApManager. 472 * 473 * This method puts the test object into the correct state and verifies steps along the way. 474 */ enterSoftApActiveMode(SoftApModeConfiguration softApConfig)475 private void enterSoftApActiveMode(SoftApModeConfiguration softApConfig) throws Exception { 476 String fromState = mActiveModeWarden.getCurrentMode(); 477 SoftApRole softApRole = softApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED 478 ? ROLE_SOFTAP_TETHERED : ROLE_SOFTAP_LOCAL_ONLY; 479 mActiveModeWarden.startSoftAp(softApConfig, TEST_WORKSOURCE); 480 mLooper.dispatchAll(); 481 when(mSoftApManager.getRole()).thenReturn(softApRole); 482 when(mSoftApManager.getSoftApModeConfiguration()).thenReturn(softApConfig); 483 mSoftApListener.onStarted(mSoftApManager); 484 mLooper.dispatchAll(); 485 486 assertInEnabledState(); 487 assertThat(softApConfig).isEqualTo(mSoftApConfig); 488 verify(mWifiInjector, times(mTimesCreatedSoftApManager)).makeSoftApManager( 489 any(), any(), any(), eq(TEST_WORKSOURCE), eq(softApRole), anyBoolean()); 490 mTimesCreatedSoftApManager++; 491 if (fromState.equals(DISABLED_STATE_STRING)) { 492 verify(mBatteryStats).reportWifiOn(); 493 } 494 if (softApRole == ROLE_SOFTAP_TETHERED) { 495 assertEquals(mSoftApManager, mActiveModeWarden.getTetheredSoftApManager()); 496 assertNull(mActiveModeWarden.getLocalOnlySoftApManager()); 497 } else { 498 assertEquals(mSoftApManager, mActiveModeWarden.getLocalOnlySoftApManager()); 499 assertNull(mActiveModeWarden.getTetheredSoftApManager()); 500 } 501 verify(mModeChangeCallback).onActiveModeManagerAdded(mSoftApManager); 502 } 503 enterStaDisabledMode(boolean isSoftApModeManagerActive)504 private void enterStaDisabledMode(boolean isSoftApModeManagerActive) { 505 String fromState = mActiveModeWarden.getCurrentMode(); 506 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 507 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 508 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 509 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 510 mLooper.dispatchAll(); 511 if (mClientListener != null) { 512 mClientListener.onStopped(mClientModeManager); 513 mLooper.dispatchAll(); 514 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 515 } 516 517 if (isSoftApModeManagerActive) { 518 assertInEnabledState(); 519 } else { 520 assertInDisabledState(); 521 } 522 if (fromState.equals(ENABLED_STATE_STRING)) { 523 verify(mScanRequestProxy).enableScanning(false, false); 524 } 525 // Ensure we return the default client mode manager when wifi is off. 526 assertEquals(mDefaultClientModeManager, mActiveModeWarden.getPrimaryClientModeManager()); 527 } 528 shutdownWifi()529 private void shutdownWifi() { 530 mActiveModeWarden.recoveryDisableWifi(); 531 mLooper.dispatchAll(); 532 } 533 assertInEnabledState()534 private void assertInEnabledState() { 535 assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(ENABLED_STATE_STRING); 536 } 537 assertInDisabledState()538 private void assertInDisabledState() { 539 assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(DISABLED_STATE_STRING); 540 } 541 542 /** 543 * Emergency mode is a sub-mode within each main state (ScanOnly, Client, DisabledState). 544 */ assertInEmergencyMode()545 private void assertInEmergencyMode() { 546 assertThat(mActiveModeWarden.isInEmergencyMode()).isTrue(); 547 } 548 assertNotInEmergencyMode()549 private void assertNotInEmergencyMode() { 550 assertThat(mActiveModeWarden.isInEmergencyMode()).isFalse(); 551 } 552 553 /** 554 * Counts the number of times a void method was called on a mock. 555 * 556 * Void methods cannot be passed to Mockito.mockingDetails(). Thus we have to use method name 557 * matching instead. 558 */ getMethodInvocationCount(Object mock, String methodName)559 private static int getMethodInvocationCount(Object mock, String methodName) { 560 long count = mockingDetails(mock).getInvocations() 561 .stream() 562 .filter(invocation -> methodName.equals(invocation.getMethod().getName())) 563 .count(); 564 return (int) count; 565 } 566 567 /** 568 * Counts the number of times a non-void method was called on a mock. 569 * 570 * For non-void methods, can pass the method call literal directly: 571 * e.g. getMethodInvocationCount(mock.method()); 572 */ getMethodInvocationCount(Object mockMethod)573 private static int getMethodInvocationCount(Object mockMethod) { 574 return mockingDetails(mockMethod).getInvocations().size(); 575 } 576 assertWifiShutDown(Runnable r)577 private void assertWifiShutDown(Runnable r) { 578 assertWifiShutDown(r, 1); 579 } 580 581 /** 582 * Asserts that the runnable r has shut down wifi properly. 583 * 584 * @param r runnable that will shut down wifi 585 * @param times expected number of times that <code>r</code> shut down wifi 586 */ assertWifiShutDown(Runnable r, int times)587 private void assertWifiShutDown(Runnable r, int times) { 588 // take snapshot of ActiveModeManagers 589 Collection<ActiveModeManager> activeModeManagers = 590 mActiveModeWarden.getActiveModeManagers(); 591 592 List<Integer> expectedStopInvocationCounts = activeModeManagers 593 .stream() 594 .map(manager -> getMethodInvocationCount(manager, "stop") + times) 595 .collect(Collectors.toList()); 596 597 r.run(); 598 599 List<Integer> actualStopInvocationCounts = activeModeManagers 600 .stream() 601 .map(manager -> getMethodInvocationCount(manager, "stop")) 602 .collect(Collectors.toList()); 603 604 String managerNames = activeModeManagers.stream() 605 .map(manager -> manager.getClass().getCanonicalName()) 606 .collect(Collectors.joining(", ", "[", "]")); 607 608 assertWithMessage(managerNames).that(actualStopInvocationCounts) 609 .isEqualTo(expectedStopInvocationCounts); 610 } 611 assertEnteredEcmMode(Runnable r)612 private void assertEnteredEcmMode(Runnable r) { 613 assertEnteredEcmMode(r, 1); 614 } 615 616 /** 617 * Asserts that the runnable r has entered ECM state properly. 618 * 619 * @param r runnable that will enter ECM 620 * @param times expected number of times that <code>r</code> shut down wifi 621 */ assertEnteredEcmMode(Runnable r, int times)622 private void assertEnteredEcmMode(Runnable r, int times) { 623 // take snapshot of ActiveModeManagers 624 Collection<ActiveModeManager> activeModeManagers = 625 mActiveModeWarden.getActiveModeManagers(); 626 627 boolean disableWifiInEcm = mFacade.getConfigWiFiDisableInECBM(mContext); 628 629 List<Integer> expectedStopInvocationCounts = activeModeManagers.stream() 630 .map(manager -> { 631 int initialCount = getMethodInvocationCount(manager, "stop"); 632 // carrier config enabled, all mode managers should have been shut down once 633 int count = disableWifiInEcm ? initialCount + times : initialCount; 634 if (manager instanceof SoftApManager) { 635 // expect SoftApManager.close() to be called 636 return count + times; 637 } else { 638 // don't expect other Managers close() to be called 639 return count; 640 } 641 }) 642 .collect(Collectors.toList()); 643 644 r.run(); 645 646 assertInEmergencyMode(); 647 648 List<Integer> actualStopInvocationCounts = activeModeManagers.stream() 649 .map(manager -> getMethodInvocationCount(manager, "stop")) 650 .collect(Collectors.toList()); 651 652 String managerNames = activeModeManagers.stream() 653 .map(manager -> manager.getClass().getCanonicalName()) 654 .collect(Collectors.joining(", ", "[", "]")); 655 656 assertWithMessage(managerNames).that(actualStopInvocationCounts) 657 .isEqualTo(expectedStopInvocationCounts); 658 } 659 660 /** Test that after starting up, ActiveModeWarden is in the DisabledState State. */ 661 @Test testDisabledStateAtStartup()662 public void testDisabledStateAtStartup() { 663 assertInDisabledState(); 664 } 665 666 /** 667 * Test that ActiveModeWarden properly enters the EnabledState (in ScanOnlyMode) from the 668 * DisabledState state. 669 */ 670 @Test testEnterScanOnlyModeFromDisabled()671 public void testEnterScanOnlyModeFromDisabled() throws Exception { 672 enterScanOnlyModeActiveState(); 673 } 674 675 /** 676 * Test that ActiveModeWarden enables hidden network scanning in scan-only-mode 677 * if configured to do. 678 */ 679 @Test testScanOnlyModeScanHiddenNetworks()680 public void testScanOnlyModeScanHiddenNetworks() throws Exception { 681 when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) 682 .thenReturn(true); 683 684 mActiveModeWarden = createActiveModeWarden(); 685 mActiveModeWarden.start(); 686 mLooper.dispatchAll(); 687 688 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 689 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 690 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 691 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 692 mLooper.dispatchAll(); 693 mClientListener.onStarted(mClientModeManager); 694 mLooper.dispatchAll(); 695 696 assertInEnabledState(); 697 verify(mWifiInjector).makeClientModeManager( 698 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 699 verify(mScanRequestProxy).enableScanning(true, true); 700 } 701 702 /** 703 * Test that ActiveModeWarden properly starts the SoftApManager from the 704 * DisabledState state. 705 */ 706 @Test testEnterSoftApModeFromDisabled()707 public void testEnterSoftApModeFromDisabled() throws Exception { 708 enterSoftApActiveMode(); 709 } 710 711 /** 712 * Test that ActiveModeWarden properly starts the SoftApManager from another state. 713 */ 714 @Test testEnterSoftApModeFromDifferentState()715 public void testEnterSoftApModeFromDifferentState() throws Exception { 716 enterClientModeActiveState(); 717 assertInEnabledState(); 718 reset(mBatteryStats, mScanRequestProxy); 719 enterSoftApActiveMode(); 720 } 721 722 /** 723 * Test that we can disable wifi fully from the EnabledState (in ScanOnlyMode). 724 */ 725 @Test testDisableWifiFromScanOnlyModeActiveState()726 public void testDisableWifiFromScanOnlyModeActiveState() throws Exception { 727 enterScanOnlyModeActiveState(); 728 729 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 730 mActiveModeWarden.scanAlwaysModeChanged(); 731 mLooper.dispatchAll(); 732 mClientListener.onStopped(mClientModeManager); 733 mLooper.dispatchAll(); 734 735 verify(mClientModeManager).stop(); 736 verify(mBatteryStats).reportWifiOff(); 737 assertInDisabledState(); 738 } 739 740 /** 741 * Test that we can disable wifi when SoftApManager is active and not impact softap. 742 */ 743 @Test testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp()744 public void testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp() throws Exception { 745 enterSoftApActiveMode(); 746 enterScanOnlyModeActiveState(); 747 748 reset(mDefaultClientModeManager); 749 enterStaDisabledMode(true); 750 verify(mSoftApManager, never()).stop(); 751 verify(mBatteryStats, never()).reportWifiOff(); 752 } 753 754 /** 755 * Test that we can switch from the EnabledState (in ScanOnlyMode) to another mode. 756 */ 757 @Test testSwitchModeWhenScanOnlyModeActiveState()758 public void testSwitchModeWhenScanOnlyModeActiveState() throws Exception { 759 enterScanOnlyModeActiveState(); 760 761 reset(mBatteryStats, mScanRequestProxy); 762 enterClientModeActiveState(true); 763 mLooper.dispatchAll(); 764 } 765 766 /** 767 * Test that we can switch from the EnabledState (in ConnectMode) to another mode. 768 */ 769 @Test testSwitchModeWhenConnectModeActiveState()770 public void testSwitchModeWhenConnectModeActiveState() throws Exception { 771 enterClientModeActiveState(); 772 773 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 774 775 reset(mBatteryStats, mScanRequestProxy); 776 enterScanOnlyModeActiveState(true); 777 mLooper.dispatchAll(); 778 779 verify(mPrimaryChangedCallback).onChange(mClientModeManager, null); 780 } 781 782 /** 783 * Test that wifi toggle switching the primary to scan only mode will also remove the additional 784 * CMMs. 785 */ 786 @Test testSwitchFromConnectModeToScanOnlyModeRemovesAdditionalCMMs()787 public void testSwitchFromConnectModeToScanOnlyModeRemovesAdditionalCMMs() throws Exception { 788 // Ensure that we can create more client ifaces. 789 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 790 when(mResources.getBoolean( 791 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 792 .thenReturn(true); 793 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 794 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 795 796 // request for an additional CMM 797 ConcreteClientModeManager additionalClientModeManager = 798 mock(ConcreteClientModeManager.class); 799 ExternalClientModeManagerRequestListener externalRequestListener = mock( 800 ExternalClientModeManagerRequestListener.class); 801 Listener<ConcreteClientModeManager> additionalClientListener = 802 requestAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_TRANSIENT, 803 additionalClientModeManager, externalRequestListener, TEST_SSID_2, 804 TEST_BSSID_2); 805 806 // Verify that there exists both a primary and a secondary transient CMM 807 List<ClientModeManager> currentCMMs = mActiveModeWarden.getClientModeManagers(); 808 assertEquals(2, currentCMMs.size()); 809 assertTrue(currentCMMs.stream().anyMatch(cmm -> cmm.getRole() == ROLE_CLIENT_PRIMARY)); 810 assertTrue(currentCMMs.stream().anyMatch( 811 cmm -> cmm.getRole() == ROLE_CLIENT_SECONDARY_TRANSIENT)); 812 verify(mWifiConnectivityManager, never()).resetOnWifiDisable(); 813 814 InOrder inOrder = inOrder(additionalClientModeManager, mClientModeManager); 815 // disable wifi and switch primary CMM to scan only mode 816 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 817 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 818 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 819 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 820 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 821 mLooper.dispatchAll(); 822 823 // Verify that we first stop the additional CMM and then switch the primary to scan only 824 // mode 825 inOrder.verify(additionalClientModeManager).stop(); 826 inOrder.verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY, INTERNAL_REQUESTOR_WS); 827 verify(mWifiConnectivityManager).resetOnWifiDisable(); 828 } 829 830 /** 831 * Verify that when there are only secondary CMMs available, the user toggling wifi on will 832 * create a new primary CMM. 833 */ 834 @Test testToggleWifiWithOnlySecondaryCmmsCreatesPrimaryOrScanOnlyCmm()835 public void testToggleWifiWithOnlySecondaryCmmsCreatesPrimaryOrScanOnlyCmm() throws Exception { 836 enterClientModeActiveState(); 837 verify(mWifiInjector, times(1)).makeClientModeManager( 838 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 839 840 // toggling wifi on again should be no-op when primary is already available 841 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 842 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 843 mLooper.dispatchAll(); 844 845 verify(mWifiInjector, times(1)).makeClientModeManager( 846 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 847 848 // Make the primary CMM change to local only secondary role. 849 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 850 mClientListener.onRoleChanged(mClientModeManager); 851 mLooper.dispatchAll(); 852 853 // Verify that there only exists the ROLE_CLIENT_LOCAL_ONLY CMM. 854 List<ClientModeManager> currentCMMs = mActiveModeWarden.getClientModeManagers(); 855 assertEquals(1, currentCMMs.size()); 856 assertTrue(currentCMMs.get(0).getRole() == ROLE_CLIENT_LOCAL_ONLY); 857 858 // verify wifi toggling on should recreate the primary CMM 859 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 860 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 861 mLooper.dispatchAll(); 862 863 verify(mWifiInjector, times(2)).makeClientModeManager( 864 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 865 } 866 867 @Test testPrimaryNotCreatedTwice()868 public void testPrimaryNotCreatedTwice() throws Exception { 869 enterClientModeActiveState(); 870 verify(mWifiInjector).makeClientModeManager( 871 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 872 873 // toggling wifi on again should be no-op when primary is already available 874 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 875 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 876 mLooper.dispatchAll(); 877 878 verify(mWifiInjector).makeClientModeManager( 879 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 880 881 // Simulate the primary not fully started by making the role null and targetRole primary. 882 when(mClientModeManager.getRole()).thenReturn(null); 883 when(mClientModeManager.getTargetRole()).thenReturn(ROLE_CLIENT_PRIMARY); 884 885 // Verify that there is no primary, but there is a CMM with targetRole as primary. 886 List<ClientModeManager> currentCMMs = mActiveModeWarden.getClientModeManagers(); 887 assertEquals(1, currentCMMs.size()); 888 ConcreteClientModeManager currentCmm = (ConcreteClientModeManager) currentCMMs.get(0); 889 assertTrue(currentCmm.getRole() == null); 890 assertTrue(currentCmm.getTargetRole() == ROLE_CLIENT_PRIMARY); 891 892 // verify wifi toggling on should not create another primary CMM. 893 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 894 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 895 mLooper.dispatchAll(); 896 897 verify(mWifiInjector).makeClientModeManager( 898 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 899 } 900 901 /** 902 * Reentering EnabledState should be a NOP. 903 */ 904 @Test testReenterClientModeActiveStateIsNop()905 public void testReenterClientModeActiveStateIsNop() throws Exception { 906 enterClientModeActiveState(); 907 verify(mWifiInjector, times(1)).makeClientModeManager( 908 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 909 910 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 911 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 912 mLooper.dispatchAll(); 913 // Should not start again. 914 verify(mWifiInjector, times(1)).makeClientModeManager( 915 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 916 } 917 918 /** 919 * Test that we can switch mode when SoftApManager is active to another mode. 920 */ 921 @Test testSwitchModeWhenSoftApActiveMode()922 public void testSwitchModeWhenSoftApActiveMode() throws Exception { 923 enterSoftApActiveMode(); 924 925 reset(mWifiNative); 926 927 enterClientModeActiveState(); 928 mLooper.dispatchAll(); 929 verify(mSoftApManager, never()).stop(); 930 assertInEnabledState(); 931 verify(mWifiNative, never()).teardownAllInterfaces(); 932 } 933 934 /** 935 * Test that we activate SoftApModeManager if we are already in DisabledState due to 936 * a failure. 937 */ 938 @Test testEnterSoftApModeActiveWhenAlreadyInSoftApMode()939 public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception { 940 enterSoftApActiveMode(); 941 // now inject failure through the SoftApManager.Listener 942 mSoftApListener.onStartFailure(mSoftApManager); 943 mLooper.dispatchAll(); 944 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 945 assertInDisabledState(); 946 // clear the first call to start SoftApManager 947 reset(mSoftApManager, mBatteryStats, mModeChangeCallback); 948 949 enterSoftApActiveMode(); 950 } 951 952 /** 953 * Test that we return to the DisabledState after a failure is reported when in the 954 * EnabledState. 955 */ 956 @Test testScanOnlyModeFailureWhenActive()957 public void testScanOnlyModeFailureWhenActive() throws Exception { 958 enterScanOnlyModeActiveState(); 959 // now inject a failure through the ScanOnlyModeManager.Listener 960 mClientListener.onStartFailure(mClientModeManager); 961 mLooper.dispatchAll(); 962 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 963 assertInDisabledState(); 964 verify(mBatteryStats).reportWifiOff(); 965 } 966 967 /** 968 * Test that we return to the DisabledState after a failure is reported when 969 * SoftApManager is active. 970 */ 971 @Test testSoftApFailureWhenActive()972 public void testSoftApFailureWhenActive() throws Exception { 973 enterSoftApActiveMode(); 974 // now inject failure through the SoftApManager.Listener 975 mSoftApListener.onStartFailure(mSoftApManager); 976 mLooper.dispatchAll(); 977 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 978 verify(mBatteryStats).reportWifiOff(); 979 } 980 981 /** 982 * Test that we return to the DisabledState after the ClientModeManager running in ScanOnlyMode 983 * is stopped. 984 */ 985 @Test testScanOnlyModeDisabledWhenActive()986 public void testScanOnlyModeDisabledWhenActive() throws Exception { 987 enterScanOnlyModeActiveState(); 988 989 // now inject the stop message through the ScanOnlyModeManager.Listener 990 mClientListener.onStopped(mClientModeManager); 991 mLooper.dispatchAll(); 992 993 assertInDisabledState(); 994 verify(mBatteryStats).reportWifiOff(); 995 } 996 997 /** 998 * Test that we return to the DisabledState after the SoftApManager is stopped. 999 */ 1000 @Test testSoftApDisabledWhenActive()1001 public void testSoftApDisabledWhenActive() throws Exception { 1002 enterSoftApActiveMode(); 1003 reset(mWifiNative); 1004 // now inject failure through the SoftApManager.Listener 1005 mSoftApListener.onStartFailure(mSoftApManager); 1006 mLooper.dispatchAll(); 1007 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1008 verify(mBatteryStats).reportWifiOff(); 1009 verifyNoMoreInteractions(mWifiNative); 1010 } 1011 1012 /** 1013 * Verifies that SoftApStateChanged event is being passed from SoftApManager to WifiServiceImpl 1014 */ 1015 @Test callsWifiServiceCallbackOnSoftApStateChanged()1016 public void callsWifiServiceCallbackOnSoftApStateChanged() throws Exception { 1017 enterSoftApActiveMode(); 1018 1019 mSoftApListener.onStarted(mSoftApManager); 1020 SoftApState softApState = new SoftApState( 1021 WifiManager.WIFI_AP_STATE_ENABLED, 0, null, null); 1022 mSoftApManagerCallback.onStateChanged(softApState); 1023 mLooper.dispatchAll(); 1024 1025 verify(mSoftApStateMachineCallback).onStateChanged(softApState); 1026 } 1027 1028 /** 1029 * Verifies that SoftApStateChanged event isn't passed to WifiServiceImpl for LOHS, 1030 * so the state change for LOHS doesn't affect Wifi Tethering indication. 1031 */ 1032 @Test doesntCallWifiServiceCallbackOnLOHSStateChanged()1033 public void doesntCallWifiServiceCallbackOnLOHSStateChanged() throws Exception { 1034 enterSoftApActiveMode(new SoftApModeConfiguration( 1035 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, mSoftApCapability, TEST_COUNTRYCODE, 1036 null)); 1037 1038 mSoftApListener.onStarted(mSoftApManager); 1039 SoftApState softApState = new SoftApState( 1040 WifiManager.WIFI_AP_STATE_ENABLED, 0, null, null); 1041 mSoftApManagerCallback.onStateChanged(softApState); 1042 mLooper.dispatchAll(); 1043 1044 verify(mSoftApStateMachineCallback, never()).onStateChanged(softApState); 1045 verify(mSoftApStateMachineCallback, never()).onConnectedClientsOrInfoChanged(any(), 1046 any(), anyBoolean()); 1047 } 1048 1049 /** 1050 * Verifies that ConnectedClientsOrInfoChanged event is being passed from SoftApManager 1051 * to WifiServiceImpl 1052 */ 1053 @Test callsWifiServiceCallbackOnSoftApConnectedClientsChanged()1054 public void callsWifiServiceCallbackOnSoftApConnectedClientsChanged() throws Exception { 1055 final Map<String, List<WifiClient>> testClients = new HashMap(); 1056 final Map<String, SoftApInfo> testInfos = new HashMap(); 1057 enterSoftApActiveMode(); 1058 mSoftApManagerCallback.onConnectedClientsOrInfoChanged(testInfos, testClients, false); 1059 mLooper.dispatchAll(); 1060 1061 verify(mSoftApStateMachineCallback).onConnectedClientsOrInfoChanged( 1062 testInfos, testClients, false); 1063 } 1064 1065 /** 1066 * Test that we remain in the active state when we get a state change update that scan mode is 1067 * active. 1068 */ 1069 @Test testScanOnlyModeStaysActiveOnEnabledUpdate()1070 public void testScanOnlyModeStaysActiveOnEnabledUpdate() throws Exception { 1071 enterScanOnlyModeActiveState(); 1072 // now inject success through the Listener 1073 mClientListener.onStarted(mClientModeManager); 1074 mLooper.dispatchAll(); 1075 assertInEnabledState(); 1076 verify(mClientModeManager, never()).stop(); 1077 } 1078 1079 /** 1080 * Test that a config passed in to the call to enterSoftApMode is used to create the new 1081 * SoftApManager. 1082 */ 1083 @Test testConfigIsPassedToWifiInjector()1084 public void testConfigIsPassedToWifiInjector() throws Exception { 1085 Builder configBuilder = new SoftApConfiguration.Builder(); 1086 configBuilder.setSsid("ThisIsAConfig"); 1087 SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( 1088 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mSoftApCapability, 1089 TEST_COUNTRYCODE, null); 1090 enterSoftApActiveMode(softApConfig); 1091 } 1092 1093 /** 1094 * Test that when enterSoftAPMode is called with a null config, we pass a null config to 1095 * WifiInjector.makeSoftApManager. 1096 * 1097 * Passing a null config to SoftApManager indicates that the default config should be used. 1098 */ 1099 @Test testNullConfigIsPassedToWifiInjector()1100 public void testNullConfigIsPassedToWifiInjector() throws Exception { 1101 enterSoftApActiveMode(); 1102 } 1103 1104 /** 1105 * Test that two calls to switch to SoftAPMode in succession ends up with the correct config. 1106 * 1107 * Expectation: we should end up in SoftAPMode state configured with the second config. 1108 */ 1109 @Test testStartSoftApModeTwiceWithTwoConfigs()1110 public void testStartSoftApModeTwiceWithTwoConfigs() throws Exception { 1111 when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); 1112 Builder configBuilder1 = new SoftApConfiguration.Builder(); 1113 configBuilder1.setSsid("ThisIsAConfig"); 1114 SoftApModeConfiguration softApConfig1 = new SoftApModeConfiguration( 1115 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder1.build(), 1116 mSoftApCapability, TEST_COUNTRYCODE, null); 1117 Builder configBuilder2 = new SoftApConfiguration.Builder(); 1118 configBuilder2.setSsid("ThisIsASecondConfig"); 1119 SoftApModeConfiguration softApConfig2 = new SoftApModeConfiguration( 1120 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder2.build(), 1121 mSoftApCapability, TEST_COUNTRYCODE, null); 1122 1123 doAnswer(new Answer<SoftApManager>() { 1124 public SoftApManager answer(InvocationOnMock invocation) { 1125 Object[] args = invocation.getArguments(); 1126 mSoftApListener = (Listener<SoftApManager>) args[0]; 1127 return mSoftApManager; 1128 } 1129 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1130 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(softApConfig1), any(), any(), 1131 anyBoolean()); 1132 // make a second softap manager 1133 SoftApManager softapManager = mock(SoftApManager.class); 1134 Mutable<Listener<SoftApManager>> softApListener = 1135 new Mutable<>(); 1136 doAnswer(new Answer<SoftApManager>() { 1137 public SoftApManager answer(InvocationOnMock invocation) { 1138 Object[] args = invocation.getArguments(); 1139 softApListener.value = (Listener<SoftApManager>) args[0]; 1140 return softapManager; 1141 } 1142 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1143 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(softApConfig2), any(), any(), 1144 anyBoolean()); 1145 1146 mActiveModeWarden.startSoftAp(softApConfig1, TEST_WORKSOURCE); 1147 mLooper.dispatchAll(); 1148 mSoftApListener.onStarted(mSoftApManager); 1149 mActiveModeWarden.startSoftAp(softApConfig2, TEST_WORKSOURCE); 1150 mLooper.dispatchAll(); 1151 softApListener.value.onStarted(softapManager); 1152 1153 verify(mWifiInjector, times(2)).makeSoftApManager( 1154 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1155 verify(mBatteryStats).reportWifiOn(); 1156 } 1157 1158 /** 1159 * Test that we safely disable wifi if it is already disabled. 1160 */ 1161 @Test disableWifiWhenAlreadyOff()1162 public void disableWifiWhenAlreadyOff() throws Exception { 1163 enterStaDisabledMode(false); 1164 verify(mWifiNative).getSupportedFeatureSet(null); 1165 verify(mWifiNative).isStaApConcurrencySupported(); 1166 verify(mWifiNative).isStaStaConcurrencySupported(); 1167 verify(mWifiNative).isP2pStaConcurrencySupported(); 1168 verify(mWifiNative).isNanStaConcurrencySupported(); 1169 verifyZeroInteractions(mWifiNative); 1170 } 1171 1172 /** 1173 * Trigger recovery and a bug report if we see a native failure 1174 * while the device is not shutting down 1175 */ 1176 @Test handleWifiNativeFailureDeviceNotShuttingDown()1177 public void handleWifiNativeFailureDeviceNotShuttingDown() throws Exception { 1178 mWifiNativeStatusListener.onStatusChanged(false); 1179 mLooper.dispatchAll(); 1180 verify(mWifiDiagnostics).triggerBugReportDataCapture( 1181 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 1182 verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 1183 verify(mWifiConfigManager).writeDataToStorage(); 1184 } 1185 1186 /** 1187 * Verify the device shutting down doesn't trigger recovery or bug report. 1188 */ 1189 @Test handleWifiNativeFailureDeviceShuttingDown()1190 public void handleWifiNativeFailureDeviceShuttingDown() throws Exception { 1191 mActiveModeWarden.notifyShuttingDown(); 1192 mWifiNativeStatusListener.onStatusChanged(false); 1193 mLooper.dispatchAll(); 1194 verify(mWifiDiagnostics, never()).triggerBugReportDataCapture( 1195 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 1196 verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 1197 verify(mWifiConfigManager, never()).writeDataToStorage(); 1198 } 1199 1200 /** 1201 * Verify an onStatusChanged callback with "true" does not trigger recovery. 1202 */ 1203 @Test handleWifiNativeStatusReady()1204 public void handleWifiNativeStatusReady() throws Exception { 1205 mWifiNativeStatusListener.onStatusChanged(true); 1206 mLooper.dispatchAll(); 1207 verify(mWifiDiagnostics, never()).triggerBugReportDataCapture( 1208 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 1209 verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 1210 verify(mWifiConfigManager, never()).writeDataToStorage(); 1211 } 1212 1213 /** 1214 * Verify that mode stop is safe even if the underlying Client mode exited already. 1215 */ 1216 @Test shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed()1217 public void shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed() throws Exception { 1218 enterClientModeActiveState(); 1219 1220 mClientListener.onStopped(mClientModeManager); 1221 mLooper.dispatchAll(); 1222 1223 shutdownWifi(); 1224 1225 assertInDisabledState(); 1226 } 1227 1228 /** 1229 * Verify that an interface destruction callback is safe after already having been stopped. 1230 */ 1231 @Test onDestroyedCallbackDoesNotCrashWhenClientModeAlreadyStopped()1232 public void onDestroyedCallbackDoesNotCrashWhenClientModeAlreadyStopped() throws Exception { 1233 enterClientModeActiveState(); 1234 1235 shutdownWifi(); 1236 1237 mClientListener.onStopped(mClientModeManager); 1238 mLooper.dispatchAll(); 1239 1240 assertInDisabledState(); 1241 } 1242 1243 /** 1244 * Verify that mode stop is safe even if the underlying softap mode exited already. 1245 */ 1246 @Test shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed()1247 public void shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed() throws Exception { 1248 enterSoftApActiveMode(); 1249 1250 mSoftApListener.onStopped(mSoftApManager); 1251 mLooper.dispatchAll(); 1252 SoftApState softApState = new SoftApState( 1253 WifiManager.WIFI_AP_STATE_DISABLED, 0, null, null); 1254 mSoftApManagerCallback.onStateChanged(softApState); 1255 mLooper.dispatchAll(); 1256 1257 shutdownWifi(); 1258 1259 verify(mSoftApStateMachineCallback).onStateChanged(softApState); 1260 } 1261 1262 /** 1263 * Verify that an interface destruction callback is safe after already having been stopped. 1264 */ 1265 @Test onDestroyedCallbackDoesNotCrashWhenSoftApModeAlreadyStopped()1266 public void onDestroyedCallbackDoesNotCrashWhenSoftApModeAlreadyStopped() throws Exception { 1267 enterSoftApActiveMode(); 1268 1269 shutdownWifi(); 1270 1271 mSoftApListener.onStopped(mSoftApManager); 1272 SoftApState softApState = new SoftApState( 1273 WifiManager.WIFI_AP_STATE_DISABLED, 0, null, null); 1274 mSoftApManagerCallback.onStateChanged(softApState); 1275 mLooper.dispatchAll(); 1276 1277 verify(mSoftApStateMachineCallback).onStateChanged(softApState); 1278 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1279 } 1280 1281 /** 1282 * Verify that we do not crash when calling dump and wifi is fully disabled. 1283 */ 1284 @Test dumpWhenWifiFullyOffDoesNotCrash()1285 public void dumpWhenWifiFullyOffDoesNotCrash() throws Exception { 1286 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1287 PrintWriter writer = new PrintWriter(stream); 1288 mActiveModeWarden.dump(null, writer, null); 1289 } 1290 1291 /** 1292 * Verify that we trigger dump on active mode managers. 1293 */ 1294 @Test dumpCallsActiveModeManagers()1295 public void dumpCallsActiveModeManagers() throws Exception { 1296 enterSoftApActiveMode(); 1297 enterClientModeActiveState(); 1298 1299 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1300 PrintWriter writer = new PrintWriter(stream); 1301 mActiveModeWarden.dump(null, writer, null); 1302 1303 verify(mSoftApManager).dump(null, writer, null); 1304 verify(mClientModeManager).dump(null, writer, null); 1305 } 1306 1307 /** 1308 * Verify that stopping tethering doesn't stop LOHS. 1309 */ 1310 @Test testStopTetheringButNotLOHS()1311 public void testStopTetheringButNotLOHS() throws Exception { 1312 // prepare WiFi configurations 1313 when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); 1314 SoftApModeConfiguration tetherConfig = 1315 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 1316 mSoftApCapability, TEST_COUNTRYCODE, null); 1317 SoftApConfiguration lohsConfigWC = mWifiApConfigStore.generateLocalOnlyHotspotConfig( 1318 mContext, null, mSoftApCapability); 1319 SoftApModeConfiguration lohsConfig = 1320 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, lohsConfigWC, 1321 mSoftApCapability, TEST_COUNTRYCODE, null); 1322 1323 // mock SoftAPManagers 1324 when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); 1325 doAnswer(new Answer<SoftApManager>() { 1326 public SoftApManager answer(InvocationOnMock invocation) { 1327 Object[] args = invocation.getArguments(); 1328 mSoftApListener = (Listener<SoftApManager>) args[0]; 1329 return mSoftApManager; 1330 } 1331 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1332 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(tetherConfig), 1333 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1334 // make a second softap manager 1335 SoftApManager lohsSoftapManager = mock(SoftApManager.class); 1336 when(lohsSoftapManager.getRole()).thenReturn(ROLE_SOFTAP_LOCAL_ONLY); 1337 Mutable<Listener<SoftApManager>> lohsSoftApListener = new Mutable<>(); 1338 doAnswer(new Answer<SoftApManager>() { 1339 public SoftApManager answer(InvocationOnMock invocation) { 1340 Object[] args = invocation.getArguments(); 1341 lohsSoftApListener.value = (Listener<SoftApManager>) args[0]; 1342 return lohsSoftapManager; 1343 } 1344 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1345 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(lohsConfig), 1346 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_LOCAL_ONLY), anyBoolean()); 1347 1348 // enable tethering and LOHS 1349 mActiveModeWarden.startSoftAp(tetherConfig, TEST_WORKSOURCE); 1350 mLooper.dispatchAll(); 1351 mSoftApListener.onStarted(mSoftApManager); 1352 mActiveModeWarden.startSoftAp(lohsConfig, TEST_WORKSOURCE); 1353 mLooper.dispatchAll(); 1354 lohsSoftApListener.value.onStarted(lohsSoftapManager); 1355 verify(mWifiInjector).makeSoftApManager(any(Listener.class), 1356 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(tetherConfig), 1357 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1358 verify(mWifiInjector).makeSoftApManager(any(Listener.class), 1359 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(lohsConfig), 1360 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_LOCAL_ONLY), anyBoolean()); 1361 verify(mBatteryStats).reportWifiOn(); 1362 1363 // disable tethering 1364 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_TETHERED); 1365 mLooper.dispatchAll(); 1366 verify(mSoftApManager).stop(); 1367 verify(lohsSoftapManager, never()).stop(); 1368 1369 mSoftApListener.onStopped(mSoftApManager); 1370 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1371 } 1372 1373 /** 1374 * Verify that toggling wifi from disabled starts client mode. 1375 */ 1376 @Test enableWifi()1377 public void enableWifi() throws Exception { 1378 assertInDisabledState(); 1379 1380 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1381 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1382 mLooper.dispatchAll(); 1383 1384 verify(mWifiInjector).makeClientModeManager( 1385 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), 1386 anyBoolean()); 1387 mClientListener.onStarted(mClientModeManager); 1388 mLooper.dispatchAll(); 1389 1390 // always set primary, even with single STA 1391 verify(mWifiNative).setMultiStaPrimaryConnection(WIFI_IFACE_NAME); 1392 1393 assertInEnabledState(); 1394 } 1395 1396 /** 1397 * Test verifying that we can enter scan mode when the scan mode changes 1398 */ 1399 @Test enableScanMode()1400 public void enableScanMode() throws Exception { 1401 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1402 mActiveModeWarden.scanAlwaysModeChanged(); 1403 mLooper.dispatchAll(); 1404 verify(mWifiInjector).makeClientModeManager( 1405 any(), eq(new WorkSource(Process.WIFI_UID)), eq(ROLE_CLIENT_SCAN_ONLY), 1406 anyBoolean()); 1407 assertInEnabledState(); 1408 verify(mClientModeManager, never()).stop(); 1409 } 1410 1411 /** 1412 * Test verifying that we ignore scan enable event when wifi is already enabled. 1413 */ 1414 @Test ignoreEnableScanModeWhenWifiEnabled()1415 public void ignoreEnableScanModeWhenWifiEnabled() throws Exception { 1416 // Turn on WIFI 1417 assertInDisabledState(); 1418 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1419 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1420 mLooper.dispatchAll(); 1421 mClientListener.onStarted(mClientModeManager); 1422 mLooper.dispatchAll(); 1423 assertInEnabledState(); 1424 1425 // Now toggle scan only change, should be ignored. We should send a role change 1426 // again with PRIMARY & the cached requestorWs. 1427 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1428 mActiveModeWarden.scanAlwaysModeChanged(); 1429 mLooper.dispatchAll(); 1430 verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE); 1431 assertInEnabledState(); 1432 verify(mClientModeManager, never()).stop(); 1433 } 1434 1435 /** 1436 * Verify that if scanning is enabled at startup, we enter scan mode 1437 */ 1438 @Test testEnterScanModeAtStartWhenSet()1439 public void testEnterScanModeAtStartWhenSet() throws Exception { 1440 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1441 1442 mActiveModeWarden = createActiveModeWarden(); 1443 mActiveModeWarden.start(); 1444 mLooper.dispatchAll(); 1445 1446 assertInEnabledState(); 1447 } 1448 1449 /** 1450 * Verify that if Wifi is enabled at startup, we enter client mode 1451 */ 1452 @Test testEnterClientModeAtStartWhenSet()1453 public void testEnterClientModeAtStartWhenSet() throws Exception { 1454 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1455 1456 mActiveModeWarden = createActiveModeWarden(); 1457 mActiveModeWarden.start(); 1458 mLooper.dispatchAll(); 1459 1460 verify(mWifiMetrics).noteWifiEnabledDuringBoot(true); 1461 1462 assertInEnabledState(); 1463 1464 verify(mWifiInjector) 1465 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1466 } 1467 1468 /** 1469 * Do not enter scan mode if location mode disabled. 1470 */ 1471 @Test testDoesNotEnterScanModeWhenLocationModeDisabled()1472 public void testDoesNotEnterScanModeWhenLocationModeDisabled() throws Exception { 1473 // Start a new WifiController with wifi disabled 1474 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 1475 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1476 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1477 1478 mActiveModeWarden = createActiveModeWarden(); 1479 mActiveModeWarden.start(); 1480 mLooper.dispatchAll(); 1481 1482 assertInDisabledState(); 1483 1484 // toggling scan always available is not sufficient for scan mode 1485 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1486 mActiveModeWarden.scanAlwaysModeChanged(); 1487 mLooper.dispatchAll(); 1488 1489 assertInDisabledState(); 1490 } 1491 1492 /** 1493 * Only enter scan mode if location mode enabled 1494 */ 1495 @Test testEnterScanModeWhenLocationModeEnabled()1496 public void testEnterScanModeWhenLocationModeEnabled() throws Exception { 1497 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1498 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1499 1500 reset(mContext); 1501 when(mContext.getResources()).thenReturn(mResources); 1502 mActiveModeWarden = createActiveModeWarden(); 1503 mActiveModeWarden.start(); 1504 mLooper.dispatchAll(); 1505 1506 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 1507 ArgumentCaptor.forClass(BroadcastReceiver.class); 1508 verify(mContext).registerReceiver( 1509 bcastRxCaptor.capture(), 1510 argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); 1511 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 1512 1513 assertInDisabledState(); 1514 1515 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 1516 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); 1517 broadcastReceiver.onReceive(mContext, intent); 1518 mLooper.dispatchAll(); 1519 1520 assertInEnabledState(); 1521 } 1522 1523 /** 1524 * Do not change Wi-Fi state when airplane mode changes if 1525 * DISALLOW_CHANGE_WIFI_STATE user restriction is set. 1526 */ 1527 @Test testWifiStateUnaffectedByAirplaneMode()1528 public void testWifiStateUnaffectedByAirplaneMode() throws Exception { 1529 assumeTrue(SdkLevel.isAtLeastT()); 1530 when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CHANGE_WIFI_STATE), 1531 any())).thenReturn(true); 1532 when(mSettingsStore.updateAirplaneModeTracker()).thenReturn(true); 1533 1534 reset(mContext); 1535 when(mContext.getResources()).thenReturn(mResources); 1536 mActiveModeWarden = createActiveModeWarden(); 1537 mActiveModeWarden.start(); 1538 mLooper.dispatchAll(); 1539 1540 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 1541 ArgumentCaptor.forClass(BroadcastReceiver.class); 1542 verify(mContext).registerReceiver( 1543 bcastRxCaptor.capture(), 1544 argThat(filter -> filter.hasAction(Intent.ACTION_AIRPLANE_MODE_CHANGED))); 1545 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 1546 1547 Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED); 1548 broadcastReceiver.onReceive(mContext, intent); 1549 mLooper.dispatchAll(); 1550 1551 verify(mSettingsStore, never()).handleAirplaneModeToggled(); 1552 1553 when(mUserManager.hasUserRestrictionForUser(eq(UserManager.DISALLOW_CHANGE_WIFI_STATE), 1554 any())).thenReturn(false); 1555 broadcastReceiver.onReceive(mContext, intent); 1556 mLooper.dispatchAll(); 1557 1558 verify(mSettingsStore).handleAirplaneModeToggled(); 1559 verify(mLastCallerInfoManager, never()).put(eq(WifiManager.API_WIFI_ENABLED), 1560 anyInt(), anyInt(), anyInt(), any(), anyBoolean()); 1561 } 1562 1563 /** 1564 * Wi-Fi remains on when airplane mode changes if airplane mode enhancement is enabled. 1565 */ 1566 @Test testWifiRemainsOnAirplaneModeEnhancement()1567 public void testWifiRemainsOnAirplaneModeEnhancement() throws Exception { 1568 enterClientModeActiveState(); 1569 assertInEnabledState(); 1570 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 1571 1572 // Wi-Fi remains on when APM enhancement enabled 1573 assertWifiShutDown(() -> { 1574 when(mSettingsStore.shouldWifiRemainEnabledWhenApmEnabled()).thenReturn(true); 1575 mActiveModeWarden.airplaneModeToggled(); 1576 mLooper.dispatchAll(); 1577 }, 0); 1578 verify(mLastCallerInfoManager, never()).put(eq(WifiManager.API_WIFI_ENABLED), 1579 anyInt(), anyInt(), anyInt(), any(), anyBoolean()); 1580 1581 // Wi-Fi shuts down when APM enhancement disabled 1582 assertWifiShutDown(() -> { 1583 when(mSettingsStore.shouldWifiRemainEnabledWhenApmEnabled()).thenReturn(false); 1584 mActiveModeWarden.airplaneModeToggled(); 1585 mLooper.dispatchAll(); 1586 }); 1587 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), anyInt(), 1588 anyInt(), eq("android_apm"), eq(false)); 1589 } 1590 1591 /** Wi-Fi state is restored properly when SoftAp is enabled during airplane mode. */ 1592 @Test testWifiStateRestoredWhenSoftApEnabledDuringApm()1593 public void testWifiStateRestoredWhenSoftApEnabledDuringApm() throws Exception { 1594 enableWifi(); 1595 assertInEnabledState(); 1596 1597 // enabling airplane mode shuts down wifi 1598 assertWifiShutDown( 1599 () -> { 1600 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 1601 mActiveModeWarden.airplaneModeToggled(); 1602 mLooper.dispatchAll(); 1603 }); 1604 verify(mLastCallerInfoManager) 1605 .put( 1606 eq(WifiManager.API_WIFI_ENABLED), 1607 anyInt(), 1608 anyInt(), 1609 anyInt(), 1610 eq("android_apm"), 1611 eq(false)); 1612 mClientListener.onStopped(mClientModeManager); 1613 mLooper.dispatchAll(); 1614 1615 // start SoftAp 1616 mActiveModeWarden.startSoftAp( 1617 new SoftApModeConfiguration( 1618 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, 1619 null, 1620 mSoftApCapability, 1621 TEST_COUNTRYCODE, 1622 null), 1623 TEST_WORKSOURCE); 1624 mLooper.dispatchAll(); 1625 1626 // disabling airplane mode enables wifi 1627 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 1628 mActiveModeWarden.airplaneModeToggled(); 1629 mLooper.dispatchAll(); 1630 verify(mLastCallerInfoManager) 1631 .put( 1632 eq(WifiManager.API_WIFI_ENABLED), 1633 anyInt(), 1634 anyInt(), 1635 anyInt(), 1636 eq("android_apm"), 1637 eq(true)); 1638 } 1639 1640 /** 1641 * Disabling location mode when in scan mode will disable wifi 1642 */ 1643 @Test testExitScanModeWhenLocationModeDisabled()1644 public void testExitScanModeWhenLocationModeDisabled() throws Exception { 1645 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1646 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 1647 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 1648 1649 reset(mContext); 1650 when(mContext.getResources()).thenReturn(mResources); 1651 mActiveModeWarden = createActiveModeWarden(); 1652 mActiveModeWarden.start(); 1653 mLooper.dispatchAll(); 1654 mClientListener.onStarted(mClientModeManager); 1655 mLooper.dispatchAll(); 1656 1657 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 1658 ArgumentCaptor.forClass(BroadcastReceiver.class); 1659 verify(mContext).registerReceiver( 1660 bcastRxCaptor.capture(), 1661 argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); 1662 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 1663 1664 assertInEnabledState(); 1665 1666 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1667 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); 1668 broadcastReceiver.onReceive(mContext, intent); 1669 mLooper.dispatchAll(); 1670 1671 mClientListener.onStopped(mClientModeManager); 1672 mLooper.dispatchAll(); 1673 1674 assertInDisabledState(); 1675 } 1676 1677 /** 1678 * When in Client mode, make sure ECM triggers wifi shutdown. 1679 */ 1680 @Test testEcmOnFromClientMode()1681 public void testEcmOnFromClientMode() throws Exception { 1682 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1683 enableWifi(); 1684 1685 // Test with WifiDisableInECBM turned on: 1686 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1687 1688 assertWifiShutDown(() -> { 1689 // test ecm changed 1690 emergencyCallbackModeChanged(true); 1691 mLooper.dispatchAll(); 1692 }); 1693 } 1694 1695 /** 1696 * ECM disabling messages, when in client mode (not expected) do not trigger state changes. 1697 */ 1698 @Test testEcmOffInClientMode()1699 public void testEcmOffInClientMode() throws Exception { 1700 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1701 enableWifi(); 1702 1703 // Test with WifiDisableInECBM turned off 1704 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1705 1706 assertEnteredEcmMode(() -> { 1707 // test ecm changed 1708 emergencyCallbackModeChanged(true); 1709 mLooper.dispatchAll(); 1710 }); 1711 } 1712 1713 /** 1714 * When ECM activates and we are in client mode, disabling ECM should return us to client mode. 1715 */ 1716 @Test testEcmDisabledReturnsToClientMode()1717 public void testEcmDisabledReturnsToClientMode() throws Exception { 1718 enableWifi(); 1719 assertInEnabledState(); 1720 1721 // Test with WifiDisableInECBM turned on: 1722 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1723 1724 assertWifiShutDown(() -> { 1725 // test ecm changed 1726 emergencyCallbackModeChanged(true); 1727 mLooper.dispatchAll(); 1728 }); 1729 1730 // test ecm changed 1731 emergencyCallbackModeChanged(false); 1732 mLooper.dispatchAll(); 1733 1734 assertInEnabledState(); 1735 } 1736 1737 /** 1738 * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed 1739 * update. 1740 */ 1741 @Test testEcmOnFromScanMode()1742 public void testEcmOnFromScanMode() throws Exception { 1743 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1744 mActiveModeWarden.scanAlwaysModeChanged(); 1745 mLooper.dispatchAll(); 1746 1747 mClientListener.onStarted(mClientModeManager); 1748 mLooper.dispatchAll(); 1749 1750 assertInEnabledState(); 1751 1752 // Test with WifiDisableInECBM turned on: 1753 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1754 1755 assertWifiShutDown(() -> { 1756 // test ecm changed 1757 emergencyCallbackModeChanged(true); 1758 mLooper.dispatchAll(); 1759 }); 1760 } 1761 1762 /** 1763 * When Ecm mode is disabled, we should not shut down scan mode if we get an emergency mode 1764 * changed update, but we should turn off soft AP 1765 */ 1766 @Test testEcmOffInScanMode()1767 public void testEcmOffInScanMode() throws Exception { 1768 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1769 mActiveModeWarden.scanAlwaysModeChanged(); 1770 mLooper.dispatchAll(); 1771 1772 assertInEnabledState(); 1773 1774 // Test with WifiDisableInECBM turned off: 1775 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1776 1777 assertEnteredEcmMode(() -> { 1778 // test ecm changed 1779 emergencyCallbackModeChanged(true); 1780 mLooper.dispatchAll(); 1781 }); 1782 } 1783 1784 /** 1785 * When ECM is disabled, we should return to scan mode 1786 */ 1787 @Test testEcmDisabledReturnsToScanMode()1788 public void testEcmDisabledReturnsToScanMode() throws Exception { 1789 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1790 mActiveModeWarden.scanAlwaysModeChanged(); 1791 mLooper.dispatchAll(); 1792 1793 assertInEnabledState(); 1794 1795 // Test with WifiDisableInECBM turned on: 1796 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1797 1798 assertWifiShutDown(() -> { 1799 // test ecm changed 1800 emergencyCallbackModeChanged(true); 1801 mLooper.dispatchAll(); 1802 }); 1803 1804 // test ecm changed 1805 emergencyCallbackModeChanged(false); 1806 mLooper.dispatchAll(); 1807 1808 assertInEnabledState(); 1809 } 1810 1811 /** 1812 * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed 1813 * update. 1814 */ 1815 @Test testEcmOnFromSoftApMode()1816 public void testEcmOnFromSoftApMode() throws Exception { 1817 enterSoftApActiveMode(); 1818 1819 // Test with WifiDisableInECBM turned on: 1820 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1821 1822 assertEnteredEcmMode(() -> { 1823 // test ecm changed 1824 emergencyCallbackModeChanged(true); 1825 mLooper.dispatchAll(); 1826 }); 1827 } 1828 1829 /** 1830 * When Ecm mode is disabled, we should shut down softap mode if we get an emergency mode 1831 * changed update 1832 */ 1833 @Test testEcmOffInSoftApMode()1834 public void testEcmOffInSoftApMode() throws Exception { 1835 enterSoftApActiveMode(); 1836 1837 // Test with WifiDisableInECBM turned off: 1838 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1839 1840 // test ecm changed 1841 emergencyCallbackModeChanged(true); 1842 mLooper.dispatchAll(); 1843 1844 verify(mSoftApManager).stop(); 1845 } 1846 1847 /** 1848 * When ECM is activated and we were in softap mode, we should just return to wifi off when ECM 1849 * ends 1850 */ 1851 @Test testEcmDisabledRemainsDisabledWhenSoftApHadBeenOn()1852 public void testEcmDisabledRemainsDisabledWhenSoftApHadBeenOn() throws Exception { 1853 assertInDisabledState(); 1854 1855 enterSoftApActiveMode(); 1856 1857 // verify Soft AP Manager started 1858 verify(mWifiInjector).makeSoftApManager( 1859 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1860 1861 // Test with WifiDisableInECBM turned on: 1862 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1863 1864 assertEnteredEcmMode(() -> { 1865 // test ecm changed 1866 emergencyCallbackModeChanged(true); 1867 mLooper.dispatchAll(); 1868 mSoftApListener.onStopped(mSoftApManager); 1869 mLooper.dispatchAll(); 1870 }); 1871 1872 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1873 1874 // test ecm changed 1875 emergencyCallbackModeChanged(false); 1876 mLooper.dispatchAll(); 1877 1878 assertInDisabledState(); 1879 1880 // verify no additional calls to enable softap 1881 verify(mWifiInjector).makeSoftApManager( 1882 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1883 } 1884 1885 /** 1886 * Wifi should remain off when already disabled and we enter ECM. 1887 */ 1888 @Test testEcmOnFromDisabledMode()1889 public void testEcmOnFromDisabledMode() throws Exception { 1890 assertInDisabledState(); 1891 verify(mWifiInjector, never()).makeSoftApManager( 1892 any(), any(), any(), any(), any(), anyBoolean()); 1893 verify(mWifiInjector, never()).makeClientModeManager( 1894 any(), any(), any(), anyBoolean()); 1895 1896 // Test with WifiDisableInECBM turned on: 1897 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1898 1899 assertEnteredEcmMode(() -> { 1900 // test ecm changed 1901 emergencyCallbackModeChanged(true); 1902 mLooper.dispatchAll(); 1903 }); 1904 } 1905 1906 1907 /** 1908 * Updates about call state change also trigger entry of ECM mode. 1909 */ 1910 @Test testEnterEcmOnEmergencyCallStateChange()1911 public void testEnterEcmOnEmergencyCallStateChange() throws Exception { 1912 assertInDisabledState(); 1913 1914 enableWifi(); 1915 assertInEnabledState(); 1916 1917 // Test with WifiDisableInECBM turned on: 1918 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1919 1920 assertEnteredEcmMode(() -> { 1921 // test call state changed 1922 emergencyCallStateChanged(true); 1923 mLooper.dispatchAll(); 1924 mClientListener.onStopped(mClientModeManager); 1925 mLooper.dispatchAll(); 1926 }); 1927 1928 emergencyCallStateChanged(false); 1929 mLooper.dispatchAll(); 1930 1931 assertInEnabledState(); 1932 } 1933 1934 /** 1935 * Verify when both ECM and call state changes arrive, we enter ECM mode 1936 */ 1937 @Test testEnterEcmWithBothSignals()1938 public void testEnterEcmWithBothSignals() throws Exception { 1939 assertInDisabledState(); 1940 1941 enableWifi(); 1942 assertInEnabledState(); 1943 1944 // Test with WifiDisableInECBM turned on: 1945 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1946 1947 assertWifiShutDown(() -> { 1948 emergencyCallStateChanged(true); 1949 mLooper.dispatchAll(); 1950 mClientListener.onStopped(mClientModeManager); 1951 mLooper.dispatchAll(); 1952 }); 1953 1954 assertWifiShutDown(() -> { 1955 emergencyCallbackModeChanged(true); 1956 mLooper.dispatchAll(); 1957 }, 0); // does not cause another shutdown 1958 1959 // client mode only started once so far 1960 verify(mWifiInjector).makeClientModeManager( 1961 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1962 1963 emergencyCallStateChanged(false); 1964 mLooper.dispatchAll(); 1965 1966 // stay in ecm, do not send an additional client mode trigger 1967 assertInEmergencyMode(); 1968 // assert that the underlying state is in disabled state 1969 assertInDisabledState(); 1970 1971 // client mode still only started once 1972 verify(mWifiInjector).makeClientModeManager( 1973 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1974 1975 emergencyCallbackModeChanged(false); 1976 mLooper.dispatchAll(); 1977 1978 // now we can re-enable wifi 1979 verify(mWifiInjector, times(2)).makeClientModeManager( 1980 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1981 assertInEnabledState(); 1982 } 1983 1984 /** 1985 * Verify when both ECM and call state changes arrive but out of order, we enter ECM mode 1986 */ 1987 @Test testEnterEcmWithBothSignalsOutOfOrder()1988 public void testEnterEcmWithBothSignalsOutOfOrder() throws Exception { 1989 assertInDisabledState(); 1990 1991 enableWifi(); 1992 1993 assertInEnabledState(); 1994 verify(mWifiInjector).makeClientModeManager( 1995 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1996 1997 // Test with WifiDisableInECBM turned on: 1998 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1999 2000 assertEnteredEcmMode(() -> { 2001 emergencyCallbackModeChanged(true); 2002 mLooper.dispatchAll(); 2003 mClientListener.onStopped(mClientModeManager); 2004 mLooper.dispatchAll(); 2005 }); 2006 assertInDisabledState(); 2007 2008 assertEnteredEcmMode(() -> { 2009 emergencyCallStateChanged(true); 2010 mLooper.dispatchAll(); 2011 }, 0); // does not enter ECM state again 2012 2013 emergencyCallStateChanged(false); 2014 mLooper.dispatchAll(); 2015 2016 // stay in ecm, do not send an additional client mode trigger 2017 assertInEmergencyMode(); 2018 // assert that the underlying state is in disabled state 2019 assertInDisabledState(); 2020 2021 // client mode still only started once 2022 verify(mWifiInjector).makeClientModeManager( 2023 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2024 2025 emergencyCallbackModeChanged(false); 2026 mLooper.dispatchAll(); 2027 2028 // now we can re-enable wifi 2029 verify(mWifiInjector, times(2)).makeClientModeManager( 2030 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2031 assertInEnabledState(); 2032 } 2033 2034 /** 2035 * Verify when both ECM and call state changes arrive but completely out of order, 2036 * we still enter and properly exit ECM mode 2037 */ 2038 @Test testEnterEcmWithBothSignalsOppositeOrder()2039 public void testEnterEcmWithBothSignalsOppositeOrder() throws Exception { 2040 assertInDisabledState(); 2041 2042 enableWifi(); 2043 2044 assertInEnabledState(); 2045 verify(mWifiInjector).makeClientModeManager( 2046 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2047 2048 // Test with WifiDisableInECBM turned on: 2049 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2050 2051 assertEnteredEcmMode(() -> { 2052 emergencyCallStateChanged(true); 2053 mLooper.dispatchAll(); 2054 mClientListener.onStopped(mClientModeManager); 2055 mLooper.dispatchAll(); 2056 }); 2057 assertInDisabledState(); 2058 2059 assertEnteredEcmMode(() -> { 2060 emergencyCallbackModeChanged(true); 2061 mLooper.dispatchAll(); 2062 }, 0); // still only 1 shutdown 2063 2064 emergencyCallbackModeChanged(false); 2065 mLooper.dispatchAll(); 2066 2067 // stay in ecm, do not send an additional client mode trigger 2068 assertInEmergencyMode(); 2069 // assert that the underlying state is in disabled state 2070 assertInDisabledState(); 2071 2072 // client mode still only started once 2073 verify(mWifiInjector).makeClientModeManager( 2074 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2075 2076 emergencyCallStateChanged(false); 2077 mLooper.dispatchAll(); 2078 2079 // now we can re-enable wifi 2080 verify(mWifiInjector, times(2)).makeClientModeManager( 2081 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2082 assertInEnabledState(); 2083 } 2084 2085 /** 2086 * When ECM is active, we might get addition signals of ECM mode, drop those additional signals, 2087 * we must exit when one of each signal is received. 2088 * 2089 * In any case, duplicate signals indicate a bug from Telephony. Each signal should be turned 2090 * off before it is turned on again. 2091 */ 2092 @Test testProperExitFromEcmModeWithMultipleMessages()2093 public void testProperExitFromEcmModeWithMultipleMessages() throws Exception { 2094 assertInDisabledState(); 2095 2096 enableWifi(); 2097 2098 verify(mWifiInjector).makeClientModeManager( 2099 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2100 assertInEnabledState(); 2101 2102 // Test with WifiDisableInECBM turned on: 2103 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2104 2105 assertEnteredEcmMode(() -> { 2106 emergencyCallbackModeChanged(true); 2107 emergencyCallStateChanged(true); 2108 emergencyCallStateChanged(true); 2109 emergencyCallbackModeChanged(true); 2110 emergencyCallbackModeChanged(true); 2111 mLooper.dispatchAll(); 2112 mClientListener.onStopped(mClientModeManager); 2113 mLooper.dispatchAll(); 2114 }); 2115 assertInDisabledState(); 2116 2117 assertEnteredEcmMode(() -> { 2118 emergencyCallbackModeChanged(false); 2119 mLooper.dispatchAll(); 2120 emergencyCallbackModeChanged(false); 2121 mLooper.dispatchAll(); 2122 emergencyCallbackModeChanged(false); 2123 mLooper.dispatchAll(); 2124 emergencyCallbackModeChanged(false); 2125 mLooper.dispatchAll(); 2126 }, 0); 2127 2128 // didn't enter client mode again 2129 verify(mWifiInjector).makeClientModeManager( 2130 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2131 assertInDisabledState(); 2132 2133 // now we will exit ECM 2134 emergencyCallStateChanged(false); 2135 mLooper.dispatchAll(); 2136 2137 // now we can re-enable wifi 2138 verify(mWifiInjector, times(2)).makeClientModeManager( 2139 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2140 assertInEnabledState(); 2141 } 2142 2143 /** 2144 * Toggling wifi on when in ECM does not exit ecm mode and enable wifi 2145 */ 2146 @Test testWifiDoesNotToggleOnWhenInEcm()2147 public void testWifiDoesNotToggleOnWhenInEcm() throws Exception { 2148 assertInDisabledState(); 2149 2150 // Test with WifiDisableInECBM turned on: 2151 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2152 // test ecm changed 2153 assertEnteredEcmMode(() -> { 2154 emergencyCallbackModeChanged(true); 2155 mLooper.dispatchAll(); 2156 }); 2157 2158 // now toggle wifi and verify we do not start wifi 2159 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 2160 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2161 mLooper.dispatchAll(); 2162 2163 verify(mWifiInjector, never()).makeClientModeManager( 2164 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2165 assertInDisabledState(); 2166 assertInEmergencyMode(); 2167 2168 // now we will exit ECM 2169 emergencyCallbackModeChanged(false); 2170 mLooper.dispatchAll(); 2171 assertNotInEmergencyMode(); 2172 2173 // Wifi toggle on now takes effect 2174 verify(mWifiInjector).makeClientModeManager( 2175 any(), eq(SETTINGS_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2176 assertInEnabledState(); 2177 } 2178 2179 /** 2180 * Toggling wifi off when in ECM does not disable wifi when getConfigWiFiDisableInECBM is 2181 * disabled. 2182 */ 2183 @Test testWifiDoesNotToggleOffWhenInEcmAndConfigDisabled()2184 public void testWifiDoesNotToggleOffWhenInEcmAndConfigDisabled() throws Exception { 2185 enableWifi(); 2186 assertInEnabledState(); 2187 verify(mWifiInjector).makeClientModeManager( 2188 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2189 2190 // Test with WifiDisableInECBM turned off 2191 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 2192 // test ecm changed 2193 assertEnteredEcmMode(() -> { 2194 emergencyCallbackModeChanged(true); 2195 mLooper.dispatchAll(); 2196 }); 2197 2198 // now toggle wifi and verify we do not start wifi 2199 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 2200 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2201 mLooper.dispatchAll(); 2202 2203 // still only called once 2204 verify(mWifiInjector).makeClientModeManager( 2205 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2206 verify(mClientModeManager, never()).stop(); 2207 assertInEnabledState(); 2208 assertInEmergencyMode(); 2209 2210 // now we will exit ECM 2211 emergencyCallbackModeChanged(false); 2212 mLooper.dispatchAll(); 2213 assertNotInEmergencyMode(); 2214 2215 // Wifi toggle off now takes effect 2216 verify(mClientModeManager).stop(); 2217 mClientListener.onStopped(mClientModeManager); 2218 mLooper.dispatchAll(); 2219 assertInDisabledState(); 2220 } 2221 2222 @Test testAirplaneModeDoesNotToggleOnWhenInEcm()2223 public void testAirplaneModeDoesNotToggleOnWhenInEcm() throws Exception { 2224 // TODO(b/139829963): investigate the expected behavior is when toggling airplane mode in 2225 // ECM 2226 } 2227 2228 /** 2229 * Toggling scan mode when in ECM does not exit ecm mode and enable scan mode 2230 */ 2231 @Test testScanModeDoesNotToggleOnWhenInEcm()2232 public void testScanModeDoesNotToggleOnWhenInEcm() throws Exception { 2233 assertInDisabledState(); 2234 2235 // Test with WifiDisableInECBM turned on: 2236 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2237 assertEnteredEcmMode(() -> { 2238 // test ecm changed 2239 emergencyCallbackModeChanged(true); 2240 mLooper.dispatchAll(); 2241 }); 2242 2243 // now enable scanning and verify we do not start wifi 2244 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 2245 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 2246 mActiveModeWarden.scanAlwaysModeChanged(); 2247 mLooper.dispatchAll(); 2248 2249 verify(mWifiInjector, never()).makeClientModeManager( 2250 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2251 assertInDisabledState(); 2252 } 2253 2254 2255 /** 2256 * Toggling softap mode when in ECM does not exit ecm mode and enable softap 2257 */ 2258 @Test testSoftApModeDoesNotToggleOnWhenInEcm()2259 public void testSoftApModeDoesNotToggleOnWhenInEcm() throws Exception { 2260 assertInDisabledState(); 2261 2262 // Test with WifiDisableInECBM turned on: 2263 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2264 assertEnteredEcmMode(() -> { 2265 // test ecm changed 2266 emergencyCallbackModeChanged(true); 2267 mLooper.dispatchAll(); 2268 }); 2269 2270 // try to start Soft AP 2271 mActiveModeWarden.startSoftAp( 2272 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2273 mSoftApCapability, TEST_COUNTRYCODE, null), TEST_WORKSOURCE); 2274 mLooper.dispatchAll(); 2275 2276 verify(mWifiInjector, never()) 2277 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2278 assertInDisabledState(); 2279 2280 // verify triggered Soft AP failure callback 2281 ArgumentCaptor<SoftApState> softApStateCaptor = 2282 ArgumentCaptor.forClass(SoftApState.class); 2283 verify(mSoftApStateMachineCallback).onStateChanged(softApStateCaptor.capture()); 2284 assertThat(softApStateCaptor.getValue().getState()).isEqualTo(WIFI_AP_STATE_FAILED); 2285 assertThat(softApStateCaptor.getValue().getFailureReason()) 2286 .isEqualTo(SAP_START_FAILURE_GENERAL); 2287 assertThat(softApStateCaptor.getValue().getFailureReasonInternal()) 2288 .isEqualTo(SAP_START_FAILURE_GENERAL); 2289 2290 // try to start LOHS 2291 mActiveModeWarden.startSoftAp( 2292 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, 2293 mSoftApCapability, TEST_COUNTRYCODE, null), TEST_WORKSOURCE); 2294 mLooper.dispatchAll(); 2295 2296 verify(mWifiInjector, never()) 2297 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2298 assertInDisabledState(); 2299 2300 // verify triggered LOHS failure callback 2301 verify(mLohsStateMachineCallback).onStateChanged(softApStateCaptor.capture()); 2302 assertThat(softApStateCaptor.getValue().getState()).isEqualTo(WIFI_AP_STATE_FAILED); 2303 assertThat(softApStateCaptor.getValue().getFailureReason()) 2304 .isEqualTo(SAP_START_FAILURE_GENERAL); 2305 assertThat(softApStateCaptor.getValue().getFailureReasonInternal()) 2306 .isEqualTo(SAP_START_FAILURE_GENERAL); 2307 } 2308 2309 /** 2310 * Toggling off softap mode when in ECM does not induce a mode change 2311 */ 2312 @Test testSoftApStoppedDoesNotSwitchModesWhenInEcm()2313 public void testSoftApStoppedDoesNotSwitchModesWhenInEcm() throws Exception { 2314 assertInDisabledState(); 2315 2316 // Test with WifiDisableInECBM turned on: 2317 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2318 assertEnteredEcmMode(() -> { 2319 // test ecm changed 2320 emergencyCallbackModeChanged(true); 2321 mLooper.dispatchAll(); 2322 }); 2323 2324 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 2325 mLooper.dispatchAll(); 2326 2327 assertInDisabledState(); 2328 verifyNoMoreInteractions(mSoftApManager, mClientModeManager); 2329 } 2330 2331 /** 2332 * Toggling softap mode when in airplane mode needs to enable softap 2333 */ 2334 @Test testSoftApModeToggleWhenInAirplaneMode()2335 public void testSoftApModeToggleWhenInAirplaneMode() throws Exception { 2336 // Test with airplane mode turned on: 2337 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 2338 2339 // Turn on SoftAp. 2340 mActiveModeWarden.startSoftAp( 2341 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2342 mSoftApCapability, TEST_COUNTRYCODE, null), TEST_WORKSOURCE); 2343 mLooper.dispatchAll(); 2344 verify(mWifiInjector) 2345 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2346 2347 // Turn off SoftAp. 2348 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 2349 mLooper.dispatchAll(); 2350 2351 verify(mSoftApManager).stop(); 2352 } 2353 2354 /** 2355 * Toggling off scan mode when in ECM does not induce a mode change 2356 */ 2357 @Test testScanModeStoppedSwitchModeToDisabledStateWhenInEcm()2358 public void testScanModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { 2359 enterScanOnlyModeActiveState(); 2360 assertInEnabledState(); 2361 2362 // Test with WifiDisableInECBM turned on: 2363 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2364 assertEnteredEcmMode(() -> { 2365 // test ecm changed 2366 emergencyCallbackModeChanged(true); 2367 mLooper.dispatchAll(); 2368 mClientListener.onStopped(mClientModeManager); 2369 mLooper.dispatchAll(); 2370 }); 2371 2372 // Spurious onStopped 2373 mClientListener.onStopped(mClientModeManager); 2374 mLooper.dispatchAll(); 2375 2376 assertInDisabledState(); 2377 } 2378 2379 /** 2380 * Toggling off client mode when in ECM does not induce a mode change 2381 */ 2382 @Test testClientModeStoppedSwitchModeToDisabledStateWhenInEcm()2383 public void testClientModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { 2384 enterClientModeActiveState(); 2385 assertInEnabledState(); 2386 2387 // Test with WifiDisableInECBM turned on: 2388 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2389 assertEnteredEcmMode(() -> { 2390 // test ecm changed 2391 emergencyCallbackModeChanged(true); 2392 mLooper.dispatchAll(); 2393 mClientListener.onStopped(mClientModeManager); 2394 mLooper.dispatchAll(); 2395 }); 2396 2397 // Spurious onStopped 2398 mClientListener.onStopped(mClientModeManager); 2399 mLooper.dispatchAll(); 2400 2401 assertInDisabledState(); 2402 } 2403 2404 /** 2405 * When AP mode is enabled and wifi was previously in AP mode, we should return to 2406 * EnabledState after the AP is disabled. 2407 * Enter EnabledState, activate AP mode, disable AP mode. 2408 * <p> 2409 * Expected: AP should successfully start and exit, then return to EnabledState. 2410 */ 2411 @Test testReturnToEnabledStateAfterAPModeShutdown()2412 public void testReturnToEnabledStateAfterAPModeShutdown() throws Exception { 2413 enableWifi(); 2414 assertInEnabledState(); 2415 verify(mWifiInjector).makeClientModeManager( 2416 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2417 2418 mActiveModeWarden.startSoftAp( 2419 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2420 mSoftApCapability, TEST_COUNTRYCODE, null), TEST_WORKSOURCE); 2421 // add an "unexpected" sta mode stop to simulate a single interface device 2422 mClientListener.onStopped(mClientModeManager); 2423 mLooper.dispatchAll(); 2424 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2425 2426 // Now stop the AP 2427 mSoftApListener.onStopped(mSoftApManager); 2428 mLooper.dispatchAll(); 2429 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2430 2431 // We should re-enable client mode 2432 verify(mWifiInjector, times(2)).makeClientModeManager( 2433 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2434 assertInEnabledState(); 2435 } 2436 2437 /** 2438 * When in STA mode and SoftAP is enabled and the device supports STA+AP (i.e. the STA wasn't 2439 * shut down when the AP started), both modes will be running concurrently. 2440 * 2441 * Then when the AP is disabled, we should remain in STA mode. 2442 * 2443 * Enter EnabledState, activate AP mode, toggle WiFi off. 2444 * <p> 2445 * Expected: AP should successfully start and exit, then return to EnabledState. 2446 */ 2447 @Test testReturnToEnabledStateAfterWifiEnabledShutdown()2448 public void testReturnToEnabledStateAfterWifiEnabledShutdown() throws Exception { 2449 enableWifi(); 2450 assertInEnabledState(); 2451 verify(mWifiInjector).makeClientModeManager( 2452 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2453 2454 mActiveModeWarden.startSoftAp( 2455 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2456 mSoftApCapability, TEST_COUNTRYCODE, null), TEST_WORKSOURCE); 2457 mLooper.dispatchAll(); 2458 2459 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 2460 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2461 mSoftApListener.onStopped(mSoftApManager); 2462 mLooper.dispatchAll(); 2463 2464 // wasn't called again 2465 verify(mWifiInjector).makeClientModeManager( 2466 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2467 assertInEnabledState(); 2468 } 2469 2470 @Test testRestartWifiStackInEnabledStateTriggersBugReport()2471 public void testRestartWifiStackInEnabledStateTriggersBugReport() throws Exception { 2472 enableWifi(); 2473 2474 // note: using a reason that will typical not start a bug report on purpose to guarantee 2475 // that it is the flag and not the reason which controls it. 2476 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG, 2477 true); 2478 mLooper.dispatchAll(); 2479 verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); 2480 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2481 } 2482 2483 @Test testRestartWifiWatchdogDoesNotTriggerBugReport()2484 public void testRestartWifiWatchdogDoesNotTriggerBugReport() throws Exception { 2485 enableWifi(); 2486 // note: using a reason that will typical start a bug report on purpose to guarantee that 2487 // it is the flag and not the reason which controls it. 2488 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2489 false); 2490 mLooper.dispatchAll(); 2491 verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); 2492 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2493 } 2494 2495 /** 2496 * When in sta mode, CMD_RECOVERY_DISABLE_WIFI messages should trigger wifi to disable. 2497 */ 2498 @Test testRecoveryDisabledTurnsWifiOff()2499 public void testRecoveryDisabledTurnsWifiOff() throws Exception { 2500 enableWifi(); 2501 assertInEnabledState(); 2502 mActiveModeWarden.recoveryDisableWifi(); 2503 mLooper.dispatchAll(); 2504 verify(mClientModeManager).stop(); 2505 mClientListener.onStopped(mClientModeManager); 2506 mLooper.dispatchAll(); 2507 assertInDisabledState(); 2508 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2509 } 2510 2511 /** 2512 * When wifi is disabled, CMD_RECOVERY_DISABLE_WIFI should not trigger a state change. 2513 */ 2514 @Test testRecoveryDisabledWhenWifiAlreadyOff()2515 public void testRecoveryDisabledWhenWifiAlreadyOff() throws Exception { 2516 assertInDisabledState(); 2517 assertWifiShutDown(() -> { 2518 mActiveModeWarden.recoveryDisableWifi(); 2519 mLooper.dispatchAll(); 2520 }); 2521 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS + 10); 2522 mLooper.dispatchAll(); 2523 2524 // Ensure we did not restart wifi. 2525 assertInDisabledState(); 2526 } 2527 2528 /** 2529 * The command to trigger a WiFi reset should not trigger any action by WifiController if we 2530 * are not in STA mode. 2531 * WiFi is not in connect mode, so any calls to reset the wifi stack due to connection failures 2532 * should be ignored. 2533 * Create and start WifiController in DisabledState, send command to restart WiFi 2534 * <p> 2535 * Expected: WiFiController should not call ActiveModeWarden.disableWifi() 2536 */ 2537 @Test testRestartWifiStackInDisabledState()2538 public void testRestartWifiStackInDisabledState() throws Exception { 2539 assertInDisabledState(); 2540 2541 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2542 true); 2543 mLooper.dispatchAll(); 2544 2545 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS + 10); 2546 mLooper.dispatchAll(); 2547 2548 assertInDisabledState(); 2549 verifyNoMoreInteractions(mClientModeManager, mSoftApManager); 2550 } 2551 2552 @Test testNetworkStateChangeListener()2553 public void testNetworkStateChangeListener() throws Exception { 2554 IWifiNetworkStateChangedListener testListener = 2555 mock(IWifiNetworkStateChangedListener.class); 2556 when(testListener.asBinder()).thenReturn(mock(IBinder.class)); 2557 2558 // register listener and verify results delivered 2559 mActiveModeWarden.addWifiNetworkStateChangedListener(testListener); 2560 mActiveModeWarden.onNetworkStateChanged( 2561 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY, 2562 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTED); 2563 verify(testListener).onWifiNetworkStateChanged( 2564 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY, 2565 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_CONNECTED); 2566 2567 // unregister listener and verify results no longer delivered 2568 mActiveModeWarden.removeWifiNetworkStateChangedListener(testListener); 2569 mActiveModeWarden.onNetworkStateChanged( 2570 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY, 2571 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED); 2572 verify(testListener, never()).onWifiNetworkStateChanged( 2573 WifiManager.WifiNetworkStateChangedListener.WIFI_ROLE_CLIENT_PRIMARY, 2574 WifiManager.WifiNetworkStateChangedListener.WIFI_NETWORK_STATUS_DISCONNECTED); 2575 } 2576 2577 /** 2578 * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through 2579 * the ActiveModeWarden.shutdownWifi() call when in STA mode. 2580 * When WiFi is in scan mode, calls to reset the wifi stack due to native failure 2581 * should trigger a supplicant stop, and subsequently, a driver reload. 2582 * Create and start WifiController in EnabledState, send command to restart WiFi 2583 * <p> 2584 * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and 2585 * ActiveModeWarden should enter SCAN_ONLY mode and the wifi driver should be started. 2586 */ 2587 @Test testRestartWifiStackInStaScanEnabledState()2588 public void testRestartWifiStackInStaScanEnabledState() throws Exception { 2589 assertInDisabledState(); 2590 2591 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 2592 mActiveModeWarden.scanAlwaysModeChanged(); 2593 mLooper.dispatchAll(); 2594 2595 assertInEnabledState(); 2596 verify(mWifiInjector).makeClientModeManager( 2597 any(), eq(new WorkSource(Process.WIFI_UID)), eq(ROLE_CLIENT_SCAN_ONLY), 2598 anyBoolean()); 2599 2600 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2601 true); 2602 mLooper.dispatchAll(); 2603 2604 verify(mClientModeManager).stop(); 2605 mClientListener.onStopped(mClientModeManager); 2606 mLooper.dispatchAll(); 2607 assertInDisabledState(); 2608 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2609 2610 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2611 mLooper.dispatchAll(); 2612 2613 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2614 assertInEnabledState(); 2615 2616 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2617 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2618 } 2619 2620 /** 2621 * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through 2622 * the ActiveModeWarden.shutdownWifi() call when in STA mode. 2623 * WiFi is in connect mode, calls to reset the wifi stack due to connection failures 2624 * should trigger a supplicant stop, and subsequently, a driver reload. 2625 * Create and start WifiController in EnabledState, send command to restart WiFi 2626 * <p> 2627 * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and 2628 * ActiveModeWarden should enter CONNECT_MODE and the wifi driver should be started. 2629 */ 2630 @Test testRestartWifiStackInStaConnectEnabledState()2631 public void testRestartWifiStackInStaConnectEnabledState() throws Exception { 2632 enableWifi(); 2633 assertInEnabledState(); 2634 verify(mWifiInjector).makeClientModeManager( 2635 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2636 2637 assertWifiShutDown(() -> { 2638 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2639 true); 2640 mLooper.dispatchAll(); 2641 // Complete the stop 2642 mClientListener.onStopped(mClientModeManager); 2643 mLooper.dispatchAll(); 2644 }); 2645 2646 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2647 2648 // still only started once 2649 verify(mWifiInjector).makeClientModeManager( 2650 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2651 2652 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2653 mLooper.dispatchAll(); 2654 2655 // started again 2656 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2657 assertInEnabledState(); 2658 2659 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2660 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2661 } 2662 2663 /** 2664 * The command to trigger a WiFi reset should not trigger a reset when in ECM mode. 2665 * Enable wifi and enter ECM state, send command to restart wifi. 2666 * <p> 2667 * Expected: The command to trigger a wifi reset should be ignored and we should remain in ECM 2668 * mode. 2669 */ 2670 @Test testRestartWifiStackDoesNotExitECMMode()2671 public void testRestartWifiStackDoesNotExitECMMode() throws Exception { 2672 enableWifi(); 2673 assertInEnabledState(); 2674 verify(mWifiInjector).makeClientModeManager( 2675 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), eq(false)); 2676 2677 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2678 assertEnteredEcmMode(() -> { 2679 emergencyCallStateChanged(true); 2680 mLooper.dispatchAll(); 2681 mClientListener.onStopped(mClientModeManager); 2682 mLooper.dispatchAll(); 2683 }); 2684 assertInEmergencyMode(); 2685 assertInDisabledState(); 2686 verify(mClientModeManager).stop(); 2687 verify(mClientModeManager, atLeastOnce()).getRole(); 2688 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 2689 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2690 2691 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG, 2692 false); 2693 mLooper.dispatchAll(); 2694 2695 // wasn't called again 2696 verify(mWifiInjector).makeClientModeManager( 2697 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2698 assertInEmergencyMode(); 2699 assertInDisabledState(); 2700 2701 verify(mClientModeManager, atLeastOnce()).getInterfaceName(); 2702 verify(mClientModeManager, atLeastOnce()).getPreviousRole(); 2703 } 2704 2705 /** 2706 * The command to trigger a WiFi reset should trigger a wifi reset in SoftApManager through 2707 * the ActiveModeWarden.shutdownWifi() call when in SAP enabled mode. 2708 */ 2709 @Test testRestartWifiStackInTetheredSoftApEnabledState()2710 public void testRestartWifiStackInTetheredSoftApEnabledState() throws Exception { 2711 enterSoftApActiveMode(); 2712 verify(mWifiInjector).makeSoftApManager( 2713 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2714 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 2715 // Return true to indicate Wifi recovery in progress 2716 when(mSelfRecovery.isRecoveryInProgress()).thenReturn(true); 2717 assertWifiShutDown(() -> { 2718 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2719 true); 2720 mLooper.dispatchAll(); 2721 // Complete the stop 2722 mSoftApListener.onStopped(mSoftApManager); 2723 mLooper.dispatchAll(); 2724 }); 2725 2726 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2727 2728 // still only started once 2729 verify(mWifiInjector).makeSoftApManager( 2730 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2731 // No client mode manager created 2732 verify(mWifiInjector, never()).makeClientModeManager( 2733 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2734 2735 verify(mSelfRecovery).isRecoveryInProgress(); 2736 verify(mSelfRecovery).onWifiStopped(); 2737 2738 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2739 mLooper.dispatchAll(); 2740 2741 // started again 2742 verify(mWifiInjector, times(2)).makeSoftApManager( 2743 any(), any(), any(), any(), any(), anyBoolean()); 2744 assertInEnabledState(); 2745 2746 verify(mSelfRecovery).onRecoveryCompleted(); 2747 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2748 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2749 } 2750 2751 /** 2752 * The command to trigger a WiFi reset should trigger a wifi reset in SoftApManager through 2753 * the ActiveModeWarden.shutdownWifi() call when in SAP enabled mode. 2754 * If the shutdown isn't done fast enough to transit to disabled state it should still 2755 * bring up soft ap manager later. 2756 */ 2757 @Test testRestartWifiStackInTetheredSoftApEnabledState_SlowDisable()2758 public void testRestartWifiStackInTetheredSoftApEnabledState_SlowDisable() throws Exception { 2759 enterSoftApActiveMode(); 2760 verify(mWifiInjector).makeSoftApManager( 2761 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2762 2763 assertWifiShutDown(() -> { 2764 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2765 true); 2766 mLooper.dispatchAll(); 2767 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2768 mLooper.dispatchAll(); 2769 }); 2770 // Wifi is still not disabled yet. 2771 verify(mModeChangeCallback, never()).onActiveModeManagerRemoved(mSoftApManager); 2772 verify(mWifiInjector).makeSoftApManager( 2773 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2774 assertInEnabledState(); 2775 2776 // Now complete the stop and transit to disabled state 2777 mSoftApListener.onStopped(mSoftApManager); 2778 // mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2779 mLooper.dispatchAll(); 2780 2781 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2782 // started again 2783 verify(mWifiInjector, times(1)).makeSoftApManager( 2784 any(), any(), any(), any(), any(), anyBoolean()); 2785 assertInDisabledState(); 2786 2787 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2788 mLooper.dispatchAll(); 2789 2790 // started again 2791 verify(mWifiInjector, times(2)).makeSoftApManager( 2792 any(), any(), any(), any(), any(), anyBoolean()); 2793 assertInEnabledState(); 2794 2795 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2796 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2797 } 2798 2799 /** 2800 * The command to trigger a WiFi reset should trigger a wifi reset in SoftApManager & 2801 * ClientModeManager through the ActiveModeWarden.shutdownWifi() call when in STA + SAP 2802 * enabled mode. 2803 */ 2804 @Test testRestartWifiStackInTetheredSoftApAndStaConnectEnabledState()2805 public void testRestartWifiStackInTetheredSoftApAndStaConnectEnabledState() throws Exception { 2806 enableWifi(); 2807 enterSoftApActiveMode(); 2808 verify(mWifiInjector).makeClientModeManager( 2809 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2810 verify(mWifiInjector).makeSoftApManager( 2811 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2812 2813 assertWifiShutDown(() -> { 2814 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2815 true); 2816 mLooper.dispatchAll(); 2817 // Complete the stop 2818 mClientListener.onStopped(mClientModeManager); 2819 mSoftApListener.onStopped(mSoftApManager); 2820 mLooper.dispatchAll(); 2821 }); 2822 2823 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2824 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2825 2826 // still only started once 2827 verify(mWifiInjector).makeClientModeManager( 2828 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2829 verify(mWifiInjector).makeSoftApManager( 2830 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2831 2832 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2833 mLooper.dispatchAll(); 2834 2835 // started again 2836 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2837 verify(mWifiInjector, times(2)).makeSoftApManager( 2838 any(), any(), any(), any(), any(), anyBoolean()); 2839 assertInEnabledState(); 2840 2841 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2842 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2843 } 2844 2845 /** 2846 * Tests that when Wifi is already disabled and another Wifi toggle command arrives, 2847 * don't enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is false. 2848 * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns false if either the wifi 2849 * scanning is disabled and airplane mode is on. 2850 */ 2851 @Test staDisabled_toggleWifiOff_scanNotAvailable_dontGoToScanMode()2852 public void staDisabled_toggleWifiOff_scanNotAvailable_dontGoToScanMode() { 2853 assertInDisabledState(); 2854 2855 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 2856 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 2857 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 2858 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 2859 2860 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2861 mLooper.dispatchAll(); 2862 2863 assertInDisabledState(); 2864 verify(mWifiInjector, never()).makeClientModeManager( 2865 any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2866 } 2867 2868 /** 2869 * Tests that when Wifi is already disabled and another Wifi toggle command arrives, 2870 * enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is true. 2871 * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns true if both the wifi 2872 * scanning is enabled and airplane mode is off. 2873 */ 2874 @Test staDisabled_toggleWifiOff_scanAvailable_goToScanMode()2875 public void staDisabled_toggleWifiOff_scanAvailable_goToScanMode() { 2876 assertInDisabledState(); 2877 2878 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 2879 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 2880 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 2881 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 2882 2883 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2884 mLooper.dispatchAll(); 2885 2886 assertInEnabledState(); 2887 verify(mWifiInjector).makeClientModeManager( 2888 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 2889 } 2890 2891 /** 2892 * Tests that if the carrier config to disable Wifi is enabled during ECM, Wifi is shut down 2893 * when entering ECM and turned back on when exiting ECM. 2894 */ 2895 @Test ecmDisablesWifi_exitEcm_restartWifi()2896 public void ecmDisablesWifi_exitEcm_restartWifi() throws Exception { 2897 enterClientModeActiveState(); 2898 2899 verify(mWifiInjector).makeClientModeManager( 2900 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2901 2902 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2903 assertEnteredEcmMode(() -> { 2904 emergencyCallbackModeChanged(true); 2905 mLooper.dispatchAll(); 2906 }); 2907 assertInEnabledState(); 2908 verify(mClientModeManager).stop(); 2909 2910 mClientListener.onStopped(mClientModeManager); 2911 mLooper.dispatchAll(); 2912 assertInDisabledState(); 2913 2914 emergencyCallbackModeChanged(false); 2915 mLooper.dispatchAll(); 2916 2917 assertNotInEmergencyMode(); 2918 // client mode restarted 2919 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2920 assertInEnabledState(); 2921 } 2922 2923 /** 2924 * Tests that if the carrier config to disable Wifi is not enabled during ECM, Wifi remains on 2925 * during ECM, and nothing happens after exiting ECM. 2926 */ 2927 @Test ecmDoesNotDisableWifi_exitEcm_noOp()2928 public void ecmDoesNotDisableWifi_exitEcm_noOp() throws Exception { 2929 enterClientModeActiveState(); 2930 2931 verify(mWifiInjector).makeClientModeManager( 2932 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2933 2934 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 2935 assertEnteredEcmMode(() -> { 2936 emergencyCallbackModeChanged(true); 2937 mLooper.dispatchAll(); 2938 }); 2939 assertInEnabledState(); 2940 verify(mClientModeManager, never()).stop(); 2941 2942 emergencyCallbackModeChanged(false); 2943 mLooper.dispatchAll(); 2944 2945 assertNotInEmergencyMode(); 2946 // client mode manager not started again 2947 verify(mWifiInjector).makeClientModeManager( 2948 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2949 assertInEnabledState(); 2950 } 2951 2952 @Test testUpdateCapabilityInSoftApActiveMode()2953 public void testUpdateCapabilityInSoftApActiveMode() throws Exception { 2954 SoftApCapability testCapability = new SoftApCapability(0); 2955 enterSoftApActiveMode(); 2956 mActiveModeWarden.updateSoftApCapability(testCapability, 2957 WifiManager.IFACE_IP_MODE_TETHERED); 2958 mLooper.dispatchAll(); 2959 verify(mSoftApManager).updateCapability(testCapability); 2960 } 2961 2962 @Test testUpdateConfigInSoftApActiveMode()2963 public void testUpdateConfigInSoftApActiveMode() throws Exception { 2964 SoftApConfiguration testConfig = new SoftApConfiguration.Builder() 2965 .setSsid("Test123").build(); 2966 enterSoftApActiveMode(); 2967 mActiveModeWarden.updateSoftApConfiguration(testConfig); 2968 mLooper.dispatchAll(); 2969 verify(mSoftApManager).updateConfiguration(testConfig); 2970 } 2971 2972 @Test testUpdateCapabilityInNonSoftApActiveMode()2973 public void testUpdateCapabilityInNonSoftApActiveMode() throws Exception { 2974 SoftApCapability testCapability = new SoftApCapability(0); 2975 enterClientModeActiveState(); 2976 mActiveModeWarden.updateSoftApCapability(testCapability, 2977 WifiManager.IFACE_IP_MODE_TETHERED); 2978 mLooper.dispatchAll(); 2979 verify(mSoftApManager, never()).updateCapability(any()); 2980 } 2981 2982 @Test testUpdateLocalModeSoftApCapabilityInTetheredSoftApActiveMode()2983 public void testUpdateLocalModeSoftApCapabilityInTetheredSoftApActiveMode() throws Exception { 2984 SoftApCapability testCapability = new SoftApCapability(0); 2985 enterSoftApActiveMode(); // Tethered mode 2986 mActiveModeWarden.updateSoftApCapability(testCapability, 2987 WifiManager.IFACE_IP_MODE_LOCAL_ONLY); 2988 mLooper.dispatchAll(); 2989 verify(mSoftApManager, never()).updateCapability(any()); 2990 } 2991 2992 @Test testUpdateConfigInNonSoftApActiveMode()2993 public void testUpdateConfigInNonSoftApActiveMode() throws Exception { 2994 SoftApConfiguration testConfig = new SoftApConfiguration.Builder() 2995 .setSsid("Test123").build(); 2996 enterClientModeActiveState(); 2997 mActiveModeWarden.updateSoftApConfiguration(testConfig); 2998 mLooper.dispatchAll(); 2999 verify(mSoftApManager, never()).updateConfiguration(any()); 3000 } 3001 3002 @Test isStaApConcurrencySupported()3003 public void isStaApConcurrencySupported() throws Exception { 3004 enterClientModeActiveState(); 3005 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); 3006 mClientListener.onStarted(mClientModeManager); 3007 assertEquals(0L, 3008 mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA); 3009 3010 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); 3011 mClientListener.onStarted(mClientModeManager); 3012 assertEquals(WifiManager.WIFI_FEATURE_AP_STA, 3013 mActiveModeWarden.getSupportedFeatureSet() & WifiManager.WIFI_FEATURE_AP_STA); 3014 } 3015 3016 @Test isStaStaConcurrencySupported()3017 public void isStaStaConcurrencySupported() throws Exception { 3018 // STA + STA not supported. 3019 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(false); 3020 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 3021 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 3022 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 3023 3024 // STA + STA supported, but no use-cases enabled. 3025 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); 3026 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 3027 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 3028 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 3029 3030 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3031 .thenReturn(true); 3032 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 3033 3034 when(mResources.getBoolean( 3035 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3036 .thenReturn(true); 3037 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 3038 3039 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3040 .thenReturn(true); 3041 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 3042 } 3043 requestAdditionalClientModeManager( ClientConnectivityRole additionaClientModeManagerRole, ConcreteClientModeManager additionalClientModeManager, ExternalClientModeManagerRequestListener externalRequestListener, String ssid, String bssid)3044 private Listener<ConcreteClientModeManager> requestAdditionalClientModeManager( 3045 ClientConnectivityRole additionaClientModeManagerRole, 3046 ConcreteClientModeManager additionalClientModeManager, 3047 ExternalClientModeManagerRequestListener externalRequestListener, 3048 String ssid, String bssid) 3049 throws Exception { 3050 enterClientModeActiveState(); 3051 when(additionalClientModeManager.getRequestorWs()).thenReturn(TEST_WORKSOURCE); 3052 3053 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3054 new Mutable<>(); 3055 3056 // Connected to ssid1/bssid1 3057 WifiConfiguration config1 = new WifiConfiguration(); 3058 config1.SSID = TEST_SSID_1; 3059 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3060 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3061 3062 doAnswer((invocation) -> { 3063 Object[] args = invocation.getArguments(); 3064 additionalClientListener.value = 3065 (Listener<ConcreteClientModeManager>) args[0]; 3066 return additionalClientModeManager; 3067 }).when(mWifiInjector).makeClientModeManager( 3068 any(Listener.class), any(), any(), anyBoolean()); 3069 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 3070 when(additionalClientModeManager.getRole()).thenReturn(additionaClientModeManagerRole); 3071 3072 // request for ssid2/bssid2 3073 if (additionaClientModeManagerRole == ROLE_CLIENT_LOCAL_ONLY) { 3074 mActiveModeWarden.requestLocalOnlyClientModeManager( 3075 externalRequestListener, TEST_WORKSOURCE, ssid, bssid, false); 3076 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3077 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3078 externalRequestListener, TEST_WORKSOURCE, ssid, bssid); 3079 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3080 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3081 externalRequestListener, TEST_WORKSOURCE, ssid, bssid); 3082 } 3083 mLooper.dispatchAll(); 3084 verify(mWifiInjector) 3085 .makeClientModeManager(any(), eq(TEST_WORKSOURCE), 3086 eq(additionaClientModeManagerRole), anyBoolean()); 3087 additionalClientListener.value.onStarted(additionalClientModeManager); 3088 mLooper.dispatchAll(); 3089 // capture last use case set 3090 ArgumentCaptor<Integer> useCaseCaptor = ArgumentCaptor.forClass(Integer.class); 3091 verify(mWifiNative, atLeastOnce()).setMultiStaUseCase(useCaseCaptor.capture()); 3092 int lastUseCaseSet = useCaseCaptor.getValue().intValue(); 3093 // Ensure the hardware is correctly configured for STA + STA 3094 if (additionaClientModeManagerRole == ROLE_CLIENT_LOCAL_ONLY 3095 || additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3096 assertEquals(WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED, lastUseCaseSet); 3097 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3098 assertEquals(WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY, lastUseCaseSet); 3099 } 3100 3101 // verify last set of primary connection is for WIFI_IFACE_NAME 3102 ArgumentCaptor<String> ifaceNameCaptor = ArgumentCaptor.forClass(String.class); 3103 verify(mWifiNative, atLeastOnce()).setMultiStaPrimaryConnection(ifaceNameCaptor.capture()); 3104 assertEquals(WIFI_IFACE_NAME, ifaceNameCaptor.getValue()); 3105 3106 // Returns the new local only client mode manager. 3107 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3108 ArgumentCaptor.forClass(ClientModeManager.class); 3109 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3110 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3111 // the additional CMM never became primary 3112 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 3113 if (additionaClientModeManagerRole == ROLE_CLIENT_LOCAL_ONLY 3114 || additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3115 assertEquals(Set.of(TEST_WORKSOURCE), mActiveModeWarden.getSecondaryRequestWs()); 3116 } 3117 return additionalClientListener.value; 3118 } 3119 3120 @Test testRemoveDefaultClientModeManager()3121 public void testRemoveDefaultClientModeManager() throws Exception { 3122 // Ensure that we can create more client ifaces. 3123 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3124 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3125 .thenReturn(true); 3126 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3127 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3128 3129 // Verify removing a non DefaultClientModeManager works properly. 3130 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_LOCAL_ONLY); 3131 3132 // Verify that a request to remove DefaultClientModeManager is ignored. 3133 ClientModeManager defaultClientModeManager = mock(DefaultClientModeManager.class); 3134 3135 mActiveModeWarden.removeClientModeManager(defaultClientModeManager); 3136 mLooper.dispatchAll(); 3137 verify(defaultClientModeManager, never()).stop(); 3138 } 3139 requestRemoveAdditionalClientModeManager( ClientConnectivityRole role)3140 private void requestRemoveAdditionalClientModeManager( 3141 ClientConnectivityRole role) throws Exception { 3142 ConcreteClientModeManager additionalClientModeManager = 3143 mock(ConcreteClientModeManager.class); 3144 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3145 ExternalClientModeManagerRequestListener.class); 3146 Listener<ConcreteClientModeManager> additionalClientListener = 3147 requestAdditionalClientModeManager(role, additionalClientModeManager, 3148 externalRequestListener, TEST_SSID_2, TEST_BSSID_2); 3149 3150 mActiveModeWarden.removeClientModeManager(additionalClientModeManager); 3151 mLooper.dispatchAll(); 3152 verify(additionalClientModeManager).stop(); 3153 additionalClientListener.onStopped(additionalClientModeManager); 3154 mLooper.dispatchAll(); 3155 verify(mModeChangeCallback).onActiveModeManagerRemoved(additionalClientModeManager); 3156 // the additional CMM still never became primary 3157 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 3158 } 3159 requestRemoveAdditionalClientModeManagerWhenNotAllowed( ClientConnectivityRole role, boolean clientIsExpected, long featureSet)3160 private void requestRemoveAdditionalClientModeManagerWhenNotAllowed( 3161 ClientConnectivityRole role, boolean clientIsExpected, 3162 long featureSet) throws Exception { 3163 enterClientModeActiveState(false, featureSet); 3164 3165 // Connected to ssid1/bssid1 3166 WifiConfiguration config1 = new WifiConfiguration(); 3167 config1.SSID = TEST_SSID_1; 3168 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3169 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3170 3171 ConcreteClientModeManager additionalClientModeManager = 3172 mock(ConcreteClientModeManager.class); 3173 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3174 new Mutable<>(); 3175 doAnswer((invocation) -> { 3176 Object[] args = invocation.getArguments(); 3177 additionalClientListener.value = 3178 (Listener<ConcreteClientModeManager>) args[0]; 3179 return additionalClientModeManager; 3180 }).when(mWifiInjector).makeClientModeManager( 3181 any(Listener.class), any(), any(), anyBoolean()); 3182 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 3183 when(additionalClientModeManager.getRole()).thenReturn(role); 3184 3185 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3186 ExternalClientModeManagerRequestListener.class); 3187 // request for ssid2/bssid2 3188 if (role == ROLE_CLIENT_LOCAL_ONLY) { 3189 mActiveModeWarden.requestLocalOnlyClientModeManager( 3190 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 3191 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3192 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3193 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3194 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3195 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3196 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3197 } 3198 mLooper.dispatchAll(); 3199 verifyNoMoreInteractions(additionalClientModeManager); 3200 // Returns the existing primary client mode manager. 3201 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3202 ArgumentCaptor.forClass(ClientModeManager.class); 3203 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3204 if (clientIsExpected) { 3205 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 3206 3207 mActiveModeWarden.removeClientModeManager(requestedClientModeManager.getValue()); 3208 } else { 3209 assertNull(requestedClientModeManager.getValue()); 3210 } 3211 mLooper.dispatchAll(); 3212 verifyNoMoreInteractions(additionalClientModeManager); 3213 } 3214 requestAdditionalClientModeManagerWhenWifiIsOff( ClientConnectivityRole role)3215 private void requestAdditionalClientModeManagerWhenWifiIsOff( 3216 ClientConnectivityRole role) throws Exception { 3217 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3218 ExternalClientModeManagerRequestListener.class); 3219 if (role == ROLE_CLIENT_LOCAL_ONLY) { 3220 mActiveModeWarden.requestLocalOnlyClientModeManager( 3221 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1, false); 3222 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3223 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3224 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 3225 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3226 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3227 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 3228 } 3229 mLooper.dispatchAll(); 3230 3231 verify(externalRequestListener).onAnswer(null); 3232 } 3233 requestAdditionalClientModeManagerWhenAlreadyPresent( ClientConnectivityRole role)3234 public void requestAdditionalClientModeManagerWhenAlreadyPresent( 3235 ClientConnectivityRole role) throws Exception { 3236 ConcreteClientModeManager additionalClientModeManager = 3237 mock(ConcreteClientModeManager.class); 3238 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3239 ExternalClientModeManagerRequestListener.class); 3240 requestAdditionalClientModeManager(role, additionalClientModeManager, 3241 externalRequestListener, TEST_SSID_2, TEST_BSSID_2); 3242 3243 // set additional CMM connected to ssid2/bssid2 3244 WifiConfiguration config2 = new WifiConfiguration(); 3245 config2.SSID = TEST_SSID_2; 3246 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3247 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3248 3249 // request for ssid3/bssid3 3250 // request for one more CMM (returns the existing one). 3251 if (role == ROLE_CLIENT_LOCAL_ONLY) { 3252 mActiveModeWarden.requestLocalOnlyClientModeManager( 3253 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3, false); 3254 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3255 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3256 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3); 3257 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3258 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3259 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3); 3260 } 3261 mLooper.dispatchAll(); 3262 3263 // Don't make another client mode manager. 3264 verify(mWifiInjector, times(1)) 3265 .makeClientModeManager(any(), any(), eq(role), anyBoolean()); 3266 // Returns the existing client mode manager. 3267 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3268 ArgumentCaptor.forClass(ClientModeManager.class); 3269 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3270 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3271 } 3272 requestAdditionalClientModeManagerWhenAlreadyPresentSameBssid( ClientConnectivityRole role)3273 public void requestAdditionalClientModeManagerWhenAlreadyPresentSameBssid( 3274 ClientConnectivityRole role) throws Exception { 3275 ConcreteClientModeManager additionalClientModeManager = 3276 mock(ConcreteClientModeManager.class); 3277 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3278 ExternalClientModeManagerRequestListener.class); 3279 requestAdditionalClientModeManager(role, additionalClientModeManager, 3280 externalRequestListener, TEST_SSID_2, TEST_BSSID_2); 3281 3282 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3283 ArgumentCaptor.forClass(ClientModeManager.class); 3284 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3285 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3286 3287 // set additional CMM connected to ssid2/bssid2 3288 WifiConfiguration config2 = new WifiConfiguration(); 3289 config2.SSID = TEST_SSID_2; 3290 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3291 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3292 3293 // request for the same SSID/BSSID and expect the existing CMM to get returned twice. 3294 if (role == ROLE_CLIENT_LOCAL_ONLY) { 3295 mActiveModeWarden.requestLocalOnlyClientModeManager( 3296 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 3297 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3298 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3299 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3300 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3301 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3302 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3303 } 3304 mLooper.dispatchAll(); 3305 3306 // Don't make another client mode manager. 3307 verify(mWifiInjector, times(1)) 3308 .makeClientModeManager(any(), any(), eq(role), anyBoolean()); 3309 // Returns the existing client mode manager. 3310 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3311 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3312 } 3313 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( ClientConnectivityRole role)3314 private void requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 3315 ClientConnectivityRole role) throws Exception { 3316 enterClientModeActiveState(); 3317 3318 // Connected to ssid1/bssid1 3319 WifiConfiguration config1 = new WifiConfiguration(); 3320 config1.SSID = TEST_SSID_1; 3321 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3322 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3323 3324 ConcreteClientModeManager additionalClientModeManager = 3325 mock(ConcreteClientModeManager.class); 3326 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3327 new Mutable<>(); 3328 doAnswer((invocation) -> { 3329 Object[] args = invocation.getArguments(); 3330 additionalClientListener.value = 3331 (Listener<ConcreteClientModeManager>) args[0]; 3332 return additionalClientModeManager; 3333 }).when(mWifiInjector).makeClientModeManager( 3334 any(Listener.class), any(), any(), anyBoolean()); 3335 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 3336 when(additionalClientModeManager.getRole()).thenReturn(role); 3337 3338 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3339 ExternalClientModeManagerRequestListener.class); 3340 // request for same ssid1/bssid1 3341 if (role == ROLE_CLIENT_LOCAL_ONLY) { 3342 mActiveModeWarden.requestLocalOnlyClientModeManager( 3343 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1, false); 3344 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 3345 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 3346 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 3347 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 3348 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3349 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 3350 } 3351 mLooper.dispatchAll(); 3352 verifyNoMoreInteractions(additionalClientModeManager); 3353 // Returns the existing primary client mode manager. 3354 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3355 ArgumentCaptor.forClass(ClientModeManager.class); 3356 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3357 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 3358 } 3359 3360 @Test requestRemoveLocalOnlyClientModeManager()3361 public void requestRemoveLocalOnlyClientModeManager() throws Exception { 3362 // Ensure that we can create more client ifaces. 3363 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3364 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3365 .thenReturn(true); 3366 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3367 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3368 3369 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_LOCAL_ONLY); 3370 } 3371 3372 @Test requestRemoveLocalOnlyClientModeManagerWhenStaStaNotSupported()3373 public void requestRemoveLocalOnlyClientModeManagerWhenStaStaNotSupported() throws Exception { 3374 // Ensure that we cannot create more client ifaces. 3375 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3376 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3377 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3378 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, true, 3379 TEST_FEATURE_SET); 3380 } 3381 3382 @Test requestRemoveLocalOnlyClientModeManagerWhenFeatureDisabled()3383 public void requestRemoveLocalOnlyClientModeManagerWhenFeatureDisabled() throws Exception { 3384 // Ensure that we can create more client ifaces. 3385 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3386 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3387 .thenReturn(false); 3388 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3389 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3390 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, true, 3391 TEST_FEATURE_SET); 3392 } 3393 3394 @Test testRequestSecondaryClientModeManagerWhenWifiIsDisabling()3395 public void testRequestSecondaryClientModeManagerWhenWifiIsDisabling() 3396 throws Exception { 3397 // Ensure that we can create more client ifaces. 3398 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3399 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3400 .thenReturn(true); 3401 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3402 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3403 3404 // Set wifi to disabling and verify secondary CMM is not obtained 3405 mActiveModeWarden.setWifiStateForApiCalls(WIFI_STATE_DISABLING); 3406 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3407 ExternalClientModeManagerRequestListener.class); 3408 mActiveModeWarden.requestLocalOnlyClientModeManager( 3409 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1, false); 3410 mLooper.dispatchAll(); 3411 3412 verify(externalRequestListener).onAnswer(null); 3413 } 3414 3415 @Test requestLocalOnlyClientModeManagerWhenWifiIsOff()3416 public void requestLocalOnlyClientModeManagerWhenWifiIsOff() throws Exception { 3417 // Ensure that we can create more client ifaces. 3418 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3419 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3420 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3421 3422 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_LOCAL_ONLY); 3423 } 3424 3425 @Test requestLocalOnlyClientModeManagerWhenAlreadyPresent()3426 public void requestLocalOnlyClientModeManagerWhenAlreadyPresent() throws Exception { 3427 // Ensure that we can create more client ifaces. 3428 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3429 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3430 .thenReturn(true); 3431 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3432 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3433 3434 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_LOCAL_ONLY); 3435 } 3436 3437 @Test requestLocalOnlyClientModeManagerWhenAlreadyPresentSameBssid()3438 public void requestLocalOnlyClientModeManagerWhenAlreadyPresentSameBssid() throws Exception { 3439 // Ensure that we can create more client ifaces. 3440 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3441 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3442 .thenReturn(true); 3443 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3444 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3445 3446 requestAdditionalClientModeManagerWhenAlreadyPresentSameBssid(ROLE_CLIENT_LOCAL_ONLY); 3447 } 3448 3449 @Test requestLocalOnlyClientModeManagerWhenConnectingToPrimaryBssid()3450 public void requestLocalOnlyClientModeManagerWhenConnectingToPrimaryBssid() throws Exception { 3451 // Ensure that we can create more client ifaces. 3452 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3453 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3454 .thenReturn(true); 3455 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3456 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3457 3458 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid(ROLE_CLIENT_LOCAL_ONLY); 3459 } 3460 3461 @Test requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkLessThanS()3462 public void requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkLessThanS() 3463 throws Exception { 3464 // Ensure that we can create more client ifaces. 3465 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3466 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3467 .thenReturn(true); 3468 3469 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 3470 when(mWifiPermissionsUtil.isTargetSdkLessThan( 3471 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 3472 .thenReturn(true); 3473 when(mWifiPermissionsUtil.isTargetSdkLessThan( 3474 "system-service", Build.VERSION_CODES.S, Process.SYSTEM_UID)) 3475 .thenReturn(false); 3476 // Simulate explicit user approval 3477 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3478 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, true)); 3479 WorkSource workSource = new WorkSource(TEST_WORKSOURCE); 3480 workSource.add(SETTINGS_WORKSOURCE); 3481 verify(mWifiNative).isItPossibleToCreateStaIface(eq(workSource)); 3482 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, 3483 true, TEST_FEATURE_SET); 3484 } 3485 3486 @Test requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkEqualToS()3487 public void requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkEqualToS() 3488 throws Exception { 3489 // Ensure that we can create more client ifaces. 3490 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3491 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3492 .thenReturn(true); 3493 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 3494 when(mWifiPermissionsUtil.isTargetSdkLessThan( 3495 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 3496 .thenReturn(false); 3497 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3498 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3499 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_LOCAL_ONLY); 3500 } 3501 3502 @Test requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkLessThanSAndCantCreate()3503 public void requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkLessThanSAndCantCreate() 3504 throws Exception { 3505 // Ensure that we can't create more client ifaces - so will attempt to fallback (which we 3506 // should be able to do for <S apps) 3507 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); 3508 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3509 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3510 .thenReturn(true); 3511 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 3512 when(mWifiPermissionsUtil.isTargetSdkLessThan( 3513 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 3514 .thenReturn(true); 3515 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3516 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3517 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, 3518 true, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY); 3519 } 3520 testLoFallbackAboveAndroidS(boolean isStaStaSupported)3521 private void testLoFallbackAboveAndroidS(boolean isStaStaSupported) throws Exception { 3522 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(isStaStaSupported); 3523 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3524 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3525 .thenReturn(true); 3526 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 3527 when(mWifiPermissionsUtil.isTargetSdkLessThan( 3528 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 3529 .thenReturn(false); 3530 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3531 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3532 long expectedFeatureSet = TEST_FEATURE_SET; 3533 if (isStaStaSupported) { 3534 expectedFeatureSet |= WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY; 3535 } 3536 3537 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY, 3538 !isStaStaSupported, 3539 expectedFeatureSet); 3540 } 3541 3542 @Test requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkEqualToSAndCantCreate()3543 public void requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkEqualToSAndCantCreate() 3544 throws Exception { 3545 // Ensure that we can't create more client ifaces - so will attempt to fallback (which we 3546 // can't for >=S apps) 3547 testLoFallbackAboveAndroidS(true); 3548 } 3549 3550 @Test requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkEqualToSAndCantCreate2()3551 public void requestRemoveLoClientModeManagerWhenNotSystemAppAndTargetSdkEqualToSAndCantCreate2() 3552 throws Exception { 3553 // Ensure that we can't create more client ifaces and STA+STA is not supported, we 3554 // fallback even for >=S apps 3555 testLoFallbackAboveAndroidS(false); 3556 } 3557 3558 @Test requestRemoveSecondaryLongLivedClientModeManager()3559 public void requestRemoveSecondaryLongLivedClientModeManager() throws Exception { 3560 // Ensure that we can create more client ifaces. 3561 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3562 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3563 .thenReturn(true); 3564 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3565 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3566 3567 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_LONG_LIVED); 3568 } 3569 3570 @Test requestRemoveSecondaryLongLivedClientModeManagerWhenStaStaNotSupported()3571 public void requestRemoveSecondaryLongLivedClientModeManagerWhenStaStaNotSupported() 3572 throws Exception { 3573 // Ensure that we cannot create more client ifaces. 3574 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3575 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3576 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3577 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_LONG_LIVED, 3578 true, TEST_FEATURE_SET); 3579 } 3580 3581 @Test requestRemoveSecondaryLongLivedClientModeManagerWhenFeatureDisabled()3582 public void requestRemoveSecondaryLongLivedClientModeManagerWhenFeatureDisabled() 3583 throws Exception { 3584 // Ensure that we can create more client ifaces. 3585 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3586 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3587 .thenReturn(false); 3588 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3589 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3590 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_LONG_LIVED, 3591 true, TEST_FEATURE_SET); 3592 } 3593 3594 @Test requestSecondaryLongLivedClientModeManagerWhenWifiIsOff()3595 public void requestSecondaryLongLivedClientModeManagerWhenWifiIsOff() throws Exception { 3596 // Ensure that we can create more client ifaces. 3597 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3598 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3599 .thenReturn(true); 3600 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3601 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3602 3603 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_SECONDARY_LONG_LIVED); 3604 } 3605 3606 @Test requestSecondaryLongLivedClientModeManagerWhenAlreadyPresent()3607 public void requestSecondaryLongLivedClientModeManagerWhenAlreadyPresent() throws Exception { 3608 // Ensure that we can create more client ifaces. 3609 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3610 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3611 .thenReturn(true); 3612 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3613 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3614 3615 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_SECONDARY_LONG_LIVED); 3616 } 3617 3618 @Test requestSecondaryLongLivedClientModeManagerWhenAlreadyPresentSameBssid()3619 public void requestSecondaryLongLivedClientModeManagerWhenAlreadyPresentSameBssid() 3620 throws Exception { 3621 // Ensure that we can create more client ifaces. 3622 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3623 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3624 .thenReturn(true); 3625 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3626 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3627 3628 requestAdditionalClientModeManagerWhenAlreadyPresentSameBssid( 3629 ROLE_CLIENT_SECONDARY_LONG_LIVED); 3630 } 3631 3632 @Test requestSecondaryLongLivedClientModeManagerWhenConnectingToPrimaryBssid()3633 public void requestSecondaryLongLivedClientModeManagerWhenConnectingToPrimaryBssid() 3634 throws Exception { 3635 // Ensure that we can create more client ifaces. 3636 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3637 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3638 .thenReturn(true); 3639 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3640 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3641 3642 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 3643 ROLE_CLIENT_SECONDARY_LONG_LIVED); 3644 } 3645 3646 @Test requestRemoveSecondaryTransientClientModeManager()3647 public void requestRemoveSecondaryTransientClientModeManager() throws Exception { 3648 // Ensure that we can create more client ifaces. 3649 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3650 when(mResources.getBoolean( 3651 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3652 .thenReturn(true); 3653 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3654 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3655 3656 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_TRANSIENT); 3657 } 3658 3659 @Test requestRemoveSecondaryTransientClientModeManagerWhenStaStaNotSupported()3660 public void requestRemoveSecondaryTransientClientModeManagerWhenStaStaNotSupported() 3661 throws Exception { 3662 // Ensure that we cannot create more client ifaces. 3663 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3664 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3665 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3666 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_TRANSIENT, 3667 true, TEST_FEATURE_SET); 3668 } 3669 3670 @Test requestRemoveSecondaryTransientClientModeManagerWhenFeatureDisabled()3671 public void requestRemoveSecondaryTransientClientModeManagerWhenFeatureDisabled() 3672 throws Exception { 3673 // Ensure that we can create more client ifaces. 3674 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3675 when(mResources.getBoolean( 3676 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3677 .thenReturn(false); 3678 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3679 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3680 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_TRANSIENT, 3681 true, TEST_FEATURE_SET); 3682 } 3683 3684 @Test requestSecondaryTransientClientModeManagerWhenWifiIsOff()3685 public void requestSecondaryTransientClientModeManagerWhenWifiIsOff() throws Exception { 3686 // Ensure that we can create more client ifaces. 3687 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3688 when(mResources.getBoolean( 3689 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3690 .thenReturn(true); 3691 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3692 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3693 3694 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_SECONDARY_TRANSIENT); 3695 } 3696 3697 @Test requestSecondaryTransientClientModeManagerWhenAlreadyPresent()3698 public void requestSecondaryTransientClientModeManagerWhenAlreadyPresent() throws Exception { 3699 // Ensure that we can create more client ifaces. 3700 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3701 when(mResources.getBoolean( 3702 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3703 .thenReturn(true); 3704 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3705 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3706 3707 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_SECONDARY_TRANSIENT); 3708 } 3709 3710 @Test requestSecondaryTransientClientModeManagerWhenAlreadyPresentSameBssid()3711 public void requestSecondaryTransientClientModeManagerWhenAlreadyPresentSameBssid() 3712 throws Exception { 3713 // Ensure that we can create more client ifaces. 3714 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3715 when(mResources.getBoolean( 3716 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3717 .thenReturn(true); 3718 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3719 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3720 3721 requestAdditionalClientModeManagerWhenAlreadyPresentSameBssid( 3722 ROLE_CLIENT_SECONDARY_TRANSIENT); 3723 } 3724 3725 @Test requestSecondaryTransientClientModeManagerWhenConnectingToPrimaryBssid()3726 public void requestSecondaryTransientClientModeManagerWhenConnectingToPrimaryBssid() 3727 throws Exception { 3728 // Ensure that we can create more client ifaces. 3729 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3730 when(mResources.getBoolean( 3731 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3732 .thenReturn(true); 3733 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3734 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3735 3736 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 3737 ROLE_CLIENT_SECONDARY_TRANSIENT); 3738 } 3739 3740 @Test requestHighPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid()3741 public void requestHighPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid() 3742 throws Exception { 3743 // Ensure that we can create more client ifaces. 3744 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3745 when(mResources.getBoolean( 3746 R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3747 .thenReturn(true); 3748 when(mResources.getBoolean( 3749 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3750 .thenReturn(true); 3751 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3752 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3753 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3754 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3755 3756 enterClientModeActiveState(); 3757 3758 // Primary Connected to ssid1/bssid1 3759 WifiConfiguration config1 = new WifiConfiguration(); 3760 config1.SSID = TEST_SSID_1; 3761 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3762 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3763 3764 ConcreteClientModeManager additionalClientModeManager = 3765 mock(ConcreteClientModeManager.class); 3766 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener1 = 3767 new Mutable<>(); 3768 doAnswer((invocation) -> { 3769 Object[] args = invocation.getArguments(); 3770 additionalClientListener1.value = 3771 (Listener<ConcreteClientModeManager>) args[0]; 3772 return additionalClientModeManager; 3773 }).when(mWifiInjector).makeClientModeManager( 3774 any(Listener.class), any(), eq(ROLE_CLIENT_LOCAL_ONLY), 3775 anyBoolean()); 3776 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 3777 3778 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3779 ExternalClientModeManagerRequestListener.class); 3780 // request for ssid2/bssid2 3781 mActiveModeWarden.requestLocalOnlyClientModeManager( 3782 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 3783 mLooper.dispatchAll(); 3784 verify(mWifiInjector).makeClientModeManager( 3785 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 3786 additionalClientListener1.value.onStarted(additionalClientModeManager); 3787 mLooper.dispatchAll(); 3788 // Returns the new client mode manager. 3789 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3790 ArgumentCaptor.forClass(ClientModeManager.class); 3791 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3792 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3793 3794 // set additional CMM connected to ssid2/bssid2 3795 WifiConfiguration config2 = new WifiConfiguration(); 3796 config2.SSID = TEST_SSID_2; 3797 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3798 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3799 3800 // request for same ssid2/bssid2 for a different role. 3801 // request for one more CMM (should return the existing local only one). 3802 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3803 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3804 mLooper.dispatchAll(); 3805 3806 // Don't make another client mode manager, but should switch role of existing client mode 3807 // manager. 3808 verify(mWifiInjector, never()) 3809 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3810 anyBoolean()); 3811 ArgumentCaptor<Listener<ConcreteClientModeManager>> 3812 additionalClientListener2 = ArgumentCaptor.forClass( 3813 Listener.class); 3814 verify(additionalClientModeManager).setRole(eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3815 eq(TEST_WORKSOURCE), additionalClientListener2.capture()); 3816 3817 // Simulate completion of role switch. 3818 additionalClientListener2.getValue().onRoleChanged(additionalClientModeManager); 3819 3820 // Returns the existing client mode manager. 3821 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3822 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3823 } 3824 3825 @Test requestLowPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid()3826 public void requestLowPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid() 3827 throws Exception { 3828 // Ensure that we can create more client ifaces. 3829 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3830 when(mResources.getBoolean( 3831 R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3832 .thenReturn(true); 3833 when(mResources.getBoolean( 3834 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3835 .thenReturn(true); 3836 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3837 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3838 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3839 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3840 3841 enterClientModeActiveState(); 3842 3843 // Primary Connected to ssid1/bssid1 3844 WifiConfiguration config1 = new WifiConfiguration(); 3845 config1.SSID = TEST_SSID_1; 3846 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3847 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3848 3849 ConcreteClientModeManager additionalClientModeManager = 3850 mock(ConcreteClientModeManager.class); 3851 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener1 = 3852 new Mutable<>(); 3853 doAnswer((invocation) -> { 3854 Object[] args = invocation.getArguments(); 3855 additionalClientListener1.value = 3856 (Listener<ConcreteClientModeManager>) args[0]; 3857 return additionalClientModeManager; 3858 }).when(mWifiInjector).makeClientModeManager( 3859 any(Listener.class), any(), eq(ROLE_CLIENT_LOCAL_ONLY), 3860 anyBoolean()); 3861 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 3862 3863 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3864 ExternalClientModeManagerRequestListener.class); 3865 // request for ssid2/bssid2 3866 mActiveModeWarden.requestLocalOnlyClientModeManager( 3867 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 3868 mLooper.dispatchAll(); 3869 verify(mWifiInjector).makeClientModeManager( 3870 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 3871 additionalClientListener1.value.onStarted(additionalClientModeManager); 3872 mLooper.dispatchAll(); 3873 // Returns the new client mode manager. 3874 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3875 ArgumentCaptor.forClass(ClientModeManager.class); 3876 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3877 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3878 3879 // set additional CMM connected to ssid2/bssid2 3880 WifiConfiguration config2 = new WifiConfiguration(); 3881 config2.SSID = TEST_SSID_2; 3882 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3883 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3884 3885 // Now, deny the creation of STA for the new request 3886 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3887 3888 // request for same ssid2/bssid2 for a different role. 3889 // request for one more CMM (should return null). 3890 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3891 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3892 mLooper.dispatchAll(); 3893 3894 // Don't make another client mode manager or change role 3895 verify(mWifiInjector, never()) 3896 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3897 anyBoolean()); 3898 verify(additionalClientModeManager, never()).setRole(eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3899 eq(TEST_WORKSOURCE), any()); 3900 3901 // Ensure the request is rejected. 3902 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3903 assertNull(requestedClientModeManager.getValue()); 3904 } 3905 3906 @Test requestSecondaryTransientClientModeManagerWhenDppInProgress()3907 public void requestSecondaryTransientClientModeManagerWhenDppInProgress() 3908 throws Exception { 3909 // Ensure that we can create more client ifaces. 3910 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3911 when(mResources.getBoolean( 3912 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3913 .thenReturn(true); 3914 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3915 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 3916 3917 // Create primary STA. 3918 enterClientModeActiveState(); 3919 3920 // Start DPP session 3921 when(mDppManager.isSessionInProgress()).thenReturn(true); 3922 3923 // request secondary transient CMM creation. 3924 ConcreteClientModeManager additionalClientModeManager = 3925 mock(ConcreteClientModeManager.class); 3926 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3927 new Mutable<>(); 3928 doAnswer((invocation) -> { 3929 Object[] args = invocation.getArguments(); 3930 additionalClientListener.value = 3931 (Listener<ConcreteClientModeManager>) args[0]; 3932 return additionalClientModeManager; 3933 }).when(mWifiInjector).makeClientModeManager( 3934 any(Listener.class), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3935 anyBoolean()); 3936 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 3937 3938 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3939 ExternalClientModeManagerRequestListener.class); 3940 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3941 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3942 mLooper.dispatchAll(); 3943 3944 // verify that we did not create a secondary CMM. 3945 verifyNoMoreInteractions(additionalClientModeManager); 3946 // Returns the existing primary client mode manager. 3947 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3948 ArgumentCaptor.forClass(ClientModeManager.class); 3949 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3950 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 3951 3952 // Stop ongoing DPP session. 3953 when(mDppManager.isSessionInProgress()).thenReturn(false); 3954 3955 // request secondary transient CMM creation again, now it should be allowed. 3956 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3957 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3958 mLooper.dispatchAll(); 3959 verify(mWifiInjector) 3960 .makeClientModeManager(any(), eq(TEST_WORKSOURCE), 3961 eq(ROLE_CLIENT_SECONDARY_TRANSIENT), anyBoolean()); 3962 additionalClientListener.value.onStarted(additionalClientModeManager); 3963 mLooper.dispatchAll(); 3964 // Returns the new secondary client mode manager. 3965 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3966 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3967 } 3968 3969 @Test testRequestForSecondaryLocalOnlyForEnterCarModePrioritized()3970 public void testRequestForSecondaryLocalOnlyForEnterCarModePrioritized() throws Exception { 3971 // mock caller to have ENTER_CAR_MODE_PRIORITIZED 3972 when(mWifiPermissionsUtil.checkEnterCarModePrioritized(anyInt())).thenReturn(true); 3973 // Ensure that we can create more client ifaces. 3974 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3975 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3976 .thenReturn(true); 3977 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3978 .thenReturn(true); 3979 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3980 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 3981 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3982 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 3983 3984 enterClientModeActiveState(); 3985 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3986 ArgumentCaptor.forClass(ClientModeManager.class); 3987 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3988 ExternalClientModeManagerRequestListener.class); 3989 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3990 new Mutable<>(); 3991 ConcreteClientModeManager additionalClientModeManager = 3992 mock(ConcreteClientModeManager.class); 3993 doAnswer((invocation) -> { 3994 Object[] args = invocation.getArguments(); 3995 additionalClientListener.value = 3996 (Listener<ConcreteClientModeManager>) args[0]; 3997 return additionalClientModeManager; 3998 }).when(mWifiInjector).makeClientModeManager( 3999 any(Listener.class), any(), any(), anyBoolean()); 4000 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 4001 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 4002 4003 // mock requesting local only secondary 4004 mActiveModeWarden.requestLocalOnlyClientModeManager( 4005 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 4006 mLooper.dispatchAll(); 4007 // Verify the primary is given to the externalRequestListener 4008 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 4009 verify(mWifiInjector, never()).makeClientModeManager( 4010 any(), any(), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 4011 assertEquals(ROLE_CLIENT_PRIMARY, requestedClientModeManager.getValue().getRole()); 4012 4013 // Request for non local-only STA and verify the secondary STA is provided instead. 4014 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); 4015 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 4016 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 4017 mLooper.dispatchAll(); 4018 verify(mWifiInjector).makeClientModeManager(any(), any(), 4019 eq(ROLE_CLIENT_SECONDARY_LONG_LIVED), anyBoolean()); 4020 4021 additionalClientListener.value.onStarted(additionalClientModeManager); 4022 mLooper.dispatchAll(); 4023 verify(externalRequestListener, times(2)).onAnswer( 4024 requestedClientModeManager.capture()); 4025 assertEquals(ROLE_CLIENT_SECONDARY_LONG_LIVED, 4026 requestedClientModeManager.getValue().getRole()); 4027 } 4028 4029 @Test testRequestForSecondaryLocalOnlyForShell()4030 public void testRequestForSecondaryLocalOnlyForShell() throws Exception { 4031 // mock caller to have ENTER_CAR_MODE_PRIORITIZED 4032 when(mWifiPermissionsUtil.checkEnterCarModePrioritized(anyInt())).thenReturn(true); 4033 // Ensure that we can create more client ifaces. 4034 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4035 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 4036 .thenReturn(true); 4037 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 4038 .thenReturn(true); 4039 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4040 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, false)); 4041 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4042 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 4043 4044 enterClientModeActiveState(); 4045 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 4046 ArgumentCaptor.forClass(ClientModeManager.class); 4047 ExternalClientModeManagerRequestListener externalRequestListener = mock( 4048 ExternalClientModeManagerRequestListener.class); 4049 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 4050 new Mutable<>(); 4051 ConcreteClientModeManager additionalClientModeManager = 4052 mock(ConcreteClientModeManager.class); 4053 doAnswer((invocation) -> { 4054 Object[] args = invocation.getArguments(); 4055 additionalClientListener.value = 4056 (Listener<ConcreteClientModeManager>) args[0]; 4057 return additionalClientModeManager; 4058 }).when(mWifiInjector).makeClientModeManager( 4059 any(Listener.class), any(), any(), anyBoolean()); 4060 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 4061 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 4062 4063 // Request will shell uid for local-only STA and verify the secondary is provided instead. 4064 WorkSource shellWs = new WorkSource(0, "shell"); 4065 mActiveModeWarden.requestLocalOnlyClientModeManager( 4066 externalRequestListener, shellWs, TEST_SSID_2, TEST_BSSID_2, false); 4067 mLooper.dispatchAll(); 4068 verify(mWifiInjector).makeClientModeManager(any(), any(), 4069 eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 4070 additionalClientListener.value.onStarted(additionalClientModeManager); 4071 mLooper.dispatchAll(); 4072 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 4073 verify(mWifiInjector).makeClientModeManager( 4074 any(), any(), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 4075 assertEquals(ROLE_CLIENT_LOCAL_ONLY, requestedClientModeManager.getValue().getRole()); 4076 } 4077 4078 @Test configureHwOnMbbSwitch()4079 public void configureHwOnMbbSwitch() 4080 throws Exception { 4081 // Ensure that we can create more client ifaces. 4082 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4083 when(mResources.getBoolean( 4084 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 4085 .thenReturn(true); 4086 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4087 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 4088 4089 ConcreteClientModeManager additionalClientModeManager = 4090 mock(ConcreteClientModeManager.class); 4091 ExternalClientModeManagerRequestListener externalRequestListener = mock( 4092 ExternalClientModeManagerRequestListener.class); 4093 Listener<ConcreteClientModeManager> additionalClientListener = 4094 requestAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_TRANSIENT, 4095 additionalClientModeManager, externalRequestListener, TEST_SSID_2, 4096 TEST_BSSID_2); 4097 4098 // Now simulate the MBB role switch. 4099 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 4100 mClientListener.onRoleChanged(mClientModeManager); 4101 4102 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 4103 additionalClientListener.onRoleChanged(additionalClientModeManager); 4104 4105 // verify last use case set is PREFER_PRIMARY 4106 ArgumentCaptor<Integer> useCaseCaptor = ArgumentCaptor.forClass(Integer.class); 4107 verify(mWifiNative, atLeastOnce()).setMultiStaUseCase(useCaseCaptor.capture()); 4108 int lastUseCaseSet = useCaseCaptor.getValue().intValue(); 4109 assertEquals(WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY, lastUseCaseSet); 4110 4111 // verify last set of primary connection is for WIFI_IFACE_NAME_1 4112 ArgumentCaptor<String> ifaceNameCaptor = ArgumentCaptor.forClass(String.class); 4113 verify(mWifiNative, atLeastOnce()).setMultiStaPrimaryConnection(ifaceNameCaptor.capture()); 4114 assertEquals(WIFI_IFACE_NAME_1, ifaceNameCaptor.getValue()); 4115 } 4116 4117 @Test airplaneModeToggleOnDisablesWifi()4118 public void airplaneModeToggleOnDisablesWifi() throws Exception { 4119 enterClientModeActiveState(); 4120 assertInEnabledState(); 4121 4122 assertWifiShutDown(() -> { 4123 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 4124 mActiveModeWarden.airplaneModeToggled(); 4125 mLooper.dispatchAll(); 4126 }); 4127 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), anyInt(), 4128 anyInt(), eq("android_apm"), eq(false)); 4129 4130 mClientListener.onStopped(mClientModeManager); 4131 mLooper.dispatchAll(); 4132 assertInDisabledState(); 4133 } 4134 4135 @Test testGetActiveModeManagersOrder()4136 public void testGetActiveModeManagersOrder() throws Exception { 4137 enableWifi(); 4138 enterSoftApActiveMode(); 4139 assertInEnabledState(); 4140 4141 Collection<ActiveModeManager> activeModeManagers = 4142 mActiveModeWarden.getActiveModeManagers(); 4143 if (activeModeManagers == null) { 4144 fail("activeModeManagers list should not be null"); 4145 } 4146 Object[] modeManagers = activeModeManagers.toArray(); 4147 assertEquals(2, modeManagers.length); 4148 assertTrue(modeManagers[0] instanceof SoftApManager); 4149 assertTrue(modeManagers[1] instanceof ConcreteClientModeManager); 4150 } 4151 4152 @Test airplaneModeToggleOnDisablesSoftAp()4153 public void airplaneModeToggleOnDisablesSoftAp() throws Exception { 4154 enterSoftApActiveMode(); 4155 assertInEnabledState(); 4156 4157 assertWifiShutDown(() -> { 4158 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 4159 mActiveModeWarden.airplaneModeToggled(); 4160 mLooper.dispatchAll(); 4161 }); 4162 4163 mSoftApListener.onStopped(mSoftApManager); 4164 mLooper.dispatchAll(); 4165 assertInDisabledState(); 4166 } 4167 4168 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager()4169 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager() 4170 throws Exception { 4171 enterClientModeActiveState(); 4172 assertInEnabledState(); 4173 4174 // APM toggle on 4175 assertWifiShutDown(() -> { 4176 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 4177 mActiveModeWarden.airplaneModeToggled(); 4178 mLooper.dispatchAll(); 4179 }); 4180 4181 4182 // APM toggle off before the stop is complete. 4183 assertInEnabledState(); 4184 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 4185 mActiveModeWarden.airplaneModeToggled(); 4186 mLooper.dispatchAll(); 4187 4188 mClientListener.onStopped(mClientModeManager); 4189 mLooper.dispatchAll(); 4190 4191 verify(mWifiInjector, times(2)).makeClientModeManager( 4192 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 4193 4194 mClientListener.onStarted(mClientModeManager); 4195 mLooper.dispatchAll(); 4196 4197 // We should be back to enabled state. 4198 assertInEnabledState(); 4199 } 4200 4201 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2()4202 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2() 4203 throws Exception { 4204 enterClientModeActiveState(); 4205 assertInEnabledState(); 4206 4207 // APM toggle on 4208 assertWifiShutDown(() -> { 4209 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 4210 mActiveModeWarden.airplaneModeToggled(); 4211 mLooper.dispatchAll(); 4212 }); 4213 4214 4215 // APM toggle off before the stop is complete. 4216 assertInEnabledState(); 4217 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 4218 mActiveModeWarden.airplaneModeToggled(); 4219 // This test is identical to 4220 // airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager, except the 4221 // dispatchAll() here is removed. There could be a race between airplaneModeToggled and 4222 // mClientListener.onStopped(). See b/160105640#comment5. 4223 4224 mClientListener.onStopped(mClientModeManager); 4225 mLooper.dispatchAll(); 4226 4227 verify(mWifiInjector, times(2)).makeClientModeManager( 4228 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 4229 4230 mClientListener.onStarted(mClientModeManager); 4231 mLooper.dispatchAll(); 4232 4233 // We should be back to enabled state. 4234 assertInEnabledState(); 4235 } 4236 4237 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager()4238 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager() 4239 throws Exception { 4240 enterClientModeActiveState(); 4241 enterSoftApActiveMode(); 4242 assertInEnabledState(); 4243 4244 // APM toggle on 4245 assertWifiShutDown(() -> { 4246 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 4247 mActiveModeWarden.airplaneModeToggled(); 4248 mLooper.dispatchAll(); 4249 }); 4250 4251 4252 // APM toggle off before the stop is complete. 4253 assertInEnabledState(); 4254 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 4255 mActiveModeWarden.airplaneModeToggled(); 4256 mLooper.dispatchAll(); 4257 4258 // AP stopped, should not process APM toggle. 4259 mSoftApListener.onStopped(mSoftApManager); 4260 mLooper.dispatchAll(); 4261 verify(mWifiInjector, times(1)).makeClientModeManager( 4262 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 4263 4264 // STA also stopped, should process APM toggle. 4265 mClientListener.onStopped(mClientModeManager); 4266 mLooper.dispatchAll(); 4267 verify(mWifiInjector, times(2)).makeClientModeManager( 4268 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 4269 4270 mClientListener.onStarted(mClientModeManager); 4271 mLooper.dispatchAll(); 4272 4273 // We should be back to enabled state. 4274 assertInEnabledState(); 4275 } 4276 4277 @Test propagateVerboseLoggingFlagToClientModeManager()4278 public void propagateVerboseLoggingFlagToClientModeManager() throws Exception { 4279 mActiveModeWarden.enableVerboseLogging(true); 4280 enterClientModeActiveState(); 4281 assertInEnabledState(); 4282 verify(mWifiInjector).makeClientModeManager(any(), any(), any(), eq(true)); 4283 4284 mActiveModeWarden.enableVerboseLogging(false); 4285 verify(mClientModeManager).enableVerboseLogging(false); 4286 } 4287 4288 @Test propagateConnectedWifiScorerToPrimaryClientModeManager()4289 public void propagateConnectedWifiScorerToPrimaryClientModeManager() throws Exception { 4290 IBinder iBinder = mock(IBinder.class); 4291 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 4292 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4293 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 4294 enterClientModeActiveState(); 4295 assertInEnabledState(); 4296 verify(mClientModeManager).setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4297 4298 mActiveModeWarden.clearWifiConnectedNetworkScorer(); 4299 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 4300 4301 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4302 verify(mClientModeManager, times(2)).setWifiConnectedNetworkScorer(iBinder, iScorer, 4303 TEST_UID); 4304 } 4305 4306 @Test propagateConnectedWifiScorerToPrimaryClientModeManager_enterScanOnlyState()4307 public void propagateConnectedWifiScorerToPrimaryClientModeManager_enterScanOnlyState() 4308 throws Exception { 4309 IBinder iBinder = mock(IBinder.class); 4310 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 4311 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4312 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 4313 enterClientModeActiveState(); 4314 assertInEnabledState(); 4315 verify(mClientModeManager).setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4316 4317 enterScanOnlyModeActiveState(true); 4318 4319 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 4320 } 4321 4322 @Test handleWifiScorerSetScoreUpdateObserverFailure()4323 public void handleWifiScorerSetScoreUpdateObserverFailure() throws Exception { 4324 IBinder iBinder = mock(IBinder.class); 4325 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 4326 doThrow(new RemoteException()).when(iScorer).onSetScoreUpdateObserver(any()); 4327 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer, TEST_UID); 4328 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 4329 enterClientModeActiveState(); 4330 assertInEnabledState(); 4331 // Ensure we did not propagate the scorer. 4332 verify(mClientModeManager, never()).setWifiConnectedNetworkScorer(iBinder, iScorer, 4333 TEST_UID); 4334 } 4335 4336 /** Verify that the primary changed callback is triggered when entering client mode. */ 4337 @Test testAddPrimaryClientModeManager()4338 public void testAddPrimaryClientModeManager() throws Exception { 4339 enterClientModeActiveState(); 4340 4341 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 4342 } 4343 4344 /** Verify the primary changed callback is not triggered when there is no primary. */ 4345 @Test testNoAddPrimaryClientModeManager()4346 public void testNoAddPrimaryClientModeManager() throws Exception { 4347 enterScanOnlyModeActiveState(); 4348 4349 verify(mPrimaryChangedCallback, never()).onChange(any(), any()); 4350 } 4351 4352 /** 4353 * Verify the primary changed callback is triggered when changing the primary from one 4354 * ClientModeManager to another. 4355 */ 4356 @Test testSwitchPrimaryClientModeManager()4357 public void testSwitchPrimaryClientModeManager() throws Exception { 4358 // Ensure that we can create more client ifaces. 4359 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4360 when(mResources.getBoolean( 4361 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 4362 .thenReturn(true); 4363 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4364 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT, false)); 4365 4366 enterClientModeActiveState(); 4367 4368 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 4369 4370 // Connected to ssid1/bssid1 4371 WifiConfiguration config1 = new WifiConfiguration(); 4372 config1.SSID = TEST_SSID_1; 4373 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 4374 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 4375 4376 ConcreteClientModeManager additionalClientModeManager = 4377 mock(ConcreteClientModeManager.class); 4378 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 4379 new Mutable<>(); 4380 doAnswer((invocation) -> { 4381 Object[] args = invocation.getArguments(); 4382 additionalClientListener.value = 4383 (Listener<ConcreteClientModeManager>) args[0]; 4384 return additionalClientModeManager; 4385 }).when(mWifiInjector).makeClientModeManager( 4386 any(Listener.class), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 4387 anyBoolean()); 4388 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 4389 4390 ExternalClientModeManagerRequestListener externalRequestListener = mock( 4391 ExternalClientModeManagerRequestListener.class); 4392 // request for ssid2/bssid2 4393 mActiveModeWarden.requestSecondaryTransientClientModeManager( 4394 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 4395 mLooper.dispatchAll(); 4396 verify(mWifiInjector).makeClientModeManager( 4397 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), anyBoolean()); 4398 additionalClientListener.value.onStarted(additionalClientModeManager); 4399 mLooper.dispatchAll(); 4400 // Returns the new client mode manager. 4401 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 4402 ArgumentCaptor.forClass(ClientModeManager.class); 4403 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 4404 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 4405 4406 // primary didn't change yet 4407 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 4408 4409 // change primary 4410 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 4411 mClientListener.onRoleChanged(mClientModeManager); 4412 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 4413 additionalClientListener.value.onRoleChanged(additionalClientModeManager); 4414 4415 // verify callback triggered 4416 verify(mPrimaryChangedCallback).onChange(mClientModeManager, null); 4417 verify(mPrimaryChangedCallback).onChange(null, additionalClientModeManager); 4418 } 4419 4420 @Test testRegisterPrimaryCmmChangedCallbackWhenConnectModeActiveState()4421 public void testRegisterPrimaryCmmChangedCallbackWhenConnectModeActiveState() throws Exception { 4422 enterClientModeActiveState(); 4423 4424 // register a new primary cmm change callback. 4425 ActiveModeWarden.PrimaryClientModeManagerChangedCallback primarCmmCallback = mock( 4426 ActiveModeWarden.PrimaryClientModeManagerChangedCallback.class); 4427 mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback(primarCmmCallback); 4428 // Ensure we get the callback immediately. 4429 verify(primarCmmCallback).onChange(null, mClientModeManager); 4430 } 4431 4432 @Test testGetCmmInRolesWithNullRoleInOneCmm()4433 public void testGetCmmInRolesWithNullRoleInOneCmm() throws Exception { 4434 enterClientModeActiveState(); 4435 4436 // Ensure that we can create more client ifaces. 4437 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4438 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 4439 .thenReturn(true); 4440 4441 ConcreteClientModeManager additionalClientModeManager = 4442 mock(ConcreteClientModeManager.class); 4443 when(mWifiInjector.makeClientModeManager( 4444 any(), any(), any(), anyBoolean())).thenReturn(additionalClientModeManager); 4445 4446 mActiveModeWarden.requestLocalOnlyClientModeManager( 4447 mock(ExternalClientModeManagerRequestListener.class), 4448 TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, false); 4449 mLooper.dispatchAll(); 4450 4451 // No role set, should be ignored. 4452 when(additionalClientModeManager.getRole()).thenReturn(null); 4453 assertEquals(1, mActiveModeWarden.getClientModeManagersInRoles( 4454 ROLE_CLIENT_PRIMARY, ROLE_CLIENT_LOCAL_ONLY).size()); 4455 4456 // Role set, should be included. 4457 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 4458 assertEquals(2, mActiveModeWarden.getClientModeManagersInRoles( 4459 ROLE_CLIENT_PRIMARY, ROLE_CLIENT_LOCAL_ONLY).size()); 4460 } 4461 4462 /** 4463 * Helper method to enter the EnabledState and set ClientModeManager in ScanOnlyMode during 4464 * emergency scan processing. 4465 */ indicateStartOfEmergencyScan( boolean hasAnyOtherStaToggleEnabled, @Nullable ActiveModeManager.ClientRole expectedRole)4466 private void indicateStartOfEmergencyScan( 4467 boolean hasAnyOtherStaToggleEnabled, 4468 @Nullable ActiveModeManager.ClientRole expectedRole) 4469 throws Exception { 4470 String fromState = mActiveModeWarden.getCurrentMode(); 4471 mActiveModeWarden.setEmergencyScanRequestInProgress(true); 4472 mLooper.dispatchAll(); 4473 4474 if (!hasAnyOtherStaToggleEnabled) { 4475 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 4476 mClientListener.onStarted(mClientModeManager); 4477 mLooper.dispatchAll(); 4478 verify(mWifiInjector).makeClientModeManager( 4479 any(), eq(SETTINGS_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 4480 verify(mModeChangeCallback).onActiveModeManagerAdded(mClientModeManager); 4481 verify(mScanRequestProxy).enableScanning(true, false); 4482 verify(mBatteryStats).reportWifiOn(); 4483 verify(mBatteryStats).reportWifiState( 4484 BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); 4485 } else { 4486 verify(mClientModeManager).setRole(eq(expectedRole), any()); 4487 verify(mClientModeManager, never()).stop(); 4488 assertEquals(fromState, mActiveModeWarden.getCurrentMode()); 4489 } 4490 assertInEnabledState(); 4491 } 4492 indicateEndOfEmergencyScan( boolean hasAnyOtherStaToggleEnabled, @Nullable ActiveModeManager.ClientRole expectedRole)4493 private void indicateEndOfEmergencyScan( 4494 boolean hasAnyOtherStaToggleEnabled, 4495 @Nullable ActiveModeManager.ClientRole expectedRole) { 4496 String fromState = mActiveModeWarden.getCurrentMode(); 4497 mActiveModeWarden.setEmergencyScanRequestInProgress(false); 4498 mLooper.dispatchAll(); 4499 if (!hasAnyOtherStaToggleEnabled) { 4500 mClientListener.onStopped(mClientModeManager); 4501 mLooper.dispatchAll(); 4502 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 4503 verify(mScanRequestProxy).enableScanning(false, false); 4504 assertInDisabledState(); 4505 } else { 4506 // Nothing changes. 4507 verify(mClientModeManager).setRole(eq(expectedRole), any()); 4508 verify(mClientModeManager, never()).stop(); 4509 assertEquals(fromState, mActiveModeWarden.getCurrentMode()); 4510 } 4511 } 4512 4513 @Test testEmergencyScanWhenWifiDisabled()4514 public void testEmergencyScanWhenWifiDisabled() throws Exception { 4515 // Wifi fully disabled. 4516 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 4517 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 4518 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 4519 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 4520 4521 indicateStartOfEmergencyScan(false, null); 4522 4523 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4524 clearInvocations(mClientModeManager); 4525 4526 indicateEndOfEmergencyScan(false, null); 4527 } 4528 4529 @Test testEmergencyScanWhenWifiEnabled()4530 public void testEmergencyScanWhenWifiEnabled() throws Exception { 4531 // Wifi enabled. 4532 enterClientModeActiveState(); 4533 4534 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4535 4536 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4537 4538 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4539 clearInvocations(mClientModeManager); 4540 4541 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4542 } 4543 4544 @Test testEmergencyScanWhenScanOnlyModeEnabled()4545 public void testEmergencyScanWhenScanOnlyModeEnabled() throws Exception { 4546 // Scan only enabled. 4547 enterScanOnlyModeActiveState(); 4548 4549 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4550 4551 indicateStartOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 4552 4553 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4554 clearInvocations(mClientModeManager); 4555 4556 indicateEndOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 4557 } 4558 4559 @Test testEmergencyScanWhenEcmOnWithWifiDisableInEcbm()4560 public void testEmergencyScanWhenEcmOnWithWifiDisableInEcbm() throws Exception { 4561 // Wifi enabled. 4562 enterClientModeActiveState(); 4563 4564 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4565 4566 // Test with WifiDisableInECBM turned on 4567 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 4568 4569 assertWifiShutDown(() -> { 4570 // test ecm changed 4571 emergencyCallbackModeChanged(true); 4572 mLooper.dispatchAll(); 4573 // fully shutdown 4574 mClientListener.onStopped(mClientModeManager); 4575 mLooper.dispatchAll(); 4576 }); 4577 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4578 4579 indicateStartOfEmergencyScan(false, null); 4580 4581 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4582 clearInvocations(mClientModeManager); 4583 4584 indicateEndOfEmergencyScan(false, null); 4585 } 4586 4587 @Test testEmergencyScanWhenEcmOnWithoutWifiDisableInEcbm()4588 public void testEmergencyScanWhenEcmOnWithoutWifiDisableInEcbm() throws Exception { 4589 // Wifi enabled. 4590 enterClientModeActiveState(); 4591 4592 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4593 4594 // Test with WifiDisableInECBM turned off 4595 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 4596 4597 assertEnteredEcmMode(() -> { 4598 // test ecm changed 4599 emergencyCallbackModeChanged(true); 4600 mLooper.dispatchAll(); 4601 }); 4602 4603 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4604 4605 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4606 clearInvocations(mClientModeManager); 4607 4608 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4609 } 4610 4611 @Test testWifiDisableDuringEmergencyScan()4612 public void testWifiDisableDuringEmergencyScan() throws Exception { 4613 // Wifi enabled. 4614 enterClientModeActiveState(); 4615 4616 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4617 4618 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4619 4620 // Toggle off wifi 4621 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 4622 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 4623 mLooper.dispatchAll(); 4624 4625 // Ensure that we switched the role to scan only state because of the emergency scan. 4626 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 4627 mClientListener.onRoleChanged(mClientModeManager); 4628 mLooper.dispatchAll(); 4629 verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY, INTERNAL_REQUESTOR_WS); 4630 verify(mClientModeManager, never()).stop(); 4631 assertInEnabledState(); 4632 4633 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4634 clearInvocations(mClientModeManager); 4635 4636 indicateEndOfEmergencyScan(false, null); 4637 } 4638 4639 @Test testScanOnlyModeDisableDuringEmergencyScan()4640 public void testScanOnlyModeDisableDuringEmergencyScan() throws Exception { 4641 // Scan only enabled. 4642 enterScanOnlyModeActiveState(); 4643 4644 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4645 4646 indicateStartOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 4647 4648 // To reset setRole invocation above which is checked below. 4649 clearInvocations(mClientModeManager); 4650 4651 // Toggle off scan only mode 4652 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 4653 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 4654 mActiveModeWarden.scanAlwaysModeChanged(); 4655 mLooper.dispatchAll(); 4656 4657 // Ensure that we remained in scan only state because of the emergency scan. 4658 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_SCAN_ONLY), any()); 4659 verify(mClientModeManager, never()).stop(); 4660 assertInEnabledState(); 4661 4662 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4663 clearInvocations(mClientModeManager); 4664 4665 indicateEndOfEmergencyScan(false, null); 4666 } 4667 4668 @Test testEcmOffWithWifiDisabledStateDuringEmergencyScan()4669 public void testEcmOffWithWifiDisabledStateDuringEmergencyScan() throws Exception { 4670 // Wifi enabled. 4671 enterClientModeActiveState(); 4672 4673 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4674 4675 // Test with WifiDisableInECBM turned on 4676 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 4677 4678 assertWifiShutDown(() -> { 4679 // test ecm changed 4680 emergencyCallbackModeChanged(true); 4681 mLooper.dispatchAll(); 4682 // fully shutdown 4683 mClientListener.onStopped(mClientModeManager); 4684 mLooper.dispatchAll(); 4685 }); 4686 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4687 4688 indicateStartOfEmergencyScan(false, null); 4689 4690 // Now turn off ECM 4691 emergencyCallbackModeChanged(false); 4692 mLooper.dispatchAll(); 4693 4694 // Ensure we turned wifi back on. 4695 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_PRIMARY), any()); 4696 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 4697 mClientListener.onRoleChanged(mClientModeManager); 4698 verify(mScanRequestProxy).enableScanning(true, true); 4699 assertInEnabledState(); 4700 4701 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4702 clearInvocations(mClientModeManager); 4703 4704 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4705 } 4706 4707 @Test testEcmOffWithoutWifiDisabledStateDuringEmergencyScan()4708 public void testEcmOffWithoutWifiDisabledStateDuringEmergencyScan() throws Exception { 4709 // Wifi enabled. 4710 enterClientModeActiveState(); 4711 4712 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 4713 4714 // Test with WifiDisableInECBM turned off 4715 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 4716 4717 assertEnteredEcmMode(() -> { 4718 // test ecm changed 4719 emergencyCallbackModeChanged(true); 4720 mLooper.dispatchAll(); 4721 }); 4722 4723 // Now turn off ECM 4724 emergencyCallbackModeChanged(false); 4725 mLooper.dispatchAll(); 4726 4727 // Ensure that we remained in connected state. 4728 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_PRIMARY), any()); 4729 verify(mClientModeManager, never()).stop(); 4730 assertInEnabledState(); 4731 4732 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 4733 clearInvocations(mClientModeManager); 4734 4735 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 4736 } 4737 4738 @Test testRequestForSecondaryLocalOnlyForPreSAppWithUserConnect()4739 public void testRequestForSecondaryLocalOnlyForPreSAppWithUserConnect() throws Exception { 4740 // Ensure that we can create more client ifaces. 4741 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4742 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 4743 .thenReturn(true); 4744 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 4745 .thenReturn(true); 4746 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 4747 when(mWifiPermissionsUtil.isTargetSdkLessThan( 4748 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 4749 .thenReturn(true); 4750 when(mWifiPermissionsUtil.isTargetSdkLessThan( 4751 "system-service", Build.VERSION_CODES.S, Process.SYSTEM_UID)) 4752 .thenReturn(false); 4753 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4754 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, true)); 4755 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4756 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED, false)); 4757 4758 enterClientModeActiveState(); 4759 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 4760 ArgumentCaptor.forClass(ClientModeManager.class); 4761 ExternalClientModeManagerRequestListener externalRequestListener = mock( 4762 ExternalClientModeManagerRequestListener.class); 4763 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 4764 new Mutable<>(); 4765 ConcreteClientModeManager additionalClientModeManager = 4766 mock(ConcreteClientModeManager.class); 4767 doAnswer((invocation) -> { 4768 Object[] args = invocation.getArguments(); 4769 additionalClientListener.value = 4770 (Listener<ConcreteClientModeManager>) args[0]; 4771 return additionalClientModeManager; 4772 }).when(mWifiInjector).makeClientModeManager( 4773 any(Listener.class), any(), any(), anyBoolean()); 4774 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 4775 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 4776 4777 // mock requesting local only secondary 4778 mActiveModeWarden.requestLocalOnlyClientModeManager( 4779 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, true); 4780 mLooper.dispatchAll(); 4781 // Verify the primary is given to the externalRequestListener 4782 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 4783 verify(mWifiInjector, never()).makeClientModeManager( 4784 any(), any(), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 4785 assertEquals(ROLE_CLIENT_PRIMARY, requestedClientModeManager.getValue().getRole()); 4786 4787 // Request for non local-only STA and verify the secondary STA is provided instead. 4788 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_LONG_LIVED); 4789 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 4790 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 4791 mLooper.dispatchAll(); 4792 verify(mWifiInjector).makeClientModeManager(any(), any(), 4793 eq(ROLE_CLIENT_SECONDARY_LONG_LIVED), anyBoolean()); 4794 4795 additionalClientListener.value.onStarted(additionalClientModeManager); 4796 mLooper.dispatchAll(); 4797 verify(externalRequestListener, times(2)).onAnswer( 4798 requestedClientModeManager.capture()); 4799 assertEquals(ROLE_CLIENT_SECONDARY_LONG_LIVED, 4800 requestedClientModeManager.getValue().getRole()); 4801 } 4802 4803 @Test testRequestForSecondaryLocalOnlyForAppWithUserConnect()4804 public void testRequestForSecondaryLocalOnlyForAppWithUserConnect() throws Exception { 4805 // Ensure that we can create more client ifaces. 4806 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 4807 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 4808 .thenReturn(true); 4809 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 4810 when(mWifiPermissionsUtil.isTargetSdkLessThan( 4811 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 4812 .thenReturn(false); 4813 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 4814 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY, true)); 4815 4816 enterClientModeActiveState(); 4817 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 4818 ArgumentCaptor.forClass(ClientModeManager.class); 4819 ExternalClientModeManagerRequestListener externalRequestListener = mock( 4820 ExternalClientModeManagerRequestListener.class); 4821 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 4822 new Mutable<>(); 4823 ConcreteClientModeManager additionalClientModeManager = 4824 mock(ConcreteClientModeManager.class); 4825 doAnswer((invocation) -> { 4826 Object[] args = invocation.getArguments(); 4827 additionalClientListener.value = 4828 (Listener<ConcreteClientModeManager>) args[0]; 4829 return additionalClientModeManager; 4830 }).when(mWifiInjector).makeClientModeManager( 4831 any(Listener.class), any(), any(), anyBoolean()); 4832 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 4833 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 4834 4835 // mock requesting local only secondary 4836 mActiveModeWarden.requestLocalOnlyClientModeManager( 4837 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2, true); 4838 mLooper.dispatchAll(); 4839 WorkSource ws = new WorkSource(TEST_WORKSOURCE); 4840 ws.add(SETTINGS_WORKSOURCE); 4841 verify(mWifiInjector).makeClientModeManager( 4842 any(), eq(ws), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 4843 additionalClientListener.value.onStarted(additionalClientModeManager); 4844 mLooper.dispatchAll(); 4845 // Verify the primary is given to the externalRequestListener 4846 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 4847 4848 assertEquals(ROLE_CLIENT_LOCAL_ONLY, requestedClientModeManager.getValue().getRole()); 4849 } 4850 4851 @Test testSetAndGetWifiState()4852 public void testSetAndGetWifiState() { 4853 int invalidState = 5; 4854 mActiveModeWarden.setWifiStateForApiCalls(WIFI_STATE_ENABLED); 4855 assertEquals(WIFI_STATE_ENABLED, mActiveModeWarden.getWifiState()); 4856 mActiveModeWarden.setWifiStateForApiCalls(invalidState); 4857 assertEquals(WIFI_STATE_ENABLED, mActiveModeWarden.getWifiState()); 4858 } 4859 4860 /** 4861 * Verifies that getSupportedFeatureSet() adds capabilities based on interface 4862 * combination. 4863 */ 4864 @Test testGetSupportedFeaturesForStaApConcurrency()4865 public void testGetSupportedFeaturesForStaApConcurrency() throws Exception { 4866 enterScanOnlyModeActiveState(); 4867 long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; 4868 when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( 4869 supportedFeaturesFromWifiNative); 4870 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); 4871 mClientListener.onStarted(mClientModeManager); 4872 4873 assertEquals(supportedFeaturesFromWifiNative, 4874 mActiveModeWarden.getSupportedFeatureSet()); 4875 4876 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); 4877 mClientListener.onStarted(mClientModeManager); 4878 4879 assertEquals(supportedFeaturesFromWifiNative | WifiManager.WIFI_FEATURE_AP_STA, 4880 mActiveModeWarden.getSupportedFeatureSet()); 4881 } 4882 4883 /** 4884 * Verifies that getSupportedFeatureSet() adds capabilities based on interface 4885 * combination. 4886 */ 4887 @Test testGetSupportedFeaturesForStaStaConcurrency()4888 public void testGetSupportedFeaturesForStaStaConcurrency() throws Exception { 4889 assumeTrue(SdkLevel.isAtLeastS()); 4890 enterScanOnlyModeActiveState(); 4891 long supportedFeaturesFromWifiNative = WifiManager.WIFI_FEATURE_OWE; 4892 when(mWifiNative.getSupportedFeatureSet(null)).thenReturn( 4893 supportedFeaturesFromWifiNative); 4894 4895 mClientListener.onStarted(mClientModeManager); 4896 assertEquals(supportedFeaturesFromWifiNative, mActiveModeWarden.getSupportedFeatureSet()); 4897 4898 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); 4899 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 4900 .thenReturn(true); 4901 mClientListener.onStarted(mClientModeManager); 4902 assertEquals(supportedFeaturesFromWifiNative 4903 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY, 4904 mActiveModeWarden.getSupportedFeatureSet()); 4905 4906 when(mResources.getBoolean( 4907 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 4908 .thenReturn(true); 4909 mClientListener.onStarted(mClientModeManager); 4910 assertEquals(supportedFeaturesFromWifiNative 4911 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY 4912 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB, 4913 mActiveModeWarden.getSupportedFeatureSet()); 4914 4915 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 4916 .thenReturn(true); 4917 when(mResources.getBoolean(R.bool.config_wifiMultiStaMultiInternetConcurrencyEnabled)) 4918 .thenReturn(true); 4919 mClientListener.onStarted(mClientModeManager); 4920 assertEquals(supportedFeaturesFromWifiNative 4921 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY 4922 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB 4923 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED 4924 | WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET, 4925 mActiveModeWarden.getSupportedFeatureSet()); 4926 } 4927 testGetSupportedFeaturesCaseForMacRandomization( long supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled, boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled)4928 private long testGetSupportedFeaturesCaseForMacRandomization( 4929 long supportedFeaturesFromWifiNative, boolean apMacRandomizationEnabled, 4930 boolean staConnectedMacRandomizationEnabled, boolean p2pMacRandomizationEnabled) { 4931 when(mResources.getBoolean( 4932 R.bool.config_wifi_connected_mac_randomization_supported)) 4933 .thenReturn(staConnectedMacRandomizationEnabled); 4934 when(mResources.getBoolean( 4935 R.bool.config_wifi_ap_mac_randomization_supported)) 4936 .thenReturn(apMacRandomizationEnabled); 4937 when(mResources.getBoolean( 4938 R.bool.config_wifi_p2p_mac_randomization_supported)) 4939 .thenReturn(p2pMacRandomizationEnabled); 4940 when(mWifiNative.getSupportedFeatureSet(anyString())) 4941 .thenReturn(supportedFeaturesFromWifiNative); 4942 mClientListener.onStarted(mClientModeManager); 4943 mLooper.dispatchAll(); 4944 return mActiveModeWarden.getSupportedFeatureSet(); 4945 } 4946 4947 /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ 4948 @Test syncGetSupportedFeaturesForMacRandomization()4949 public void syncGetSupportedFeaturesForMacRandomization() throws Exception { 4950 final long featureStaConnectedMacRandomization = 4951 WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; 4952 final long featureApMacRandomization = 4953 WifiManager.WIFI_FEATURE_AP_RAND_MAC; 4954 final long featureP2pMacRandomization = 4955 WifiManager.WIFI_FEATURE_CONNECTED_RAND_MAC; 4956 4957 enterClientModeActiveState(); 4958 assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization 4959 | featureP2pMacRandomization, 4960 testGetSupportedFeaturesCaseForMacRandomization( 4961 featureP2pMacRandomization, true, true, true)); 4962 // p2p supported by HAL, but disabled by overlay. 4963 assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, 4964 testGetSupportedFeaturesCaseForMacRandomization( 4965 featureP2pMacRandomization, true, true, false)); 4966 assertEquals(featureStaConnectedMacRandomization | featureApMacRandomization, 4967 testGetSupportedFeaturesCaseForMacRandomization(0, true, true, false)); 4968 } 4969 testGetSupportedFeaturesCaseForRtt( long supportedFeaturesFromWifiNative, boolean rttDisabled)4970 private long testGetSupportedFeaturesCaseForRtt( 4971 long supportedFeaturesFromWifiNative, boolean rttDisabled) { 4972 when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_WIFI_RTT)).thenReturn( 4973 !rttDisabled); 4974 when(mWifiNative.getSupportedFeatureSet(anyString())).thenReturn( 4975 supportedFeaturesFromWifiNative); 4976 mClientListener.onStarted(mClientModeManager); 4977 mLooper.dispatchAll(); 4978 return mActiveModeWarden.getSupportedFeatureSet(); 4979 } 4980 4981 /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */ 4982 @Test syncGetSupportedFeaturesForRtt()4983 public void syncGetSupportedFeaturesForRtt() throws Exception { 4984 final long featureAware = WifiManager.WIFI_FEATURE_AWARE; 4985 final long featureInfra = WifiManager.WIFI_FEATURE_INFRA; 4986 final long featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT; 4987 final long featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT; 4988 final long featureLongBits = 0x1000000000L; 4989 enterClientModeActiveState(); 4990 assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, false)); 4991 assertEquals(0, testGetSupportedFeaturesCaseForRtt(0, true)); 4992 assertEquals(featureAware | featureInfra, 4993 testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, false)); 4994 assertEquals(featureAware | featureInfra, 4995 testGetSupportedFeaturesCaseForRtt(featureAware | featureInfra, true)); 4996 assertEquals(featureInfra | featureD2dRtt, 4997 testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, false)); 4998 assertEquals(featureInfra, 4999 testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2dRtt, true)); 5000 assertEquals(featureInfra | featureD2apRtt, 5001 testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, false)); 5002 assertEquals(featureInfra, 5003 testGetSupportedFeaturesCaseForRtt(featureInfra | featureD2apRtt, true)); 5004 assertEquals(featureInfra | featureD2dRtt | featureD2apRtt, 5005 testGetSupportedFeaturesCaseForRtt( 5006 featureInfra | featureD2dRtt | featureD2apRtt, false)); 5007 assertEquals(featureInfra, 5008 testGetSupportedFeaturesCaseForRtt( 5009 featureInfra | featureD2dRtt | featureD2apRtt, true)); 5010 5011 assertEquals(featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, 5012 testGetSupportedFeaturesCaseForRtt( 5013 featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, false)); 5014 assertEquals(featureLongBits | featureInfra, 5015 testGetSupportedFeaturesCaseForRtt( 5016 featureLongBits | featureInfra | featureD2dRtt | featureD2apRtt, true)); 5017 } 5018 5019 @Test testGetCurrentNetworkScanOnly()5020 public void testGetCurrentNetworkScanOnly() throws Exception { 5021 enterScanOnlyModeActiveState(); 5022 assertNull(mActiveModeWarden.getCurrentNetwork()); 5023 } 5024 testGetCurrentNetworkClientMode()5025 @Test public void testGetCurrentNetworkClientMode() throws Exception { 5026 mActiveModeWarden.setCurrentNetwork(mNetwork); 5027 assertEquals(mNetwork, mActiveModeWarden.getCurrentNetwork()); 5028 } 5029 5030 /** 5031 * Verifies that isClientModeManagerConnectedOrConnectingToBssid() checks for Affiliated link 5032 * BSSID, if exists. 5033 */ 5034 @Test testClientModeManagerConnectedOrConnectingToBssid()5035 public void testClientModeManagerConnectedOrConnectingToBssid() { 5036 5037 WifiConfiguration config1 = new WifiConfiguration(); 5038 config1.SSID = TEST_SSID_1; 5039 MacAddress bssid2 = MacAddress.fromString(TEST_BSSID_2); 5040 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 5041 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 5042 when(mClientModeManager.isAffiliatedLinkBssid(eq(bssid2))).thenReturn(true); 5043 5044 assertTrue(mActiveModeWarden.isClientModeManagerConnectedOrConnectingToBssid( 5045 mClientModeManager, TEST_SSID_1, TEST_BSSID_2)); 5046 } 5047 5048 @Test syncGetSupportedBands()5049 public void syncGetSupportedBands() throws Exception { 5050 enterClientModeActiveState(); 5051 when(mWifiNative.getSupportedBandsForSta(anyString())).thenReturn(11); 5052 mClientListener.onStarted(mClientModeManager); 5053 mLooper.dispatchAll(); 5054 verify(mSettingsConfigStore).put(WIFI_NATIVE_SUPPORTED_STA_BANDS, 11); 5055 assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_24_GHZ)); 5056 assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ)); 5057 assertFalse(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_5_GHZ_DFS_ONLY)); 5058 assertTrue(mActiveModeWarden.isBandSupportedForSta(WifiScanner.WIFI_BAND_6_GHZ)); 5059 } 5060 5061 @Test testSatelliteModeOnDisableWifi()5062 public void testSatelliteModeOnDisableWifi() throws Exception { 5063 // Wifi is enabled 5064 enterClientModeActiveState(); 5065 assertInEnabledState(); 5066 5067 // Satellite mode is ON, disable Wifi 5068 assertWifiShutDown(() -> { 5069 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5070 mActiveModeWarden.handleSatelliteModeChange(); 5071 mLooper.dispatchAll(); 5072 }); 5073 mClientListener.onStopped(mClientModeManager); 5074 mLooper.dispatchAll(); 5075 assertInDisabledState(); 5076 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), 5077 anyInt(), anyInt(), any(), eq(false)); 5078 } 5079 5080 @Test testSatelliteModeOffNoOp()5081 public void testSatelliteModeOffNoOp() throws Exception { 5082 // Wifi is enabled 5083 enterClientModeActiveState(); 5084 assertInEnabledState(); 5085 5086 // Satellite mode is off 5087 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5088 mActiveModeWarden.handleSatelliteModeChange(); 5089 5090 mLooper.dispatchAll(); 5091 assertInEnabledState(); 5092 // Should not enable wifi again since wifi is already on 5093 verify(mLastCallerInfoManager, never()).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), 5094 anyInt(), anyInt(), any(), eq(true)); 5095 } 5096 5097 @Test testSatelliteModeOnAndThenOffEnableWifi()5098 public void testSatelliteModeOnAndThenOffEnableWifi() throws Exception { 5099 // Wifi is enabled 5100 enterClientModeActiveState(); 5101 assertInEnabledState(); 5102 5103 // Satellite mode is ON, disable Wifi 5104 assertWifiShutDown(() -> { 5105 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5106 mActiveModeWarden.handleSatelliteModeChange(); 5107 mLooper.dispatchAll(); 5108 }); 5109 mClientListener.onStopped(mClientModeManager); 5110 mLooper.dispatchAll(); 5111 assertInDisabledState(); 5112 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), 5113 anyInt(), anyInt(), any(), eq(false)); 5114 5115 // Satellite mode is off, enable Wifi 5116 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5117 mActiveModeWarden.handleSatelliteModeChange(); 5118 mLooper.dispatchAll(); 5119 assertInEnabledState(); 5120 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), 5121 anyInt(), anyInt(), any(), eq(true)); 5122 } 5123 5124 5125 @Test testSatelliteModeOnAirplaneModeOn()5126 public void testSatelliteModeOnAirplaneModeOn() throws Exception { 5127 // Sequence: Satellite ON -> APM ON -> Satellite OFF -> APM OFF 5128 5129 // Wifi is enabled 5130 enterClientModeActiveState(); 5131 assertInEnabledState(); 5132 5133 // Satellite mode is ON, disable Wifi 5134 assertWifiShutDown(() -> { 5135 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5136 mActiveModeWarden.handleSatelliteModeChange(); 5137 mLooper.dispatchAll(); 5138 }); 5139 mClientListener.onStopped(mClientModeManager); 5140 mLooper.dispatchAll(); 5141 assertInDisabledState(); 5142 5143 // APM toggle on, no change to Wifi state 5144 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 5145 mActiveModeWarden.airplaneModeToggled(); 5146 mLooper.dispatchAll(); 5147 assertInDisabledState(); 5148 5149 // Satellite mode is off, no change to Wifi state as APM is on 5150 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5151 mActiveModeWarden.handleSatelliteModeChange(); 5152 mLooper.dispatchAll(); 5153 assertInDisabledState(); 5154 5155 // APM toggle off, enable Wifi 5156 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 5157 mActiveModeWarden.airplaneModeToggled(); 5158 mLooper.dispatchAll(); 5159 assertInEnabledState(); 5160 } 5161 5162 @Test testAirplaneModeOnSatelliteModeOn()5163 public void testAirplaneModeOnSatelliteModeOn() throws Exception { 5164 // Sequence: APM ON -> Satellite ON -> APM OFF -> Satellite OFF 5165 5166 // Wifi is enabled 5167 enterClientModeActiveState(); 5168 assertInEnabledState(); 5169 5170 // APM toggle on, Wifi disabled 5171 assertWifiShutDown(() -> { 5172 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 5173 mActiveModeWarden.airplaneModeToggled(); 5174 mLooper.dispatchAll(); 5175 }); 5176 mClientListener.onStopped(mClientModeManager); 5177 mLooper.dispatchAll(); 5178 assertInDisabledState(); 5179 5180 // Satellite mode is on, no change to Wifi state 5181 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5182 mActiveModeWarden.handleSatelliteModeChange(); 5183 mLooper.dispatchAll(); 5184 assertInDisabledState(); 5185 5186 // APM toggle off, no change to Wifi state 5187 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 5188 mActiveModeWarden.airplaneModeToggled(); 5189 mLooper.dispatchAll(); 5190 assertInDisabledState(); 5191 5192 // Satellite mode is off, enable Wifi 5193 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5194 mActiveModeWarden.handleSatelliteModeChange(); 5195 mLooper.dispatchAll(); 5196 assertInEnabledState(); 5197 } 5198 5199 @Test testToggleSatelliteModeBeforeAirplaneMode()5200 public void testToggleSatelliteModeBeforeAirplaneMode() throws Exception { 5201 // Sequence: APM ON -> Satellite ON -> Satellite OFF -> APM OFF 5202 5203 // Wifi is enabled 5204 enterClientModeActiveState(); 5205 assertInEnabledState(); 5206 5207 // APM toggle on, Wifi disabled 5208 assertWifiShutDown(() -> { 5209 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 5210 mActiveModeWarden.airplaneModeToggled(); 5211 mLooper.dispatchAll(); 5212 }); 5213 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), anyInt(), 5214 anyInt(), eq("android_apm"), eq(false)); 5215 verify(mLastCallerInfoManager, never()).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), 5216 anyInt(), anyInt(), eq("android_apm"), eq(true)); 5217 mClientListener.onStopped(mClientModeManager); 5218 mLooper.dispatchAll(); 5219 assertInDisabledState(); 5220 5221 // Satellite mode is on, no change to Wifi state 5222 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5223 mActiveModeWarden.handleSatelliteModeChange(); 5224 mLooper.dispatchAll(); 5225 assertInDisabledState(); 5226 5227 // Satellite mode is off, no change to Wifi state 5228 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5229 mActiveModeWarden.handleSatelliteModeChange(); 5230 mLooper.dispatchAll(); 5231 assertInDisabledState(); 5232 5233 // APM toggle off, enable Wifi 5234 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 5235 mActiveModeWarden.airplaneModeToggled(); 5236 mLooper.dispatchAll(); 5237 assertInEnabledState(); 5238 verify(mLastCallerInfoManager).put(eq(WifiManager.API_WIFI_ENABLED), anyInt(), anyInt(), 5239 anyInt(), eq("android_apm"), eq(true)); 5240 } 5241 5242 @Test testToggleAirplaneModeBeforeSatelliteMode()5243 public void testToggleAirplaneModeBeforeSatelliteMode() throws Exception { 5244 // Sequence: Satellite ON -> APM ON -> APM OFF -> Satellite OFF 5245 5246 // Wifi is enabled 5247 enterClientModeActiveState(); 5248 assertInEnabledState(); 5249 5250 // Satellite mode is ON, disable Wifi 5251 assertWifiShutDown(() -> { 5252 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5253 mActiveModeWarden.handleSatelliteModeChange(); 5254 mLooper.dispatchAll(); 5255 }); 5256 mClientListener.onStopped(mClientModeManager); 5257 mLooper.dispatchAll(); 5258 assertInDisabledState(); 5259 5260 // APM toggle on, no change to Wifi state 5261 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 5262 mActiveModeWarden.airplaneModeToggled(); 5263 mLooper.dispatchAll(); 5264 assertInDisabledState(); 5265 5266 // APM toggle off, no change to Wifi state 5267 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 5268 mActiveModeWarden.airplaneModeToggled(); 5269 mLooper.dispatchAll(); 5270 assertInDisabledState(); 5271 5272 // Satellite mode is off, enable Wifi 5273 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5274 mActiveModeWarden.handleSatelliteModeChange(); 5275 mLooper.dispatchAll(); 5276 assertInEnabledState(); 5277 } 5278 5279 @Test testToggleWifiWithSatelliteAndAirplaneMode()5280 public void testToggleWifiWithSatelliteAndAirplaneMode() throws Exception { 5281 // Sequence: APM ON -> Wifi ON -> Satellite ON -> APM OFF -> Satellite OFF 5282 5283 // Wifi is enabled 5284 enterClientModeActiveState(); 5285 assertInEnabledState(); 5286 5287 // APM toggle on, Wifi disabled 5288 assertWifiShutDown(() -> { 5289 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 5290 mActiveModeWarden.airplaneModeToggled(); 5291 mLooper.dispatchAll(); 5292 }); 5293 mClientListener.onStopped(mClientModeManager); 5294 mLooper.dispatchAll(); 5295 assertInDisabledState(); 5296 5297 // Wifi on 5298 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 5299 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 5300 mLooper.dispatchAll(); 5301 assertInEnabledState(); 5302 5303 // Satellite mode is ON, disable Wifi 5304 assertWifiShutDown(() -> { 5305 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5306 mActiveModeWarden.handleSatelliteModeChange(); 5307 mLooper.dispatchAll(); 5308 }); 5309 mClientListener.onStopped(mClientModeManager); 5310 mLooper.dispatchAll(); 5311 assertInDisabledState(); 5312 5313 // APM toggle off, no change to Wifi state 5314 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 5315 mActiveModeWarden.airplaneModeToggled(); 5316 mLooper.dispatchAll(); 5317 assertInDisabledState(); 5318 5319 // Satellite mode is off, enable Wifi 5320 when(mSettingsStore.isSatelliteModeOn()).thenReturn(false); 5321 mActiveModeWarden.handleSatelliteModeChange(); 5322 mLooper.dispatchAll(); 5323 assertInEnabledState(); 5324 } 5325 5326 @Test testSatelliteModemDisableWifiWhenLocationModeChanged()5327 public void testSatelliteModemDisableWifiWhenLocationModeChanged() throws Exception { 5328 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 5329 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 5330 5331 // Wifi is enabled 5332 enterClientModeActiveState(); 5333 assertInEnabledState(); 5334 5335 // Satellite mode is ON, disable Wifi 5336 assertWifiShutDown(() -> { 5337 when(mSettingsStore.isSatelliteModeOn()).thenReturn(true); 5338 mActiveModeWarden.handleSatelliteModeChange(); 5339 mLooper.dispatchAll(); 5340 }); 5341 mClientListener.onStopped(mClientModeManager); 5342 mLooper.dispatchAll(); 5343 assertInDisabledState(); 5344 5345 // Location state changes 5346 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 5347 ArgumentCaptor.forClass(BroadcastReceiver.class); 5348 verify(mContext).registerReceiver( 5349 bcastRxCaptor.capture(), 5350 argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); 5351 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 5352 5353 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 5354 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); 5355 broadcastReceiver.onReceive(mContext, intent); 5356 mLooper.dispatchAll(); 5357 5358 // Ensure Wi-Fi is still disabled 5359 assertInDisabledState(); 5360 } 5361 5362 @Test testOnIdleModeChanged()5363 public void testOnIdleModeChanged() throws Exception { 5364 enterClientModeActiveState(); 5365 List<ClientModeManager> currentCMMs = mActiveModeWarden.getClientModeManagers(); 5366 assertTrue(currentCMMs.size() >= 1); 5367 mActiveModeWarden.onIdleModeChanged(true); 5368 for (ClientModeManager cmm : currentCMMs) { 5369 verify(cmm).onIdleModeChanged(true); 5370 } 5371 } 5372 5373 @Test testWepNotDeprecated()5374 public void testWepNotDeprecated() throws Exception { 5375 when(mWifiGlobals.isWepSupported()).thenReturn(true); 5376 enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WEP); 5377 } 5378 5379 @Test testWpaPersonalNotDeprecated()5380 public void testWpaPersonalNotDeprecated() throws Exception { 5381 when(mWifiGlobals.isWpaPersonalDeprecated()).thenReturn(false); 5382 enterClientModeActiveState(false, TEST_FEATURE_SET | WifiManager.WIFI_FEATURE_WPA_PERSONAL); 5383 } 5384 5385 @Test testD2dSupportedWhenInfraStaDisabledWhenP2pStaConcurrencySupported()5386 public void testD2dSupportedWhenInfraStaDisabledWhenP2pStaConcurrencySupported() 5387 throws Exception { 5388 when(mWifiNative.isP2pStaConcurrencySupported()).thenReturn(true); 5389 when(mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()).thenReturn(true); 5390 mActiveModeWarden = createActiveModeWarden(); 5391 mActiveModeWarden.start(); 5392 mLooper.dispatchAll(); 5393 verify(mWifiGlobals).setD2dStaConcurrencySupported(true); 5394 verify(mWifiGlobals, atLeastOnce()).isD2dSupportedWhenInfraStaDisabled(); 5395 } 5396 5397 @Test testD2dSupportedWhenInfraStaDisabledWhenNanStaConcurrencySupported()5398 public void testD2dSupportedWhenInfraStaDisabledWhenNanStaConcurrencySupported() 5399 throws Exception { 5400 when(mWifiNative.isNanStaConcurrencySupported()).thenReturn(true); 5401 when(mWifiGlobals.isD2dSupportedWhenInfraStaDisabled()).thenReturn(true); 5402 mActiveModeWarden = createActiveModeWarden(); 5403 mActiveModeWarden.start(); 5404 mLooper.dispatchAll(); 5405 verify(mWifiGlobals).setD2dStaConcurrencySupported(true); 5406 verify(mWifiGlobals, atLeastOnce()).isD2dSupportedWhenInfraStaDisabled(); 5407 } 5408 } 5409