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 com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_LOCAL_ONLY; 20 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY; 21 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY; 22 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_LONG_LIVED; 23 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT; 24 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_LOCAL_ONLY; 25 import static com.android.server.wifi.ActiveModeManager.ROLE_SOFTAP_TETHERED; 26 import static com.android.server.wifi.ActiveModeWarden.INTERNAL_REQUESTOR_WS; 27 28 import static com.google.common.truth.Truth.assertThat; 29 import static com.google.common.truth.Truth.assertWithMessage; 30 31 import static org.junit.Assert.assertEquals; 32 import static org.junit.Assert.assertFalse; 33 import static org.junit.Assert.assertNull; 34 import static org.junit.Assert.assertTrue; 35 import static org.mockito.ArgumentMatchers.anyBoolean; 36 import static org.mockito.ArgumentMatchers.argThat; 37 import static org.mockito.Mockito.any; 38 import static org.mockito.Mockito.anyInt; 39 import static org.mockito.Mockito.anyString; 40 import static org.mockito.Mockito.atLeastOnce; 41 import static org.mockito.Mockito.clearInvocations; 42 import static org.mockito.Mockito.doAnswer; 43 import static org.mockito.Mockito.doThrow; 44 import static org.mockito.Mockito.eq; 45 import static org.mockito.Mockito.mock; 46 import static org.mockito.Mockito.mockingDetails; 47 import static org.mockito.Mockito.never; 48 import static org.mockito.Mockito.reset; 49 import static org.mockito.Mockito.times; 50 import static org.mockito.Mockito.verify; 51 import static org.mockito.Mockito.verifyNoMoreInteractions; 52 import static org.mockito.Mockito.verifyZeroInteractions; 53 import static org.mockito.Mockito.when; 54 55 import android.annotation.Nullable; 56 import android.content.BroadcastReceiver; 57 import android.content.Context; 58 import android.content.Intent; 59 import android.content.res.Resources; 60 import android.location.LocationManager; 61 import android.net.wifi.ISubsystemRestartCallback; 62 import android.net.wifi.IWifiConnectedNetworkScorer; 63 import android.net.wifi.SoftApCapability; 64 import android.net.wifi.SoftApConfiguration; 65 import android.net.wifi.SoftApConfiguration.Builder; 66 import android.net.wifi.SoftApInfo; 67 import android.net.wifi.WifiClient; 68 import android.net.wifi.WifiConfiguration; 69 import android.net.wifi.WifiManager; 70 import android.os.BatteryStatsManager; 71 import android.os.Build; 72 import android.os.IBinder; 73 import android.os.Process; 74 import android.os.RemoteException; 75 import android.os.WorkSource; 76 import android.os.test.TestLooper; 77 import android.telephony.TelephonyManager; 78 import android.util.Log; 79 80 import androidx.test.filters.SmallTest; 81 82 import com.android.server.wifi.ActiveModeManager.ClientConnectivityRole; 83 import com.android.server.wifi.ActiveModeManager.Listener; 84 import com.android.server.wifi.ActiveModeManager.SoftApRole; 85 import com.android.server.wifi.ActiveModeWarden.ExternalClientModeManagerRequestListener; 86 import com.android.server.wifi.util.GeneralUtil.Mutable; 87 import com.android.server.wifi.util.WifiPermissionsUtil; 88 import com.android.wifi.resources.R; 89 90 import org.junit.After; 91 import org.junit.Before; 92 import org.junit.Test; 93 import org.mockito.ArgumentCaptor; 94 import org.mockito.Mock; 95 import org.mockito.Mockito; 96 import org.mockito.MockitoAnnotations; 97 import org.mockito.invocation.InvocationOnMock; 98 import org.mockito.stubbing.Answer; 99 100 import java.io.ByteArrayOutputStream; 101 import java.io.PrintWriter; 102 import java.util.Collection; 103 import java.util.HashMap; 104 import java.util.List; 105 import java.util.Map; 106 import java.util.stream.Collectors; 107 108 /** 109 * Unit tests for {@link com.android.server.wifi.ActiveModeWarden}. 110 */ 111 @SmallTest 112 public class ActiveModeWardenTest extends WifiBaseTest { 113 public static final String TAG = "WifiActiveModeWardenTest"; 114 115 private static final String ENABLED_STATE_STRING = "EnabledState"; 116 private static final String DISABLED_STATE_STRING = "DisabledState"; 117 private static final String TEST_SSID_1 = "\"Ssid12345\""; 118 private static final String TEST_SSID_2 = "\"Ssid45678\""; 119 private static final String TEST_SSID_3 = "\"Ssid98765\""; 120 private static final String TEST_BSSID_1 = "01:12:23:34:45:56"; 121 private static final String TEST_BSSID_2 = "10:21:32:43:54:65"; 122 private static final String TEST_BSSID_3 = "11:22:33:44:55:66"; 123 124 private static final String WIFI_IFACE_NAME = "mockWlan"; 125 private static final String WIFI_IFACE_NAME_1 = "mockWlan1"; 126 private static final int TEST_WIFI_RECOVERY_DELAY_MS = 2000; 127 private static final int TEST_AP_FREQUENCY = 2412; 128 private static final int TEST_AP_BANDWIDTH = SoftApInfo.CHANNEL_WIDTH_20MHZ; 129 private static final int TEST_UID = 435546654; 130 private static final String TEST_PACKAGE = "com.test"; 131 private static final WorkSource TEST_WORKSOURCE = new WorkSource(TEST_UID, TEST_PACKAGE); 132 133 TestLooper mLooper; 134 @Mock WifiInjector mWifiInjector; 135 @Mock Context mContext; 136 @Mock Resources mResources; 137 @Mock WifiNative mWifiNative; 138 @Mock WifiApConfigStore mWifiApConfigStore; 139 @Mock ConcreteClientModeManager mClientModeManager; 140 @Mock SoftApManager mSoftApManager; 141 @Mock DefaultClientModeManager mDefaultClientModeManager; 142 @Mock BatteryStatsManager mBatteryStats; 143 @Mock SelfRecovery mSelfRecovery; 144 @Mock WifiDiagnostics mWifiDiagnostics; 145 @Mock ScanRequestProxy mScanRequestProxy; 146 @Mock FrameworkFacade mFacade; 147 @Mock WifiSettingsStore mSettingsStore; 148 @Mock WifiPermissionsUtil mWifiPermissionsUtil; 149 @Mock SoftApCapability mSoftApCapability; 150 @Mock ActiveModeWarden.ModeChangeCallback mModeChangeCallback; 151 @Mock ActiveModeWarden.PrimaryClientModeManagerChangedCallback mPrimaryChangedCallback; 152 @Mock WifiMetrics mWifiMetrics; 153 @Mock ISubsystemRestartCallback mSubsystemRestartCallback; 154 @Mock ExternalScoreUpdateObserverProxy mExternalScoreUpdateObserverProxy; 155 @Mock DppManager mDppManager; 156 @Mock SarManager mSarManager; 157 @Mock HalDeviceManager mHalDeviceManager; 158 159 Listener<ConcreteClientModeManager> mClientListener; 160 Listener<SoftApManager> mSoftApListener; 161 WifiServiceImpl.SoftApCallbackInternal mSoftApManagerCallback; 162 SoftApModeConfiguration mSoftApConfig; 163 @Mock WifiServiceImpl.SoftApCallbackInternal mSoftApStateMachineCallback; 164 @Mock WifiServiceImpl.SoftApCallbackInternal mLohsStateMachineCallback; 165 WifiNative.StatusListener mWifiNativeStatusListener; 166 ActiveModeWarden mActiveModeWarden; 167 private SoftApInfo mTestSoftApInfo; 168 169 final ArgumentCaptor<WifiNative.StatusListener> mStatusListenerCaptor = 170 ArgumentCaptor.forClass(WifiNative.StatusListener.class); 171 172 private BroadcastReceiver mEmergencyCallbackModeChangedBr; 173 private BroadcastReceiver mEmergencyCallStateChangedBr; 174 175 /** 176 * Set up the test environment. 177 */ 178 @Before setUp()179 public void setUp() throws Exception { 180 Log.d(TAG, "Setting up ..."); 181 182 MockitoAnnotations.initMocks(this); 183 mLooper = new TestLooper(); 184 185 when(mWifiInjector.getScanRequestProxy()).thenReturn(mScanRequestProxy); 186 when(mWifiInjector.getSarManager()).thenReturn(mSarManager); 187 when(mWifiInjector.getHalDeviceManager()).thenReturn(mHalDeviceManager); 188 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 189 when(mClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME); 190 when(mContext.getResources()).thenReturn(mResources); 191 when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); 192 193 when(mResources.getString(R.string.wifi_localhotspot_configure_ssid_default)) 194 .thenReturn("AndroidShare"); 195 when(mResources.getInteger(R.integer.config_wifi_framework_recovery_timeout_delay)) 196 .thenReturn(TEST_WIFI_RECOVERY_DELAY_MS); 197 when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) 198 .thenReturn(false); 199 when(mResources.getBoolean(R.bool.config_wifi_turn_off_during_emergency_call)) 200 .thenReturn(true); 201 202 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 203 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 204 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 205 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 206 when(mFacade.getSettingsWorkSource(mContext)).thenReturn(TEST_WORKSOURCE); 207 208 doAnswer(new Answer<ClientModeManager>() { 209 public ClientModeManager answer(InvocationOnMock invocation) { 210 Object[] args = invocation.getArguments(); 211 mClientListener = (Listener<ConcreteClientModeManager>) args[0]; 212 return mClientModeManager; 213 } 214 }).when(mWifiInjector).makeClientModeManager( 215 any(Listener.class), any(), any(), anyBoolean()); 216 doAnswer(new Answer<SoftApManager>() { 217 public SoftApManager answer(InvocationOnMock invocation) { 218 Object[] args = invocation.getArguments(); 219 mSoftApListener = (Listener<SoftApManager>) args[0]; 220 mSoftApManagerCallback = (WifiServiceImpl.SoftApCallbackInternal) args[1]; 221 mSoftApConfig = (SoftApModeConfiguration) args[2]; 222 return mSoftApManager; 223 } 224 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 225 any(WifiServiceImpl.SoftApCallbackInternal.class), any(), any(), any(), 226 anyBoolean()); 227 when(mWifiNative.initialize()).thenReturn(true); 228 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(true); 229 230 mActiveModeWarden = createActiveModeWarden(); 231 mActiveModeWarden.start(); 232 mLooper.dispatchAll(); 233 234 verify(mWifiMetrics).noteWifiEnabledDuringBoot(false); 235 236 verify(mWifiNative).registerStatusListener(mStatusListenerCaptor.capture()); 237 verify(mWifiNative).initialize(); 238 mWifiNativeStatusListener = mStatusListenerCaptor.getValue(); 239 240 mActiveModeWarden.registerSoftApCallback(mSoftApStateMachineCallback); 241 mActiveModeWarden.registerLohsCallback(mLohsStateMachineCallback); 242 mActiveModeWarden.registerModeChangeCallback(mModeChangeCallback); 243 mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback(mPrimaryChangedCallback); 244 when(mSubsystemRestartCallback.asBinder()).thenReturn(Mockito.mock(IBinder.class)); 245 mActiveModeWarden.registerSubsystemRestartCallback(mSubsystemRestartCallback); 246 mTestSoftApInfo = new SoftApInfo(); 247 mTestSoftApInfo.setFrequency(TEST_AP_FREQUENCY); 248 mTestSoftApInfo.setBandwidth(TEST_AP_BANDWIDTH); 249 250 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 251 ArgumentCaptor.forClass(BroadcastReceiver.class); 252 verify(mContext).registerReceiver( 253 bcastRxCaptor.capture(), 254 argThat(filter -> 255 filter.hasAction(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED))); 256 mEmergencyCallbackModeChangedBr = bcastRxCaptor.getValue(); 257 258 verify(mContext).registerReceiver( 259 bcastRxCaptor.capture(), 260 argThat(filter -> 261 filter.hasAction(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED))); 262 mEmergencyCallStateChangedBr = bcastRxCaptor.getValue(); 263 } 264 createActiveModeWarden()265 private ActiveModeWarden createActiveModeWarden() { 266 ActiveModeWarden warden = new ActiveModeWarden( 267 mWifiInjector, 268 mLooper.getLooper(), 269 mWifiNative, 270 mDefaultClientModeManager, 271 mBatteryStats, 272 mWifiDiagnostics, 273 mContext, 274 mSettingsStore, 275 mFacade, 276 mWifiPermissionsUtil, 277 mWifiMetrics, 278 mExternalScoreUpdateObserverProxy, 279 mDppManager); 280 // SelfRecovery is created in WifiInjector after ActiveModeWarden, so getSelfRecovery() 281 // returns null when constructing ActiveModeWarden. 282 when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery); 283 return warden; 284 } 285 286 /** 287 * Clean up after tests - explicitly set tested object to null. 288 */ 289 @After cleanUp()290 public void cleanUp() throws Exception { 291 mActiveModeWarden = null; 292 mLooper.dispatchAll(); 293 } 294 emergencyCallbackModeChanged(boolean enabled)295 private void emergencyCallbackModeChanged(boolean enabled) { 296 Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 297 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, enabled); 298 mEmergencyCallbackModeChangedBr.onReceive(mContext, intent); 299 } 300 emergencyCallStateChanged(boolean enabled)301 private void emergencyCallStateChanged(boolean enabled) { 302 Intent intent = new Intent(TelephonyManager.ACTION_EMERGENCY_CALL_STATE_CHANGED); 303 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, enabled); 304 mEmergencyCallStateChangedBr.onReceive(mContext, intent); 305 } 306 enterClientModeActiveState()307 private void enterClientModeActiveState() throws Exception { 308 enterClientModeActiveState(false); 309 } 310 311 /** 312 * Helper method to enter the EnabledState and set ClientModeManager in ConnectMode. 313 * @param isClientModeSwitch true if switching from another mode, false if creating a new one 314 */ enterClientModeActiveState(boolean isClientModeSwitch)315 private void enterClientModeActiveState(boolean isClientModeSwitch) throws Exception { 316 String fromState = mActiveModeWarden.getCurrentMode(); 317 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 318 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 319 mLooper.dispatchAll(); 320 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 321 // ClientModeManager starts in SCAN_ONLY role. 322 mClientListener.onRoleChanged(mClientModeManager); 323 mLooper.dispatchAll(); 324 325 assertInEnabledState(); 326 if (!isClientModeSwitch) { 327 verify(mWifiInjector).makeClientModeManager( 328 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 329 } else { 330 verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE); 331 } 332 verify(mScanRequestProxy).enableScanning(true, true); 333 if (fromState.equals(DISABLED_STATE_STRING)) { 334 verify(mBatteryStats).reportWifiOn(); 335 } 336 assertEquals(mClientModeManager, mActiveModeWarden.getPrimaryClientModeManager()); 337 verify(mModeChangeCallback).onActiveModeManagerRoleChanged(mClientModeManager); 338 } 339 enterScanOnlyModeActiveState()340 private void enterScanOnlyModeActiveState() throws Exception { 341 enterScanOnlyModeActiveState(false); 342 } 343 344 /** 345 * Helper method to enter the EnabledState and set ClientModeManager in ScanOnlyMode. 346 */ enterScanOnlyModeActiveState(boolean isClientModeSwitch)347 private void enterScanOnlyModeActiveState(boolean isClientModeSwitch) throws Exception { 348 String fromState = mActiveModeWarden.getCurrentMode(); 349 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 350 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 351 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 352 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 353 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 354 mLooper.dispatchAll(); 355 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 356 357 if (!isClientModeSwitch) { 358 mClientListener.onStarted(mClientModeManager); 359 mLooper.dispatchAll(); 360 verify(mWifiInjector).makeClientModeManager( 361 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 362 verify(mModeChangeCallback).onActiveModeManagerAdded(mClientModeManager); 363 } else { 364 mClientListener.onRoleChanged(mClientModeManager); 365 mLooper.dispatchAll(); 366 verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY, INTERNAL_REQUESTOR_WS); 367 // If switching from client mode back to scan only mode, role change would have been 368 // called once before when transitioning from scan only mode to client mode. 369 // Verify that it was called again. 370 verify(mModeChangeCallback, times(2)) 371 .onActiveModeManagerRoleChanged(mClientModeManager); 372 } 373 assertInEnabledState(); 374 verify(mScanRequestProxy).enableScanning(true, false); 375 if (fromState.equals(DISABLED_STATE_STRING)) { 376 verify(mBatteryStats).reportWifiOn(); 377 } 378 verify(mBatteryStats).reportWifiState(BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); 379 assertEquals(mClientModeManager, mActiveModeWarden.getScanOnlyClientModeManager()); 380 } 381 enterSoftApActiveMode()382 private void enterSoftApActiveMode() throws Exception { 383 enterSoftApActiveMode( 384 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 385 mSoftApCapability)); 386 } 387 388 private int mTimesCreatedSoftApManager = 1; 389 390 /** 391 * Helper method to activate SoftApManager. 392 * 393 * This method puts the test object into the correct state and verifies steps along the way. 394 */ enterSoftApActiveMode(SoftApModeConfiguration softApConfig)395 private void enterSoftApActiveMode(SoftApModeConfiguration softApConfig) throws Exception { 396 String fromState = mActiveModeWarden.getCurrentMode(); 397 SoftApRole softApRole = softApConfig.getTargetMode() == WifiManager.IFACE_IP_MODE_TETHERED 398 ? ROLE_SOFTAP_TETHERED : ROLE_SOFTAP_LOCAL_ONLY; 399 mActiveModeWarden.startSoftAp(softApConfig, TEST_WORKSOURCE); 400 mLooper.dispatchAll(); 401 when(mSoftApManager.getRole()).thenReturn(softApRole); 402 when(mSoftApManager.getSoftApModeConfiguration()).thenReturn(softApConfig); 403 mSoftApListener.onStarted(mSoftApManager); 404 mLooper.dispatchAll(); 405 406 assertInEnabledState(); 407 assertThat(softApConfig).isEqualTo(mSoftApConfig); 408 verify(mWifiInjector, times(mTimesCreatedSoftApManager)).makeSoftApManager( 409 any(), any(), any(), eq(TEST_WORKSOURCE), eq(softApRole), anyBoolean()); 410 mTimesCreatedSoftApManager++; 411 if (fromState.equals(DISABLED_STATE_STRING)) { 412 verify(mBatteryStats).reportWifiOn(); 413 } 414 if (softApRole == ROLE_SOFTAP_TETHERED) { 415 assertEquals(mSoftApManager, mActiveModeWarden.getTetheredSoftApManager()); 416 assertNull(mActiveModeWarden.getLocalOnlySoftApManager()); 417 } else { 418 assertEquals(mSoftApManager, mActiveModeWarden.getLocalOnlySoftApManager()); 419 assertNull(mActiveModeWarden.getTetheredSoftApManager()); 420 } 421 verify(mModeChangeCallback).onActiveModeManagerAdded(mSoftApManager); 422 } 423 enterStaDisabledMode(boolean isSoftApModeManagerActive)424 private void enterStaDisabledMode(boolean isSoftApModeManagerActive) { 425 String fromState = mActiveModeWarden.getCurrentMode(); 426 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 427 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 428 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 429 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 430 mLooper.dispatchAll(); 431 if (mClientListener != null) { 432 mClientListener.onStopped(mClientModeManager); 433 mLooper.dispatchAll(); 434 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 435 } 436 437 if (isSoftApModeManagerActive) { 438 assertInEnabledState(); 439 } else { 440 assertInDisabledState(); 441 } 442 if (fromState.equals(ENABLED_STATE_STRING)) { 443 verify(mScanRequestProxy).enableScanning(false, false); 444 } 445 // Ensure we return the default client mode manager when wifi is off. 446 assertEquals(mDefaultClientModeManager, mActiveModeWarden.getPrimaryClientModeManager()); 447 } 448 shutdownWifi()449 private void shutdownWifi() { 450 mActiveModeWarden.recoveryDisableWifi(); 451 mLooper.dispatchAll(); 452 } 453 assertInEnabledState()454 private void assertInEnabledState() { 455 assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(ENABLED_STATE_STRING); 456 } 457 assertInDisabledState()458 private void assertInDisabledState() { 459 assertThat(mActiveModeWarden.getCurrentMode()).isEqualTo(DISABLED_STATE_STRING); 460 } 461 462 /** 463 * Emergency mode is a sub-mode within each main state (ScanOnly, Client, DisabledState). 464 */ assertInEmergencyMode()465 private void assertInEmergencyMode() { 466 assertThat(mActiveModeWarden.isInEmergencyMode()).isTrue(); 467 } 468 assertNotInEmergencyMode()469 private void assertNotInEmergencyMode() { 470 assertThat(mActiveModeWarden.isInEmergencyMode()).isFalse(); 471 } 472 473 /** 474 * Counts the number of times a void method was called on a mock. 475 * 476 * Void methods cannot be passed to Mockito.mockingDetails(). Thus we have to use method name 477 * matching instead. 478 */ getMethodInvocationCount(Object mock, String methodName)479 private static int getMethodInvocationCount(Object mock, String methodName) { 480 long count = mockingDetails(mock).getInvocations() 481 .stream() 482 .filter(invocation -> methodName.equals(invocation.getMethod().getName())) 483 .count(); 484 return (int) count; 485 } 486 487 /** 488 * Counts the number of times a non-void method was called on a mock. 489 * 490 * For non-void methods, can pass the method call literal directly: 491 * e.g. getMethodInvocationCount(mock.method()); 492 */ getMethodInvocationCount(Object mockMethod)493 private static int getMethodInvocationCount(Object mockMethod) { 494 return mockingDetails(mockMethod).getInvocations().size(); 495 } 496 assertWifiShutDown(Runnable r)497 private void assertWifiShutDown(Runnable r) { 498 assertWifiShutDown(r, 1); 499 } 500 501 /** 502 * Asserts that the runnable r has shut down wifi properly. 503 * 504 * @param r runnable that will shut down wifi 505 * @param times expected number of times that <code>r</code> shut down wifi 506 */ assertWifiShutDown(Runnable r, int times)507 private void assertWifiShutDown(Runnable r, int times) { 508 // take snapshot of ActiveModeManagers 509 Collection<ActiveModeManager> activeModeManagers = 510 mActiveModeWarden.getActiveModeManagers(); 511 512 List<Integer> expectedStopInvocationCounts = activeModeManagers 513 .stream() 514 .map(manager -> getMethodInvocationCount(manager, "stop") + times) 515 .collect(Collectors.toList()); 516 517 r.run(); 518 519 List<Integer> actualStopInvocationCounts = activeModeManagers 520 .stream() 521 .map(manager -> getMethodInvocationCount(manager, "stop")) 522 .collect(Collectors.toList()); 523 524 String managerNames = activeModeManagers.stream() 525 .map(manager -> manager.getClass().getCanonicalName()) 526 .collect(Collectors.joining(", ", "[", "]")); 527 528 assertWithMessage(managerNames).that(actualStopInvocationCounts) 529 .isEqualTo(expectedStopInvocationCounts); 530 } 531 assertEnteredEcmMode(Runnable r)532 private void assertEnteredEcmMode(Runnable r) { 533 assertEnteredEcmMode(r, 1); 534 } 535 536 /** 537 * Asserts that the runnable r has entered ECM state properly. 538 * 539 * @param r runnable that will enter ECM 540 * @param times expected number of times that <code>r</code> shut down wifi 541 */ assertEnteredEcmMode(Runnable r, int times)542 private void assertEnteredEcmMode(Runnable r, int times) { 543 // take snapshot of ActiveModeManagers 544 Collection<ActiveModeManager> activeModeManagers = 545 mActiveModeWarden.getActiveModeManagers(); 546 547 boolean disableWifiInEcm = mFacade.getConfigWiFiDisableInECBM(mContext); 548 549 List<Integer> expectedStopInvocationCounts = activeModeManagers.stream() 550 .map(manager -> { 551 int initialCount = getMethodInvocationCount(manager, "stop"); 552 // carrier config enabled, all mode managers should have been shut down once 553 int count = disableWifiInEcm ? initialCount + times : initialCount; 554 if (manager instanceof SoftApManager) { 555 // expect SoftApManager.close() to be called 556 return count + times; 557 } else { 558 // don't expect other Managers close() to be called 559 return count; 560 } 561 }) 562 .collect(Collectors.toList()); 563 564 r.run(); 565 566 assertInEmergencyMode(); 567 568 List<Integer> actualStopInvocationCounts = activeModeManagers.stream() 569 .map(manager -> getMethodInvocationCount(manager, "stop")) 570 .collect(Collectors.toList()); 571 572 String managerNames = activeModeManagers.stream() 573 .map(manager -> manager.getClass().getCanonicalName()) 574 .collect(Collectors.joining(", ", "[", "]")); 575 576 assertWithMessage(managerNames).that(actualStopInvocationCounts) 577 .isEqualTo(expectedStopInvocationCounts); 578 } 579 580 /** Test that after starting up, ActiveModeWarden is in the DisabledState State. */ 581 @Test testDisabledStateAtStartup()582 public void testDisabledStateAtStartup() { 583 assertInDisabledState(); 584 } 585 586 /** 587 * Test that ActiveModeWarden properly enters the EnabledState (in ScanOnlyMode) from the 588 * DisabledState state. 589 */ 590 @Test testEnterScanOnlyModeFromDisabled()591 public void testEnterScanOnlyModeFromDisabled() throws Exception { 592 enterScanOnlyModeActiveState(); 593 } 594 595 /** 596 * Test that ActiveModeWarden enables hidden network scanning in scan-only-mode 597 * if configured to do. 598 */ 599 @Test testScanOnlyModeScanHiddenNetworks()600 public void testScanOnlyModeScanHiddenNetworks() throws Exception { 601 when(mResources.getBoolean(R.bool.config_wifiScanHiddenNetworksScanOnlyMode)) 602 .thenReturn(true); 603 604 mActiveModeWarden = createActiveModeWarden(); 605 mActiveModeWarden.start(); 606 mLooper.dispatchAll(); 607 608 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 609 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 610 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 611 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 612 mLooper.dispatchAll(); 613 mClientListener.onStarted(mClientModeManager); 614 mLooper.dispatchAll(); 615 616 assertInEnabledState(); 617 verify(mWifiInjector).makeClientModeManager( 618 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 619 verify(mScanRequestProxy).enableScanning(true, true); 620 } 621 622 /** 623 * Test that ActiveModeWarden properly starts the SoftApManager from the 624 * DisabledState state. 625 */ 626 @Test testEnterSoftApModeFromDisabled()627 public void testEnterSoftApModeFromDisabled() throws Exception { 628 enterSoftApActiveMode(); 629 } 630 631 /** 632 * Test that ActiveModeWarden properly starts the SoftApManager from another state. 633 */ 634 @Test testEnterSoftApModeFromDifferentState()635 public void testEnterSoftApModeFromDifferentState() throws Exception { 636 enterClientModeActiveState(); 637 assertInEnabledState(); 638 reset(mBatteryStats, mScanRequestProxy); 639 enterSoftApActiveMode(); 640 } 641 642 /** 643 * Test that we can disable wifi fully from the EnabledState (in ScanOnlyMode). 644 */ 645 @Test testDisableWifiFromScanOnlyModeActiveState()646 public void testDisableWifiFromScanOnlyModeActiveState() throws Exception { 647 enterScanOnlyModeActiveState(); 648 649 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 650 mActiveModeWarden.scanAlwaysModeChanged(); 651 mLooper.dispatchAll(); 652 mClientListener.onStopped(mClientModeManager); 653 mLooper.dispatchAll(); 654 655 verify(mClientModeManager).stop(); 656 verify(mBatteryStats).reportWifiOff(); 657 assertInDisabledState(); 658 } 659 660 /** 661 * Test that we can disable wifi when SoftApManager is active and not impact softap. 662 */ 663 @Test testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp()664 public void testDisableWifiFromSoftApModeActiveStateDoesNotStopSoftAp() throws Exception { 665 enterSoftApActiveMode(); 666 enterScanOnlyModeActiveState(); 667 668 reset(mDefaultClientModeManager); 669 enterStaDisabledMode(true); 670 verify(mSoftApManager, never()).stop(); 671 verify(mBatteryStats, never()).reportWifiOff(); 672 } 673 674 /** 675 * Test that we can switch from the EnabledState (in ScanOnlyMode) to another mode. 676 */ 677 @Test testSwitchModeWhenScanOnlyModeActiveState()678 public void testSwitchModeWhenScanOnlyModeActiveState() throws Exception { 679 enterScanOnlyModeActiveState(); 680 681 reset(mBatteryStats, mScanRequestProxy); 682 enterClientModeActiveState(true); 683 mLooper.dispatchAll(); 684 } 685 686 /** 687 * Test that we can switch from the EnabledState (in ConnectMode) to another mode. 688 */ 689 @Test testSwitchModeWhenConnectModeActiveState()690 public void testSwitchModeWhenConnectModeActiveState() throws Exception { 691 enterClientModeActiveState(); 692 693 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 694 695 reset(mBatteryStats, mScanRequestProxy); 696 enterScanOnlyModeActiveState(true); 697 mLooper.dispatchAll(); 698 699 verify(mPrimaryChangedCallback).onChange(mClientModeManager, null); 700 } 701 702 /** 703 * Reentering EnabledState should be a NOP. 704 */ 705 @Test testReenterClientModeActiveStateIsNop()706 public void testReenterClientModeActiveStateIsNop() throws Exception { 707 enterClientModeActiveState(); 708 verify(mWifiInjector, times(1)).makeClientModeManager( 709 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 710 711 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 712 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 713 mLooper.dispatchAll(); 714 // Should not start again. 715 verify(mWifiInjector, times(1)).makeClientModeManager( 716 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 717 } 718 719 /** 720 * Test that we can switch mode when SoftApManager is active to another mode. 721 */ 722 @Test testSwitchModeWhenSoftApActiveMode()723 public void testSwitchModeWhenSoftApActiveMode() throws Exception { 724 enterSoftApActiveMode(); 725 726 reset(mWifiNative); 727 728 enterClientModeActiveState(); 729 mLooper.dispatchAll(); 730 verify(mSoftApManager, never()).stop(); 731 assertInEnabledState(); 732 verify(mWifiNative, never()).teardownAllInterfaces(); 733 } 734 735 /** 736 * Test that we activate SoftApModeManager if we are already in DisabledState due to 737 * a failure. 738 */ 739 @Test testEnterSoftApModeActiveWhenAlreadyInSoftApMode()740 public void testEnterSoftApModeActiveWhenAlreadyInSoftApMode() throws Exception { 741 enterSoftApActiveMode(); 742 // now inject failure through the SoftApManager.Listener 743 mSoftApListener.onStartFailure(mSoftApManager); 744 mLooper.dispatchAll(); 745 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 746 assertInDisabledState(); 747 // clear the first call to start SoftApManager 748 reset(mSoftApManager, mBatteryStats, mModeChangeCallback); 749 750 enterSoftApActiveMode(); 751 } 752 753 /** 754 * Test that we return to the DisabledState after a failure is reported when in the 755 * EnabledState. 756 */ 757 @Test testScanOnlyModeFailureWhenActive()758 public void testScanOnlyModeFailureWhenActive() throws Exception { 759 enterScanOnlyModeActiveState(); 760 // now inject a failure through the ScanOnlyModeManager.Listener 761 mClientListener.onStartFailure(mClientModeManager); 762 mLooper.dispatchAll(); 763 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 764 assertInDisabledState(); 765 verify(mBatteryStats).reportWifiOff(); 766 } 767 768 /** 769 * Test that we return to the DisabledState after a failure is reported when 770 * SoftApManager is active. 771 */ 772 @Test testSoftApFailureWhenActive()773 public void testSoftApFailureWhenActive() throws Exception { 774 enterSoftApActiveMode(); 775 // now inject failure through the SoftApManager.Listener 776 mSoftApListener.onStartFailure(mSoftApManager); 777 mLooper.dispatchAll(); 778 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 779 verify(mBatteryStats).reportWifiOff(); 780 } 781 782 /** 783 * Test that we return to the DisabledState after the ClientModeManager running in ScanOnlyMode 784 * is stopped. 785 */ 786 @Test testScanOnlyModeDisabledWhenActive()787 public void testScanOnlyModeDisabledWhenActive() throws Exception { 788 enterScanOnlyModeActiveState(); 789 790 // now inject the stop message through the ScanOnlyModeManager.Listener 791 mClientListener.onStopped(mClientModeManager); 792 mLooper.dispatchAll(); 793 794 assertInDisabledState(); 795 verify(mBatteryStats).reportWifiOff(); 796 } 797 798 /** 799 * Test that we return to the DisabledState after the SoftApManager is stopped. 800 */ 801 @Test testSoftApDisabledWhenActive()802 public void testSoftApDisabledWhenActive() throws Exception { 803 enterSoftApActiveMode(); 804 reset(mWifiNative); 805 // now inject failure through the SoftApManager.Listener 806 mSoftApListener.onStartFailure(mSoftApManager); 807 mLooper.dispatchAll(); 808 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 809 verify(mBatteryStats).reportWifiOff(); 810 verifyNoMoreInteractions(mWifiNative); 811 } 812 813 /** 814 * Verifies that SoftApStateChanged event is being passed from SoftApManager to WifiServiceImpl 815 */ 816 @Test callsWifiServiceCallbackOnSoftApStateChanged()817 public void callsWifiServiceCallbackOnSoftApStateChanged() throws Exception { 818 enterSoftApActiveMode(); 819 820 mSoftApListener.onStarted(mSoftApManager); 821 mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); 822 mLooper.dispatchAll(); 823 824 verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); 825 } 826 827 /** 828 * Verifies that SoftApStateChanged event isn't passed to WifiServiceImpl for LOHS, 829 * so the state change for LOHS doesn't affect Wifi Tethering indication. 830 */ 831 @Test doesntCallWifiServiceCallbackOnLOHSStateChanged()832 public void doesntCallWifiServiceCallbackOnLOHSStateChanged() throws Exception { 833 enterSoftApActiveMode(new SoftApModeConfiguration( 834 WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, mSoftApCapability)); 835 836 mSoftApListener.onStarted(mSoftApManager); 837 mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_ENABLED, 0); 838 mLooper.dispatchAll(); 839 840 verify(mSoftApStateMachineCallback, never()).onStateChanged(anyInt(), anyInt()); 841 verify(mSoftApStateMachineCallback, never()).onConnectedClientsOrInfoChanged(any(), 842 any(), anyBoolean()); 843 } 844 845 /** 846 * Verifies that ConnectedClientsOrInfoChanged event is being passed from SoftApManager 847 * to WifiServiceImpl 848 */ 849 @Test callsWifiServiceCallbackOnSoftApConnectedClientsChanged()850 public void callsWifiServiceCallbackOnSoftApConnectedClientsChanged() throws Exception { 851 final Map<String, List<WifiClient>> testClients = new HashMap(); 852 final Map<String, SoftApInfo> testInfos = new HashMap(); 853 enterSoftApActiveMode(); 854 mSoftApManagerCallback.onConnectedClientsOrInfoChanged(testInfos, testClients, false); 855 mLooper.dispatchAll(); 856 857 verify(mSoftApStateMachineCallback).onConnectedClientsOrInfoChanged( 858 testInfos, testClients, false); 859 } 860 861 /** 862 * Test that we remain in the active state when we get a state change update that scan mode is 863 * active. 864 */ 865 @Test testScanOnlyModeStaysActiveOnEnabledUpdate()866 public void testScanOnlyModeStaysActiveOnEnabledUpdate() throws Exception { 867 enterScanOnlyModeActiveState(); 868 // now inject success through the Listener 869 mClientListener.onStarted(mClientModeManager); 870 mLooper.dispatchAll(); 871 assertInEnabledState(); 872 verify(mClientModeManager, never()).stop(); 873 } 874 875 /** 876 * Test that a config passed in to the call to enterSoftApMode is used to create the new 877 * SoftApManager. 878 */ 879 @Test testConfigIsPassedToWifiInjector()880 public void testConfigIsPassedToWifiInjector() throws Exception { 881 Builder configBuilder = new SoftApConfiguration.Builder(); 882 configBuilder.setSsid("ThisIsAConfig"); 883 SoftApModeConfiguration softApConfig = new SoftApModeConfiguration( 884 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder.build(), mSoftApCapability); 885 enterSoftApActiveMode(softApConfig); 886 } 887 888 /** 889 * Test that when enterSoftAPMode is called with a null config, we pass a null config to 890 * WifiInjector.makeSoftApManager. 891 * 892 * Passing a null config to SoftApManager indicates that the default config should be used. 893 */ 894 @Test testNullConfigIsPassedToWifiInjector()895 public void testNullConfigIsPassedToWifiInjector() throws Exception { 896 enterSoftApActiveMode(); 897 } 898 899 /** 900 * Test that two calls to switch to SoftAPMode in succession ends up with the correct config. 901 * 902 * Expectation: we should end up in SoftAPMode state configured with the second config. 903 */ 904 @Test testStartSoftApModeTwiceWithTwoConfigs()905 public void testStartSoftApModeTwiceWithTwoConfigs() throws Exception { 906 when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); 907 Builder configBuilder1 = new SoftApConfiguration.Builder(); 908 configBuilder1.setSsid("ThisIsAConfig"); 909 SoftApModeConfiguration softApConfig1 = new SoftApModeConfiguration( 910 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder1.build(), 911 mSoftApCapability); 912 Builder configBuilder2 = new SoftApConfiguration.Builder(); 913 configBuilder2.setSsid("ThisIsASecondConfig"); 914 SoftApModeConfiguration softApConfig2 = new SoftApModeConfiguration( 915 WifiManager.IFACE_IP_MODE_TETHERED, configBuilder2.build(), 916 mSoftApCapability); 917 918 doAnswer(new Answer<SoftApManager>() { 919 public SoftApManager answer(InvocationOnMock invocation) { 920 Object[] args = invocation.getArguments(); 921 mSoftApListener = (Listener<SoftApManager>) args[0]; 922 return mSoftApManager; 923 } 924 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 925 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(softApConfig1), any(), any(), 926 anyBoolean()); 927 // make a second softap manager 928 SoftApManager softapManager = mock(SoftApManager.class); 929 Mutable<Listener<SoftApManager>> softApListener = 930 new Mutable<>(); 931 doAnswer(new Answer<SoftApManager>() { 932 public SoftApManager answer(InvocationOnMock invocation) { 933 Object[] args = invocation.getArguments(); 934 softApListener.value = (Listener<SoftApManager>) args[0]; 935 return softapManager; 936 } 937 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 938 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(softApConfig2), any(), any(), 939 anyBoolean()); 940 941 mActiveModeWarden.startSoftAp(softApConfig1, TEST_WORKSOURCE); 942 mLooper.dispatchAll(); 943 mSoftApListener.onStarted(mSoftApManager); 944 mActiveModeWarden.startSoftAp(softApConfig2, TEST_WORKSOURCE); 945 mLooper.dispatchAll(); 946 softApListener.value.onStarted(softapManager); 947 948 verify(mWifiInjector, times(2)).makeSoftApManager( 949 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 950 verify(mBatteryStats).reportWifiOn(); 951 } 952 953 /** 954 * Test that we safely disable wifi if it is already disabled. 955 */ 956 @Test disableWifiWhenAlreadyOff()957 public void disableWifiWhenAlreadyOff() throws Exception { 958 enterStaDisabledMode(false); 959 verifyZeroInteractions(mWifiNative); 960 } 961 962 /** 963 * Trigger recovery and a bug report if we see a native failure 964 * while the device is not shutting down 965 */ 966 @Test handleWifiNativeFailureDeviceNotShuttingDown()967 public void handleWifiNativeFailureDeviceNotShuttingDown() throws Exception { 968 mWifiNativeStatusListener.onStatusChanged(false); 969 mLooper.dispatchAll(); 970 verify(mWifiDiagnostics).triggerBugReportDataCapture( 971 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 972 verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 973 } 974 975 /** 976 * Verify the device shutting down doesn't trigger recovery or bug report. 977 */ 978 @Test handleWifiNativeFailureDeviceShuttingDown()979 public void handleWifiNativeFailureDeviceShuttingDown() throws Exception { 980 mActiveModeWarden.notifyShuttingDown(); 981 mWifiNativeStatusListener.onStatusChanged(false); 982 mLooper.dispatchAll(); 983 verify(mWifiDiagnostics, never()).triggerBugReportDataCapture( 984 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 985 verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 986 } 987 988 /** 989 * Verify an onStatusChanged callback with "true" does not trigger recovery. 990 */ 991 @Test handleWifiNativeStatusReady()992 public void handleWifiNativeStatusReady() throws Exception { 993 mWifiNativeStatusListener.onStatusChanged(true); 994 mLooper.dispatchAll(); 995 verify(mWifiDiagnostics, never()).triggerBugReportDataCapture( 996 WifiDiagnostics.REPORT_REASON_WIFINATIVE_FAILURE); 997 verify(mSelfRecovery, never()).trigger(eq(SelfRecovery.REASON_WIFINATIVE_FAILURE)); 998 } 999 1000 /** 1001 * Verify that mode stop is safe even if the underlying Client mode exited already. 1002 */ 1003 @Test shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed()1004 public void shutdownWifiDoesNotCrashWhenClientModeExitsOnDestroyed() throws Exception { 1005 enterClientModeActiveState(); 1006 1007 mClientListener.onStopped(mClientModeManager); 1008 mLooper.dispatchAll(); 1009 1010 shutdownWifi(); 1011 1012 assertInDisabledState(); 1013 } 1014 1015 /** 1016 * Verify that an interface destruction callback is safe after already having been stopped. 1017 */ 1018 @Test onDestroyedCallbackDoesNotCrashWhenClientModeAlreadyStopped()1019 public void onDestroyedCallbackDoesNotCrashWhenClientModeAlreadyStopped() throws Exception { 1020 enterClientModeActiveState(); 1021 1022 shutdownWifi(); 1023 1024 mClientListener.onStopped(mClientModeManager); 1025 mLooper.dispatchAll(); 1026 1027 assertInDisabledState(); 1028 } 1029 1030 /** 1031 * Verify that mode stop is safe even if the underlying softap mode exited already. 1032 */ 1033 @Test shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed()1034 public void shutdownWifiDoesNotCrashWhenSoftApExitsOnDestroyed() throws Exception { 1035 enterSoftApActiveMode(); 1036 1037 mSoftApListener.onStopped(mSoftApManager); 1038 mLooper.dispatchAll(); 1039 mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 1040 mLooper.dispatchAll(); 1041 1042 shutdownWifi(); 1043 1044 verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 1045 } 1046 1047 /** 1048 * Verify that an interface destruction callback is safe after already having been stopped. 1049 */ 1050 @Test onDestroyedCallbackDoesNotCrashWhenSoftApModeAlreadyStopped()1051 public void onDestroyedCallbackDoesNotCrashWhenSoftApModeAlreadyStopped() throws Exception { 1052 enterSoftApActiveMode(); 1053 1054 shutdownWifi(); 1055 1056 mSoftApListener.onStopped(mSoftApManager); 1057 mSoftApManagerCallback.onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 1058 mLooper.dispatchAll(); 1059 1060 verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_DISABLED, 0); 1061 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1062 } 1063 1064 /** 1065 * Verify that we do not crash when calling dump and wifi is fully disabled. 1066 */ 1067 @Test dumpWhenWifiFullyOffDoesNotCrash()1068 public void dumpWhenWifiFullyOffDoesNotCrash() throws Exception { 1069 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1070 PrintWriter writer = new PrintWriter(stream); 1071 mActiveModeWarden.dump(null, writer, null); 1072 } 1073 1074 /** 1075 * Verify that we trigger dump on active mode managers. 1076 */ 1077 @Test dumpCallsActiveModeManagers()1078 public void dumpCallsActiveModeManagers() throws Exception { 1079 enterSoftApActiveMode(); 1080 enterClientModeActiveState(); 1081 1082 ByteArrayOutputStream stream = new ByteArrayOutputStream(); 1083 PrintWriter writer = new PrintWriter(stream); 1084 mActiveModeWarden.dump(null, writer, null); 1085 1086 verify(mSoftApManager).dump(null, writer, null); 1087 verify(mClientModeManager).dump(null, writer, null); 1088 } 1089 1090 /** 1091 * Verify that stopping tethering doesn't stop LOHS. 1092 */ 1093 @Test testStopTetheringButNotLOHS()1094 public void testStopTetheringButNotLOHS() throws Exception { 1095 // prepare WiFi configurations 1096 when(mWifiInjector.getWifiApConfigStore()).thenReturn(mWifiApConfigStore); 1097 SoftApModeConfiguration tetherConfig = 1098 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 1099 mSoftApCapability); 1100 SoftApConfiguration lohsConfigWC = mWifiApConfigStore.generateLocalOnlyHotspotConfig( 1101 mContext, SoftApConfiguration.BAND_2GHZ, null); 1102 SoftApModeConfiguration lohsConfig = 1103 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, lohsConfigWC, 1104 mSoftApCapability); 1105 1106 // mock SoftAPManagers 1107 when(mSoftApManager.getRole()).thenReturn(ROLE_SOFTAP_TETHERED); 1108 doAnswer(new Answer<SoftApManager>() { 1109 public SoftApManager answer(InvocationOnMock invocation) { 1110 Object[] args = invocation.getArguments(); 1111 mSoftApListener = (Listener<SoftApManager>) args[0]; 1112 return mSoftApManager; 1113 } 1114 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1115 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(tetherConfig), 1116 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1117 // make a second softap manager 1118 SoftApManager lohsSoftapManager = mock(SoftApManager.class); 1119 when(lohsSoftapManager.getRole()).thenReturn(ROLE_SOFTAP_LOCAL_ONLY); 1120 Mutable<Listener<SoftApManager>> lohsSoftApListener = new Mutable<>(); 1121 doAnswer(new Answer<SoftApManager>() { 1122 public SoftApManager answer(InvocationOnMock invocation) { 1123 Object[] args = invocation.getArguments(); 1124 lohsSoftApListener.value = (Listener<SoftApManager>) args[0]; 1125 return lohsSoftapManager; 1126 } 1127 }).when(mWifiInjector).makeSoftApManager(any(Listener.class), 1128 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(lohsConfig), 1129 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_LOCAL_ONLY), anyBoolean()); 1130 1131 // enable tethering and LOHS 1132 mActiveModeWarden.startSoftAp(tetherConfig, TEST_WORKSOURCE); 1133 mLooper.dispatchAll(); 1134 mSoftApListener.onStarted(mSoftApManager); 1135 mActiveModeWarden.startSoftAp(lohsConfig, TEST_WORKSOURCE); 1136 mLooper.dispatchAll(); 1137 lohsSoftApListener.value.onStarted(lohsSoftapManager); 1138 verify(mWifiInjector).makeSoftApManager(any(Listener.class), 1139 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(tetherConfig), 1140 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1141 verify(mWifiInjector).makeSoftApManager(any(Listener.class), 1142 any(WifiServiceImpl.SoftApCallbackInternal.class), eq(lohsConfig), 1143 eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_LOCAL_ONLY), anyBoolean()); 1144 verify(mBatteryStats).reportWifiOn(); 1145 1146 // disable tethering 1147 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_TETHERED); 1148 mLooper.dispatchAll(); 1149 verify(mSoftApManager).stop(); 1150 verify(lohsSoftapManager, never()).stop(); 1151 1152 mSoftApListener.onStopped(mSoftApManager); 1153 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1154 } 1155 1156 /** 1157 * Verify that toggling wifi from disabled starts client mode. 1158 */ 1159 @Test enableWifi()1160 public void enableWifi() throws Exception { 1161 assertInDisabledState(); 1162 1163 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1164 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1165 mLooper.dispatchAll(); 1166 1167 verify(mWifiInjector).makeClientModeManager( 1168 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), 1169 anyBoolean()); 1170 mClientListener.onStarted(mClientModeManager); 1171 mLooper.dispatchAll(); 1172 1173 // always set primary, even with single STA 1174 verify(mWifiNative).setMultiStaPrimaryConnection(WIFI_IFACE_NAME); 1175 1176 assertInEnabledState(); 1177 } 1178 1179 /** 1180 * Test verifying that we can enter scan mode when the scan mode changes 1181 */ 1182 @Test enableScanMode()1183 public void enableScanMode() throws Exception { 1184 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1185 mActiveModeWarden.scanAlwaysModeChanged(); 1186 mLooper.dispatchAll(); 1187 verify(mWifiInjector).makeClientModeManager( 1188 any(), eq(new WorkSource(Process.WIFI_UID)), eq(ROLE_CLIENT_SCAN_ONLY), 1189 anyBoolean()); 1190 assertInEnabledState(); 1191 verify(mClientModeManager, never()).stop(); 1192 } 1193 1194 /** 1195 * Test verifying that we ignore scan enable event when wifi is already enabled. 1196 */ 1197 @Test ignoreEnableScanModeWhenWifiEnabled()1198 public void ignoreEnableScanModeWhenWifiEnabled() throws Exception { 1199 // Turn on WIFI 1200 assertInDisabledState(); 1201 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1202 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1203 mLooper.dispatchAll(); 1204 mClientListener.onStarted(mClientModeManager); 1205 mLooper.dispatchAll(); 1206 assertInEnabledState(); 1207 1208 // Now toggle scan only change, should be ignored. We should send a role change 1209 // again with PRIMARY & the cached requestorWs. 1210 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1211 mActiveModeWarden.scanAlwaysModeChanged(); 1212 mLooper.dispatchAll(); 1213 verify(mClientModeManager).setRole(ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE); 1214 assertInEnabledState(); 1215 verify(mClientModeManager, never()).stop(); 1216 } 1217 1218 /** 1219 * Verify that if scanning is enabled at startup, we enter scan mode 1220 */ 1221 @Test testEnterScanModeAtStartWhenSet()1222 public void testEnterScanModeAtStartWhenSet() throws Exception { 1223 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1224 1225 mActiveModeWarden = createActiveModeWarden(); 1226 mActiveModeWarden.start(); 1227 mLooper.dispatchAll(); 1228 1229 assertInEnabledState(); 1230 } 1231 1232 /** 1233 * Verify that if Wifi is enabled at startup, we enter client mode 1234 */ 1235 @Test testEnterClientModeAtStartWhenSet()1236 public void testEnterClientModeAtStartWhenSet() throws Exception { 1237 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1238 1239 mActiveModeWarden = createActiveModeWarden(); 1240 mActiveModeWarden.start(); 1241 mLooper.dispatchAll(); 1242 1243 verify(mWifiMetrics).noteWifiEnabledDuringBoot(true); 1244 1245 assertInEnabledState(); 1246 1247 verify(mWifiInjector) 1248 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1249 } 1250 1251 /** 1252 * Do not enter scan mode if location mode disabled. 1253 */ 1254 @Test testDoesNotEnterScanModeWhenLocationModeDisabled()1255 public void testDoesNotEnterScanModeWhenLocationModeDisabled() throws Exception { 1256 // Start a new WifiController with wifi disabled 1257 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 1258 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1259 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1260 1261 mActiveModeWarden = createActiveModeWarden(); 1262 mActiveModeWarden.start(); 1263 mLooper.dispatchAll(); 1264 1265 assertInDisabledState(); 1266 1267 // toggling scan always available is not sufficient for scan mode 1268 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1269 mActiveModeWarden.scanAlwaysModeChanged(); 1270 mLooper.dispatchAll(); 1271 1272 assertInDisabledState(); 1273 } 1274 1275 /** 1276 * Only enter scan mode if location mode enabled 1277 */ 1278 @Test testEnterScanModeWhenLocationModeEnabled()1279 public void testEnterScanModeWhenLocationModeEnabled() throws Exception { 1280 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1281 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1282 1283 reset(mContext); 1284 when(mContext.getResources()).thenReturn(mResources); 1285 mActiveModeWarden = createActiveModeWarden(); 1286 mActiveModeWarden.start(); 1287 mLooper.dispatchAll(); 1288 1289 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 1290 ArgumentCaptor.forClass(BroadcastReceiver.class); 1291 verify(mContext).registerReceiver( 1292 bcastRxCaptor.capture(), 1293 argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); 1294 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 1295 1296 assertInDisabledState(); 1297 1298 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 1299 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); 1300 broadcastReceiver.onReceive(mContext, intent); 1301 mLooper.dispatchAll(); 1302 1303 assertInEnabledState(); 1304 } 1305 1306 1307 /** 1308 * Disabling location mode when in scan mode will disable wifi 1309 */ 1310 @Test testExitScanModeWhenLocationModeDisabled()1311 public void testExitScanModeWhenLocationModeDisabled() throws Exception { 1312 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1313 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 1314 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 1315 1316 reset(mContext); 1317 when(mContext.getResources()).thenReturn(mResources); 1318 mActiveModeWarden = createActiveModeWarden(); 1319 mActiveModeWarden.start(); 1320 mLooper.dispatchAll(); 1321 mClientListener.onStarted(mClientModeManager); 1322 mLooper.dispatchAll(); 1323 1324 ArgumentCaptor<BroadcastReceiver> bcastRxCaptor = 1325 ArgumentCaptor.forClass(BroadcastReceiver.class); 1326 verify(mContext).registerReceiver( 1327 bcastRxCaptor.capture(), 1328 argThat(filter -> filter.hasAction(LocationManager.MODE_CHANGED_ACTION))); 1329 BroadcastReceiver broadcastReceiver = bcastRxCaptor.getValue(); 1330 1331 assertInEnabledState(); 1332 1333 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 1334 Intent intent = new Intent(LocationManager.MODE_CHANGED_ACTION); 1335 broadcastReceiver.onReceive(mContext, intent); 1336 mLooper.dispatchAll(); 1337 1338 mClientListener.onStopped(mClientModeManager); 1339 mLooper.dispatchAll(); 1340 1341 assertInDisabledState(); 1342 } 1343 1344 /** 1345 * When in Client mode, make sure ECM triggers wifi shutdown. 1346 */ 1347 @Test testEcmOnFromClientMode()1348 public void testEcmOnFromClientMode() throws Exception { 1349 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1350 enableWifi(); 1351 1352 // Test with WifiDisableInECBM turned on: 1353 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1354 1355 assertWifiShutDown(() -> { 1356 // test ecm changed 1357 emergencyCallbackModeChanged(true); 1358 mLooper.dispatchAll(); 1359 }); 1360 } 1361 1362 /** 1363 * ECM disabling messages, when in client mode (not expected) do not trigger state changes. 1364 */ 1365 @Test testEcmOffInClientMode()1366 public void testEcmOffInClientMode() throws Exception { 1367 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 1368 enableWifi(); 1369 1370 // Test with WifiDisableInECBM turned off 1371 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1372 1373 assertEnteredEcmMode(() -> { 1374 // test ecm changed 1375 emergencyCallbackModeChanged(true); 1376 mLooper.dispatchAll(); 1377 }); 1378 } 1379 1380 /** 1381 * When ECM activates and we are in client mode, disabling ECM should return us to client mode. 1382 */ 1383 @Test testEcmDisabledReturnsToClientMode()1384 public void testEcmDisabledReturnsToClientMode() throws Exception { 1385 enableWifi(); 1386 assertInEnabledState(); 1387 1388 // Test with WifiDisableInECBM turned on: 1389 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1390 1391 assertWifiShutDown(() -> { 1392 // test ecm changed 1393 emergencyCallbackModeChanged(true); 1394 mLooper.dispatchAll(); 1395 }); 1396 1397 // test ecm changed 1398 emergencyCallbackModeChanged(false); 1399 mLooper.dispatchAll(); 1400 1401 assertInEnabledState(); 1402 } 1403 1404 /** 1405 * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed 1406 * update. 1407 */ 1408 @Test testEcmOnFromScanMode()1409 public void testEcmOnFromScanMode() throws Exception { 1410 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1411 mActiveModeWarden.scanAlwaysModeChanged(); 1412 mLooper.dispatchAll(); 1413 1414 mClientListener.onStarted(mClientModeManager); 1415 mLooper.dispatchAll(); 1416 1417 assertInEnabledState(); 1418 1419 // Test with WifiDisableInECBM turned on: 1420 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1421 1422 assertWifiShutDown(() -> { 1423 // test ecm changed 1424 emergencyCallbackModeChanged(true); 1425 mLooper.dispatchAll(); 1426 }); 1427 } 1428 1429 /** 1430 * When Ecm mode is disabled, we should not shut down scan mode if we get an emergency mode 1431 * changed update, but we should turn off soft AP 1432 */ 1433 @Test testEcmOffInScanMode()1434 public void testEcmOffInScanMode() throws Exception { 1435 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1436 mActiveModeWarden.scanAlwaysModeChanged(); 1437 mLooper.dispatchAll(); 1438 1439 assertInEnabledState(); 1440 1441 // Test with WifiDisableInECBM turned off: 1442 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1443 1444 assertEnteredEcmMode(() -> { 1445 // test ecm changed 1446 emergencyCallbackModeChanged(true); 1447 mLooper.dispatchAll(); 1448 }); 1449 } 1450 1451 /** 1452 * When ECM is disabled, we should return to scan mode 1453 */ 1454 @Test testEcmDisabledReturnsToScanMode()1455 public void testEcmDisabledReturnsToScanMode() throws Exception { 1456 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1457 mActiveModeWarden.scanAlwaysModeChanged(); 1458 mLooper.dispatchAll(); 1459 1460 assertInEnabledState(); 1461 1462 // Test with WifiDisableInECBM turned on: 1463 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1464 1465 assertWifiShutDown(() -> { 1466 // test ecm changed 1467 emergencyCallbackModeChanged(true); 1468 mLooper.dispatchAll(); 1469 }); 1470 1471 // test ecm changed 1472 emergencyCallbackModeChanged(false); 1473 mLooper.dispatchAll(); 1474 1475 assertInEnabledState(); 1476 } 1477 1478 /** 1479 * When Ecm mode is enabled, we should shut down wifi when we get an emergency mode changed 1480 * update. 1481 */ 1482 @Test testEcmOnFromSoftApMode()1483 public void testEcmOnFromSoftApMode() throws Exception { 1484 enterSoftApActiveMode(); 1485 1486 // Test with WifiDisableInECBM turned on: 1487 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1488 1489 assertEnteredEcmMode(() -> { 1490 // test ecm changed 1491 emergencyCallbackModeChanged(true); 1492 mLooper.dispatchAll(); 1493 }); 1494 } 1495 1496 /** 1497 * When Ecm mode is disabled, we should shut down softap mode if we get an emergency mode 1498 * changed update 1499 */ 1500 @Test testEcmOffInSoftApMode()1501 public void testEcmOffInSoftApMode() throws Exception { 1502 enterSoftApActiveMode(); 1503 1504 // Test with WifiDisableInECBM turned off: 1505 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1506 1507 // test ecm changed 1508 emergencyCallbackModeChanged(true); 1509 mLooper.dispatchAll(); 1510 1511 verify(mSoftApManager).stop(); 1512 } 1513 1514 /** 1515 * When ECM is activated and we were in softap mode, we should just return to wifi off when ECM 1516 * ends 1517 */ 1518 @Test testEcmDisabledRemainsDisabledWhenSoftApHadBeenOn()1519 public void testEcmDisabledRemainsDisabledWhenSoftApHadBeenOn() throws Exception { 1520 assertInDisabledState(); 1521 1522 enterSoftApActiveMode(); 1523 1524 // verify Soft AP Manager started 1525 verify(mWifiInjector).makeSoftApManager( 1526 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1527 1528 // Test with WifiDisableInECBM turned on: 1529 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1530 1531 assertEnteredEcmMode(() -> { 1532 // test ecm changed 1533 emergencyCallbackModeChanged(true); 1534 mLooper.dispatchAll(); 1535 mSoftApListener.onStopped(mSoftApManager); 1536 mLooper.dispatchAll(); 1537 }); 1538 1539 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 1540 1541 // test ecm changed 1542 emergencyCallbackModeChanged(false); 1543 mLooper.dispatchAll(); 1544 1545 assertInDisabledState(); 1546 1547 // verify no additional calls to enable softap 1548 verify(mWifiInjector).makeSoftApManager( 1549 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 1550 } 1551 1552 /** 1553 * Wifi should remain off when already disabled and we enter ECM. 1554 */ 1555 @Test testEcmOnFromDisabledMode()1556 public void testEcmOnFromDisabledMode() throws Exception { 1557 assertInDisabledState(); 1558 verify(mWifiInjector, never()).makeSoftApManager( 1559 any(), any(), any(), any(), any(), anyBoolean()); 1560 verify(mWifiInjector, never()).makeClientModeManager( 1561 any(), any(), any(), anyBoolean()); 1562 1563 // Test with WifiDisableInECBM turned on: 1564 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1565 1566 assertEnteredEcmMode(() -> { 1567 // test ecm changed 1568 emergencyCallbackModeChanged(true); 1569 mLooper.dispatchAll(); 1570 }); 1571 } 1572 1573 1574 /** 1575 * Updates about call state change also trigger entry of ECM mode. 1576 */ 1577 @Test testEnterEcmOnEmergencyCallStateChange()1578 public void testEnterEcmOnEmergencyCallStateChange() throws Exception { 1579 assertInDisabledState(); 1580 1581 enableWifi(); 1582 assertInEnabledState(); 1583 1584 // Test with WifiDisableInECBM turned on: 1585 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1586 1587 assertEnteredEcmMode(() -> { 1588 // test call state changed 1589 emergencyCallStateChanged(true); 1590 mLooper.dispatchAll(); 1591 mClientListener.onStopped(mClientModeManager); 1592 mLooper.dispatchAll(); 1593 }); 1594 1595 emergencyCallStateChanged(false); 1596 mLooper.dispatchAll(); 1597 1598 assertInEnabledState(); 1599 } 1600 1601 /** 1602 * Verify when both ECM and call state changes arrive, we enter ECM mode 1603 */ 1604 @Test testEnterEcmWithBothSignals()1605 public void testEnterEcmWithBothSignals() throws Exception { 1606 assertInDisabledState(); 1607 1608 enableWifi(); 1609 assertInEnabledState(); 1610 1611 // Test with WifiDisableInECBM turned on: 1612 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1613 1614 assertWifiShutDown(() -> { 1615 emergencyCallStateChanged(true); 1616 mLooper.dispatchAll(); 1617 mClientListener.onStopped(mClientModeManager); 1618 mLooper.dispatchAll(); 1619 }); 1620 1621 assertWifiShutDown(() -> { 1622 emergencyCallbackModeChanged(true); 1623 mLooper.dispatchAll(); 1624 }, 0); // does not cause another shutdown 1625 1626 // client mode only started once so far 1627 verify(mWifiInjector).makeClientModeManager( 1628 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1629 1630 emergencyCallStateChanged(false); 1631 mLooper.dispatchAll(); 1632 1633 // stay in ecm, do not send an additional client mode trigger 1634 assertInEmergencyMode(); 1635 // assert that the underlying state is in disabled state 1636 assertInDisabledState(); 1637 1638 // client mode still only started once 1639 verify(mWifiInjector).makeClientModeManager( 1640 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1641 1642 emergencyCallbackModeChanged(false); 1643 mLooper.dispatchAll(); 1644 1645 // now we can re-enable wifi 1646 verify(mWifiInjector, times(2)).makeClientModeManager( 1647 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1648 assertInEnabledState(); 1649 } 1650 1651 /** 1652 * Verify when both ECM and call state changes arrive but out of order, we enter ECM mode 1653 */ 1654 @Test testEnterEcmWithBothSignalsOutOfOrder()1655 public void testEnterEcmWithBothSignalsOutOfOrder() throws Exception { 1656 assertInDisabledState(); 1657 1658 enableWifi(); 1659 1660 assertInEnabledState(); 1661 verify(mWifiInjector).makeClientModeManager( 1662 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1663 1664 // Test with WifiDisableInECBM turned on: 1665 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1666 1667 assertEnteredEcmMode(() -> { 1668 emergencyCallbackModeChanged(true); 1669 mLooper.dispatchAll(); 1670 mClientListener.onStopped(mClientModeManager); 1671 mLooper.dispatchAll(); 1672 }); 1673 assertInDisabledState(); 1674 1675 assertEnteredEcmMode(() -> { 1676 emergencyCallStateChanged(true); 1677 mLooper.dispatchAll(); 1678 }, 0); // does not enter ECM state again 1679 1680 emergencyCallStateChanged(false); 1681 mLooper.dispatchAll(); 1682 1683 // stay in ecm, do not send an additional client mode trigger 1684 assertInEmergencyMode(); 1685 // assert that the underlying state is in disabled state 1686 assertInDisabledState(); 1687 1688 // client mode still only started once 1689 verify(mWifiInjector).makeClientModeManager( 1690 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1691 1692 emergencyCallbackModeChanged(false); 1693 mLooper.dispatchAll(); 1694 1695 // now we can re-enable wifi 1696 verify(mWifiInjector, times(2)).makeClientModeManager( 1697 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1698 assertInEnabledState(); 1699 } 1700 1701 /** 1702 * Verify when both ECM and call state changes arrive but completely out of order, 1703 * we still enter and properly exit ECM mode 1704 */ 1705 @Test testEnterEcmWithBothSignalsOppositeOrder()1706 public void testEnterEcmWithBothSignalsOppositeOrder() throws Exception { 1707 assertInDisabledState(); 1708 1709 enableWifi(); 1710 1711 assertInEnabledState(); 1712 verify(mWifiInjector).makeClientModeManager( 1713 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1714 1715 // Test with WifiDisableInECBM turned on: 1716 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1717 1718 assertEnteredEcmMode(() -> { 1719 emergencyCallStateChanged(true); 1720 mLooper.dispatchAll(); 1721 mClientListener.onStopped(mClientModeManager); 1722 mLooper.dispatchAll(); 1723 }); 1724 assertInDisabledState(); 1725 1726 assertEnteredEcmMode(() -> { 1727 emergencyCallbackModeChanged(true); 1728 mLooper.dispatchAll(); 1729 }, 0); // still only 1 shutdown 1730 1731 emergencyCallbackModeChanged(false); 1732 mLooper.dispatchAll(); 1733 1734 // stay in ecm, do not send an additional client mode trigger 1735 assertInEmergencyMode(); 1736 // assert that the underlying state is in disabled state 1737 assertInDisabledState(); 1738 1739 // client mode still only started once 1740 verify(mWifiInjector).makeClientModeManager( 1741 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1742 1743 emergencyCallStateChanged(false); 1744 mLooper.dispatchAll(); 1745 1746 // now we can re-enable wifi 1747 verify(mWifiInjector, times(2)).makeClientModeManager( 1748 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1749 assertInEnabledState(); 1750 } 1751 1752 /** 1753 * When ECM is active, we might get addition signals of ECM mode, drop those additional signals, 1754 * we must exit when one of each signal is received. 1755 * 1756 * In any case, duplicate signals indicate a bug from Telephony. Each signal should be turned 1757 * off before it is turned on again. 1758 */ 1759 @Test testProperExitFromEcmModeWithMultipleMessages()1760 public void testProperExitFromEcmModeWithMultipleMessages() throws Exception { 1761 assertInDisabledState(); 1762 1763 enableWifi(); 1764 1765 verify(mWifiInjector).makeClientModeManager( 1766 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1767 assertInEnabledState(); 1768 1769 // Test with WifiDisableInECBM turned on: 1770 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1771 1772 assertEnteredEcmMode(() -> { 1773 emergencyCallbackModeChanged(true); 1774 emergencyCallStateChanged(true); 1775 emergencyCallStateChanged(true); 1776 emergencyCallbackModeChanged(true); 1777 emergencyCallbackModeChanged(true); 1778 mLooper.dispatchAll(); 1779 mClientListener.onStopped(mClientModeManager); 1780 mLooper.dispatchAll(); 1781 }); 1782 assertInDisabledState(); 1783 1784 assertEnteredEcmMode(() -> { 1785 emergencyCallbackModeChanged(false); 1786 mLooper.dispatchAll(); 1787 emergencyCallbackModeChanged(false); 1788 mLooper.dispatchAll(); 1789 emergencyCallbackModeChanged(false); 1790 mLooper.dispatchAll(); 1791 emergencyCallbackModeChanged(false); 1792 mLooper.dispatchAll(); 1793 }, 0); 1794 1795 // didn't enter client mode again 1796 verify(mWifiInjector).makeClientModeManager( 1797 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1798 assertInDisabledState(); 1799 1800 // now we will exit ECM 1801 emergencyCallStateChanged(false); 1802 mLooper.dispatchAll(); 1803 1804 // now we can re-enable wifi 1805 verify(mWifiInjector, times(2)).makeClientModeManager( 1806 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1807 assertInEnabledState(); 1808 } 1809 1810 /** 1811 * Toggling wifi on when in ECM does not exit ecm mode and enable wifi 1812 */ 1813 @Test testWifiDoesNotToggleOnWhenInEcm()1814 public void testWifiDoesNotToggleOnWhenInEcm() throws Exception { 1815 assertInDisabledState(); 1816 1817 // Test with WifiDisableInECBM turned on: 1818 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1819 // test ecm changed 1820 assertEnteredEcmMode(() -> { 1821 emergencyCallbackModeChanged(true); 1822 mLooper.dispatchAll(); 1823 }); 1824 1825 // now toggle wifi and verify we do not start wifi 1826 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1827 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1828 mLooper.dispatchAll(); 1829 1830 verify(mWifiInjector, never()).makeClientModeManager( 1831 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1832 assertInDisabledState(); 1833 assertInEmergencyMode(); 1834 1835 // now we will exit ECM 1836 emergencyCallbackModeChanged(false); 1837 mLooper.dispatchAll(); 1838 assertNotInEmergencyMode(); 1839 1840 // Wifi toggle on now takes effect 1841 verify(mWifiInjector).makeClientModeManager( 1842 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1843 assertInEnabledState(); 1844 } 1845 1846 /** 1847 * Toggling wifi off when in ECM does not disable wifi when getConfigWiFiDisableInECBM is 1848 * disabled. 1849 */ 1850 @Test testWifiDoesNotToggleOffWhenInEcmAndConfigDisabled()1851 public void testWifiDoesNotToggleOffWhenInEcmAndConfigDisabled() throws Exception { 1852 enableWifi(); 1853 assertInEnabledState(); 1854 verify(mWifiInjector).makeClientModeManager( 1855 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1856 1857 // Test with WifiDisableInECBM turned off 1858 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 1859 // test ecm changed 1860 assertEnteredEcmMode(() -> { 1861 emergencyCallbackModeChanged(true); 1862 mLooper.dispatchAll(); 1863 }); 1864 1865 // now toggle wifi and verify we do not start wifi 1866 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 1867 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 1868 mLooper.dispatchAll(); 1869 1870 // still only called once 1871 verify(mWifiInjector).makeClientModeManager( 1872 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1873 verify(mClientModeManager, never()).stop(); 1874 assertInEnabledState(); 1875 assertInEmergencyMode(); 1876 1877 // now we will exit ECM 1878 emergencyCallbackModeChanged(false); 1879 mLooper.dispatchAll(); 1880 assertNotInEmergencyMode(); 1881 1882 // Wifi toggle off now takes effect 1883 verify(mClientModeManager).stop(); 1884 mClientListener.onStopped(mClientModeManager); 1885 mLooper.dispatchAll(); 1886 assertInDisabledState(); 1887 } 1888 1889 @Test testAirplaneModeDoesNotToggleOnWhenInEcm()1890 public void testAirplaneModeDoesNotToggleOnWhenInEcm() throws Exception { 1891 // TODO(b/139829963): investigate the expected behavior is when toggling airplane mode in 1892 // ECM 1893 } 1894 1895 /** 1896 * Toggling scan mode when in ECM does not exit ecm mode and enable scan mode 1897 */ 1898 @Test testScanModeDoesNotToggleOnWhenInEcm()1899 public void testScanModeDoesNotToggleOnWhenInEcm() throws Exception { 1900 assertInDisabledState(); 1901 1902 // Test with WifiDisableInECBM turned on: 1903 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1904 assertEnteredEcmMode(() -> { 1905 // test ecm changed 1906 emergencyCallbackModeChanged(true); 1907 mLooper.dispatchAll(); 1908 }); 1909 1910 // now enable scanning and verify we do not start wifi 1911 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 1912 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 1913 mActiveModeWarden.scanAlwaysModeChanged(); 1914 mLooper.dispatchAll(); 1915 1916 verify(mWifiInjector, never()).makeClientModeManager( 1917 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 1918 assertInDisabledState(); 1919 } 1920 1921 1922 /** 1923 * Toggling softap mode when in ECM does not exit ecm mode and enable softap 1924 */ 1925 @Test testSoftApModeDoesNotToggleOnWhenInEcm()1926 public void testSoftApModeDoesNotToggleOnWhenInEcm() throws Exception { 1927 assertInDisabledState(); 1928 1929 // Test with WifiDisableInECBM turned on: 1930 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1931 assertEnteredEcmMode(() -> { 1932 // test ecm changed 1933 emergencyCallbackModeChanged(true); 1934 mLooper.dispatchAll(); 1935 }); 1936 1937 // try to start Soft AP 1938 mActiveModeWarden.startSoftAp( 1939 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 1940 mSoftApCapability), TEST_WORKSOURCE); 1941 mLooper.dispatchAll(); 1942 1943 verify(mWifiInjector, never()) 1944 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 1945 assertInDisabledState(); 1946 1947 // verify triggered Soft AP failure callback 1948 verify(mSoftApStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 1949 WifiManager.SAP_START_FAILURE_GENERAL); 1950 1951 // try to start LOHS 1952 mActiveModeWarden.startSoftAp( 1953 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_LOCAL_ONLY, null, 1954 mSoftApCapability), TEST_WORKSOURCE); 1955 mLooper.dispatchAll(); 1956 1957 verify(mWifiInjector, never()) 1958 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 1959 assertInDisabledState(); 1960 1961 // verify triggered LOHS failure callback 1962 verify(mLohsStateMachineCallback).onStateChanged(WifiManager.WIFI_AP_STATE_FAILED, 1963 WifiManager.SAP_START_FAILURE_GENERAL); 1964 } 1965 1966 /** 1967 * Toggling off softap mode when in ECM does not induce a mode change 1968 */ 1969 @Test testSoftApStoppedDoesNotSwitchModesWhenInEcm()1970 public void testSoftApStoppedDoesNotSwitchModesWhenInEcm() throws Exception { 1971 assertInDisabledState(); 1972 1973 // Test with WifiDisableInECBM turned on: 1974 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 1975 assertEnteredEcmMode(() -> { 1976 // test ecm changed 1977 emergencyCallbackModeChanged(true); 1978 mLooper.dispatchAll(); 1979 }); 1980 1981 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 1982 mLooper.dispatchAll(); 1983 1984 assertInDisabledState(); 1985 verifyNoMoreInteractions(mSoftApManager, mClientModeManager); 1986 } 1987 1988 /** 1989 * Toggling softap mode when in airplane mode needs to enable softap 1990 */ 1991 @Test testSoftApModeToggleWhenInAirplaneMode()1992 public void testSoftApModeToggleWhenInAirplaneMode() throws Exception { 1993 // Test with airplane mode turned on: 1994 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 1995 1996 // Turn on SoftAp. 1997 mActiveModeWarden.startSoftAp( 1998 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 1999 mSoftApCapability), TEST_WORKSOURCE); 2000 mLooper.dispatchAll(); 2001 verify(mWifiInjector) 2002 .makeSoftApManager(any(), any(), any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2003 2004 // Turn off SoftAp. 2005 mActiveModeWarden.stopSoftAp(WifiManager.IFACE_IP_MODE_UNSPECIFIED); 2006 mLooper.dispatchAll(); 2007 2008 verify(mSoftApManager).stop(); 2009 } 2010 2011 /** 2012 * Toggling off scan mode when in ECM does not induce a mode change 2013 */ 2014 @Test testScanModeStoppedSwitchModeToDisabledStateWhenInEcm()2015 public void testScanModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { 2016 enterScanOnlyModeActiveState(); 2017 assertInEnabledState(); 2018 2019 // Test with WifiDisableInECBM turned on: 2020 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2021 assertEnteredEcmMode(() -> { 2022 // test ecm changed 2023 emergencyCallbackModeChanged(true); 2024 mLooper.dispatchAll(); 2025 mClientListener.onStopped(mClientModeManager); 2026 mLooper.dispatchAll(); 2027 }); 2028 2029 // Spurious onStopped 2030 mClientListener.onStopped(mClientModeManager); 2031 mLooper.dispatchAll(); 2032 2033 assertInDisabledState(); 2034 } 2035 2036 /** 2037 * Toggling off client mode when in ECM does not induce a mode change 2038 */ 2039 @Test testClientModeStoppedSwitchModeToDisabledStateWhenInEcm()2040 public void testClientModeStoppedSwitchModeToDisabledStateWhenInEcm() throws Exception { 2041 enterClientModeActiveState(); 2042 assertInEnabledState(); 2043 2044 // Test with WifiDisableInECBM turned on: 2045 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2046 assertEnteredEcmMode(() -> { 2047 // test ecm changed 2048 emergencyCallbackModeChanged(true); 2049 mLooper.dispatchAll(); 2050 mClientListener.onStopped(mClientModeManager); 2051 mLooper.dispatchAll(); 2052 }); 2053 2054 // Spurious onStopped 2055 mClientListener.onStopped(mClientModeManager); 2056 mLooper.dispatchAll(); 2057 2058 assertInDisabledState(); 2059 } 2060 2061 /** 2062 * When AP mode is enabled and wifi was previously in AP mode, we should return to 2063 * EnabledState after the AP is disabled. 2064 * Enter EnabledState, activate AP mode, disable AP mode. 2065 * <p> 2066 * Expected: AP should successfully start and exit, then return to EnabledState. 2067 */ 2068 @Test testReturnToEnabledStateAfterAPModeShutdown()2069 public void testReturnToEnabledStateAfterAPModeShutdown() throws Exception { 2070 enableWifi(); 2071 assertInEnabledState(); 2072 verify(mWifiInjector).makeClientModeManager( 2073 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2074 2075 mActiveModeWarden.startSoftAp( 2076 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2077 mSoftApCapability), TEST_WORKSOURCE); 2078 // add an "unexpected" sta mode stop to simulate a single interface device 2079 mClientListener.onStopped(mClientModeManager); 2080 mLooper.dispatchAll(); 2081 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2082 2083 // Now stop the AP 2084 mSoftApListener.onStopped(mSoftApManager); 2085 mLooper.dispatchAll(); 2086 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2087 2088 // We should re-enable client mode 2089 verify(mWifiInjector, times(2)).makeClientModeManager( 2090 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2091 assertInEnabledState(); 2092 } 2093 2094 /** 2095 * When in STA mode and SoftAP is enabled and the device supports STA+AP (i.e. the STA wasn't 2096 * shut down when the AP started), both modes will be running concurrently. 2097 * 2098 * Then when the AP is disabled, we should remain in STA mode. 2099 * 2100 * Enter EnabledState, activate AP mode, toggle WiFi off. 2101 * <p> 2102 * Expected: AP should successfully start and exit, then return to EnabledState. 2103 */ 2104 @Test testReturnToEnabledStateAfterWifiEnabledShutdown()2105 public void testReturnToEnabledStateAfterWifiEnabledShutdown() throws Exception { 2106 enableWifi(); 2107 assertInEnabledState(); 2108 verify(mWifiInjector).makeClientModeManager( 2109 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2110 2111 mActiveModeWarden.startSoftAp( 2112 new SoftApModeConfiguration(WifiManager.IFACE_IP_MODE_TETHERED, null, 2113 mSoftApCapability), TEST_WORKSOURCE); 2114 mLooper.dispatchAll(); 2115 2116 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 2117 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2118 mSoftApListener.onStopped(mSoftApManager); 2119 mLooper.dispatchAll(); 2120 2121 // wasn't called again 2122 verify(mWifiInjector).makeClientModeManager( 2123 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2124 assertInEnabledState(); 2125 } 2126 2127 @Test testRestartWifiStackInEnabledStateTriggersBugReport()2128 public void testRestartWifiStackInEnabledStateTriggersBugReport() throws Exception { 2129 enableWifi(); 2130 2131 // note: using a reason that will typical not start a bug report on purpose to guarantee 2132 // that it is the flag and not the reason which controls it. 2133 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG, "some text", 2134 true); 2135 mLooper.dispatchAll(); 2136 verify(mWifiDiagnostics).takeBugReport(anyString(), anyString()); 2137 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2138 } 2139 2140 @Test testRestartWifiWatchdogDoesNotTriggerBugReport()2141 public void testRestartWifiWatchdogDoesNotTriggerBugReport() throws Exception { 2142 enableWifi(); 2143 // note: using a reason that will typical start a bug report on purpose to guarantee that 2144 // it is the flag and not the reason which controls it. 2145 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2146 "anything", false); 2147 mLooper.dispatchAll(); 2148 verify(mWifiDiagnostics, never()).takeBugReport(anyString(), anyString()); 2149 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2150 } 2151 2152 /** 2153 * When in sta mode, CMD_RECOVERY_DISABLE_WIFI messages should trigger wifi to disable. 2154 */ 2155 @Test testRecoveryDisabledTurnsWifiOff()2156 public void testRecoveryDisabledTurnsWifiOff() throws Exception { 2157 enableWifi(); 2158 assertInEnabledState(); 2159 mActiveModeWarden.recoveryDisableWifi(); 2160 mLooper.dispatchAll(); 2161 verify(mClientModeManager).stop(); 2162 mClientListener.onStopped(mClientModeManager); 2163 mLooper.dispatchAll(); 2164 assertInDisabledState(); 2165 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2166 } 2167 2168 /** 2169 * When wifi is disabled, CMD_RECOVERY_DISABLE_WIFI should not trigger a state change. 2170 */ 2171 @Test testRecoveryDisabledWhenWifiAlreadyOff()2172 public void testRecoveryDisabledWhenWifiAlreadyOff() throws Exception { 2173 assertInDisabledState(); 2174 assertWifiShutDown(() -> { 2175 mActiveModeWarden.recoveryDisableWifi(); 2176 mLooper.dispatchAll(); 2177 }); 2178 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS + 10); 2179 mLooper.dispatchAll(); 2180 2181 // Ensure we did not restart wifi. 2182 assertInDisabledState(); 2183 } 2184 2185 /** 2186 * The command to trigger a WiFi reset should not trigger any action by WifiController if we 2187 * are not in STA mode. 2188 * WiFi is not in connect mode, so any calls to reset the wifi stack due to connection failures 2189 * should be ignored. 2190 * Create and start WifiController in DisabledState, send command to restart WiFi 2191 * <p> 2192 * Expected: WiFiController should not call ActiveModeWarden.disableWifi() 2193 */ 2194 @Test testRestartWifiStackInDisabledState()2195 public void testRestartWifiStackInDisabledState() throws Exception { 2196 assertInDisabledState(); 2197 2198 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2199 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_WIFINATIVE_FAILURE], true); 2200 mLooper.dispatchAll(); 2201 2202 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS + 10); 2203 mLooper.dispatchAll(); 2204 2205 assertInDisabledState(); 2206 verifyNoMoreInteractions(mClientModeManager, mSoftApManager); 2207 } 2208 2209 /** 2210 * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through 2211 * the ActiveModeWarden.shutdownWifi() call when in STA mode. 2212 * When WiFi is in scan mode, calls to reset the wifi stack due to native failure 2213 * should trigger a supplicant stop, and subsequently, a driver reload. 2214 * Create and start WifiController in EnabledState, send command to restart WiFi 2215 * <p> 2216 * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and 2217 * ActiveModeWarden should enter SCAN_ONLY mode and the wifi driver should be started. 2218 */ 2219 @Test testRestartWifiStackInStaScanEnabledState()2220 public void testRestartWifiStackInStaScanEnabledState() throws Exception { 2221 assertInDisabledState(); 2222 2223 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 2224 mActiveModeWarden.scanAlwaysModeChanged(); 2225 mLooper.dispatchAll(); 2226 2227 assertInEnabledState(); 2228 verify(mWifiInjector).makeClientModeManager( 2229 any(), eq(new WorkSource(Process.WIFI_UID)), eq(ROLE_CLIENT_SCAN_ONLY), 2230 anyBoolean()); 2231 2232 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2233 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_WIFINATIVE_FAILURE], true); 2234 mLooper.dispatchAll(); 2235 2236 verify(mClientModeManager).stop(); 2237 mClientListener.onStopped(mClientModeManager); 2238 mLooper.dispatchAll(); 2239 assertInDisabledState(); 2240 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2241 2242 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2243 mLooper.dispatchAll(); 2244 2245 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2246 assertInEnabledState(); 2247 2248 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2249 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2250 } 2251 2252 /** 2253 * The command to trigger a WiFi reset should trigger a wifi reset in ClientModeImpl through 2254 * the ActiveModeWarden.shutdownWifi() call when in STA mode. 2255 * WiFi is in connect mode, calls to reset the wifi stack due to connection failures 2256 * should trigger a supplicant stop, and subsequently, a driver reload. 2257 * Create and start WifiController in EnabledState, send command to restart WiFi 2258 * <p> 2259 * Expected: WiFiController should call ActiveModeWarden.shutdownWifi() and 2260 * ActiveModeWarden should enter CONNECT_MODE and the wifi driver should be started. 2261 */ 2262 @Test testRestartWifiStackInStaConnectEnabledState()2263 public void testRestartWifiStackInStaConnectEnabledState() throws Exception { 2264 enableWifi(); 2265 assertInEnabledState(); 2266 verify(mWifiInjector).makeClientModeManager( 2267 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2268 2269 assertWifiShutDown(() -> { 2270 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2271 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_WIFINATIVE_FAILURE], true); 2272 mLooper.dispatchAll(); 2273 // Complete the stop 2274 mClientListener.onStopped(mClientModeManager); 2275 mLooper.dispatchAll(); 2276 }); 2277 2278 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2279 2280 // still only started once 2281 verify(mWifiInjector).makeClientModeManager( 2282 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2283 2284 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2285 mLooper.dispatchAll(); 2286 2287 // started again 2288 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2289 assertInEnabledState(); 2290 2291 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2292 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2293 } 2294 2295 /** 2296 * The command to trigger a WiFi reset should not trigger a reset when in ECM mode. 2297 * Enable wifi and enter ECM state, send command to restart wifi. 2298 * <p> 2299 * Expected: The command to trigger a wifi reset should be ignored and we should remain in ECM 2300 * mode. 2301 */ 2302 @Test testRestartWifiStackDoesNotExitECMMode()2303 public void testRestartWifiStackDoesNotExitECMMode() throws Exception { 2304 enableWifi(); 2305 assertInEnabledState(); 2306 verify(mWifiInjector).makeClientModeManager( 2307 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), eq(false)); 2308 2309 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2310 assertEnteredEcmMode(() -> { 2311 emergencyCallStateChanged(true); 2312 mLooper.dispatchAll(); 2313 mClientListener.onStopped(mClientModeManager); 2314 mLooper.dispatchAll(); 2315 }); 2316 assertInEmergencyMode(); 2317 assertInDisabledState(); 2318 verify(mClientModeManager).stop(); 2319 verify(mClientModeManager, atLeastOnce()).getRole(); 2320 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 2321 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2322 2323 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_LAST_RESORT_WATCHDOG, 2324 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_LAST_RESORT_WATCHDOG], false); 2325 mLooper.dispatchAll(); 2326 2327 // wasn't called again 2328 verify(mWifiInjector).makeClientModeManager( 2329 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2330 assertInEmergencyMode(); 2331 assertInDisabledState(); 2332 2333 verify(mClientModeManager, atLeastOnce()).getInterfaceName(); 2334 verifyNoMoreInteractions(mClientModeManager, mSoftApManager); 2335 } 2336 2337 /** 2338 * The command to trigger a WiFi reset should trigger a wifi reset in SoftApManager through 2339 * the ActiveModeWarden.shutdownWifi() call when in SAP enabled mode. 2340 */ 2341 @Test testRestartWifiStackInTetheredSoftApEnabledState()2342 public void testRestartWifiStackInTetheredSoftApEnabledState() throws Exception { 2343 enterSoftApActiveMode(); 2344 verify(mWifiInjector).makeSoftApManager( 2345 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2346 2347 assertWifiShutDown(() -> { 2348 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2349 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_WIFINATIVE_FAILURE], true); 2350 mLooper.dispatchAll(); 2351 // Complete the stop 2352 mSoftApListener.onStopped(mSoftApManager); 2353 mLooper.dispatchAll(); 2354 }); 2355 2356 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2357 2358 // still only started once 2359 verify(mWifiInjector).makeSoftApManager( 2360 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2361 2362 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2363 mLooper.dispatchAll(); 2364 2365 // started again 2366 verify(mWifiInjector, times(2)).makeSoftApManager( 2367 any(), any(), any(), any(), any(), anyBoolean()); 2368 assertInEnabledState(); 2369 2370 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2371 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2372 } 2373 2374 /** 2375 * The command to trigger a WiFi reset should trigger a wifi reset in SoftApManager & 2376 * ClientModeManager through the ActiveModeWarden.shutdownWifi() call when in STA + SAP 2377 * enabled mode. 2378 */ 2379 @Test testRestartWifiStackInTetheredSoftApAndStaConnectEnabledState()2380 public void testRestartWifiStackInTetheredSoftApAndStaConnectEnabledState() throws Exception { 2381 enableWifi(); 2382 enterSoftApActiveMode(); 2383 verify(mWifiInjector).makeClientModeManager( 2384 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2385 verify(mWifiInjector).makeSoftApManager( 2386 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2387 2388 assertWifiShutDown(() -> { 2389 mActiveModeWarden.recoveryRestartWifi(SelfRecovery.REASON_WIFINATIVE_FAILURE, 2390 SelfRecovery.REASON_STRINGS[SelfRecovery.REASON_WIFINATIVE_FAILURE], true); 2391 mLooper.dispatchAll(); 2392 // Complete the stop 2393 mClientListener.onStopped(mClientModeManager); 2394 mSoftApListener.onStopped(mSoftApManager); 2395 mLooper.dispatchAll(); 2396 }); 2397 2398 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 2399 verify(mModeChangeCallback).onActiveModeManagerRemoved(mSoftApManager); 2400 2401 // still only started once 2402 verify(mWifiInjector).makeClientModeManager( 2403 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2404 verify(mWifiInjector).makeSoftApManager( 2405 any(), any(), any(), eq(TEST_WORKSOURCE), eq(ROLE_SOFTAP_TETHERED), anyBoolean()); 2406 2407 mLooper.moveTimeForward(TEST_WIFI_RECOVERY_DELAY_MS); 2408 mLooper.dispatchAll(); 2409 2410 // started again 2411 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2412 verify(mWifiInjector, times(2)).makeSoftApManager( 2413 any(), any(), any(), any(), any(), anyBoolean()); 2414 assertInEnabledState(); 2415 2416 verify(mSubsystemRestartCallback).onSubsystemRestarting(); 2417 verify(mSubsystemRestartCallback).onSubsystemRestarted(); 2418 } 2419 2420 /** 2421 * Tests that when Wifi is already disabled and another Wifi toggle command arrives, 2422 * don't enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is false. 2423 * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns false if either the wifi 2424 * scanning is disabled and airplane mode is on. 2425 */ 2426 @Test staDisabled_toggleWifiOff_scanNotAvailable_dontGoToScanMode()2427 public void staDisabled_toggleWifiOff_scanNotAvailable_dontGoToScanMode() { 2428 assertInDisabledState(); 2429 2430 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 2431 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 2432 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 2433 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 2434 2435 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2436 mLooper.dispatchAll(); 2437 2438 assertInDisabledState(); 2439 verify(mWifiInjector, never()).makeClientModeManager( 2440 any(), eq(TEST_WORKSOURCE), any(), anyBoolean()); 2441 } 2442 2443 /** 2444 * Tests that when Wifi is already disabled and another Wifi toggle command arrives, 2445 * enter scan mode if {@link WifiSettingsStore#isScanAlwaysAvailable()} is true. 2446 * Note: {@link WifiSettingsStore#isScanAlwaysAvailable()} returns true if both the wifi 2447 * scanning is enabled and airplane mode is off. 2448 */ 2449 @Test staDisabled_toggleWifiOff_scanAvailable_goToScanMode()2450 public void staDisabled_toggleWifiOff_scanAvailable_goToScanMode() { 2451 assertInDisabledState(); 2452 2453 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 2454 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(true); 2455 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(true); 2456 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 2457 2458 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 2459 mLooper.dispatchAll(); 2460 2461 assertInEnabledState(); 2462 verify(mWifiInjector).makeClientModeManager( 2463 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 2464 } 2465 2466 /** 2467 * Tests that if the carrier config to disable Wifi is enabled during ECM, Wifi is shut down 2468 * when entering ECM and turned back on when exiting ECM. 2469 */ 2470 @Test ecmDisablesWifi_exitEcm_restartWifi()2471 public void ecmDisablesWifi_exitEcm_restartWifi() throws Exception { 2472 enterClientModeActiveState(); 2473 2474 verify(mWifiInjector).makeClientModeManager( 2475 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2476 2477 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 2478 assertEnteredEcmMode(() -> { 2479 emergencyCallbackModeChanged(true); 2480 mLooper.dispatchAll(); 2481 }); 2482 assertInEnabledState(); 2483 verify(mClientModeManager).stop(); 2484 2485 mClientListener.onStopped(mClientModeManager); 2486 mLooper.dispatchAll(); 2487 assertInDisabledState(); 2488 2489 emergencyCallbackModeChanged(false); 2490 mLooper.dispatchAll(); 2491 2492 assertNotInEmergencyMode(); 2493 // client mode restarted 2494 verify(mWifiInjector, times(2)).makeClientModeManager(any(), any(), any(), anyBoolean()); 2495 assertInEnabledState(); 2496 } 2497 2498 /** 2499 * Tests that if the carrier config to disable Wifi is not enabled during ECM, Wifi remains on 2500 * during ECM, and nothing happens after exiting ECM. 2501 */ 2502 @Test ecmDoesNotDisableWifi_exitEcm_noOp()2503 public void ecmDoesNotDisableWifi_exitEcm_noOp() throws Exception { 2504 enterClientModeActiveState(); 2505 2506 verify(mWifiInjector).makeClientModeManager( 2507 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2508 2509 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 2510 assertEnteredEcmMode(() -> { 2511 emergencyCallbackModeChanged(true); 2512 mLooper.dispatchAll(); 2513 }); 2514 assertInEnabledState(); 2515 verify(mClientModeManager, never()).stop(); 2516 2517 emergencyCallbackModeChanged(false); 2518 mLooper.dispatchAll(); 2519 2520 assertNotInEmergencyMode(); 2521 // client mode manager not started again 2522 verify(mWifiInjector).makeClientModeManager( 2523 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 2524 assertInEnabledState(); 2525 } 2526 2527 @Test testUpdateCapabilityInSoftApActiveMode()2528 public void testUpdateCapabilityInSoftApActiveMode() throws Exception { 2529 SoftApCapability testCapability = new SoftApCapability(0); 2530 enterSoftApActiveMode(); 2531 mActiveModeWarden.updateSoftApCapability(testCapability); 2532 mLooper.dispatchAll(); 2533 verify(mSoftApManager).updateCapability(testCapability); 2534 } 2535 2536 @Test testUpdateConfigInSoftApActiveMode()2537 public void testUpdateConfigInSoftApActiveMode() throws Exception { 2538 SoftApConfiguration testConfig = new SoftApConfiguration.Builder() 2539 .setSsid("Test123").build(); 2540 enterSoftApActiveMode(); 2541 mActiveModeWarden.updateSoftApConfiguration(testConfig); 2542 mLooper.dispatchAll(); 2543 verify(mSoftApManager).updateConfiguration(testConfig); 2544 } 2545 2546 @Test testUpdateCapabilityInNonSoftApActiveMode()2547 public void testUpdateCapabilityInNonSoftApActiveMode() throws Exception { 2548 SoftApCapability testCapability = new SoftApCapability(0); 2549 enterClientModeActiveState(); 2550 mActiveModeWarden.updateSoftApCapability(testCapability); 2551 mLooper.dispatchAll(); 2552 verify(mSoftApManager, never()).updateCapability(any()); 2553 } 2554 2555 @Test testUpdateConfigInNonSoftApActiveMode()2556 public void testUpdateConfigInNonSoftApActiveMode() throws Exception { 2557 SoftApConfiguration testConfig = new SoftApConfiguration.Builder() 2558 .setSsid("Test123").build(); 2559 enterClientModeActiveState(); 2560 mActiveModeWarden.updateSoftApConfiguration(testConfig); 2561 mLooper.dispatchAll(); 2562 verify(mSoftApManager, never()).updateConfiguration(any()); 2563 } 2564 2565 @Test isStaApConcurrencySupported()2566 public void isStaApConcurrencySupported() throws Exception { 2567 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(false); 2568 assertFalse(mActiveModeWarden.isStaApConcurrencySupported()); 2569 2570 when(mWifiNative.isStaApConcurrencySupported()).thenReturn(true); 2571 assertTrue(mActiveModeWarden.isStaApConcurrencySupported()); 2572 } 2573 2574 @Test isStaStaConcurrencySupported()2575 public void isStaStaConcurrencySupported() throws Exception { 2576 // STA + STA not supported. 2577 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(false); 2578 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 2579 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 2580 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 2581 2582 // STA + STA supported, but no use-cases enabled. 2583 when(mWifiNative.isStaStaConcurrencySupported()).thenReturn(true); 2584 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 2585 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 2586 assertFalse(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 2587 2588 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2589 .thenReturn(true); 2590 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForLocalOnlyConnections()); 2591 2592 when(mResources.getBoolean( 2593 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 2594 .thenReturn(true); 2595 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForMbb()); 2596 2597 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 2598 .thenReturn(true); 2599 assertTrue(mActiveModeWarden.isStaStaConcurrencySupportedForRestrictedConnections()); 2600 } 2601 requestAdditionalClientModeManager( ClientConnectivityRole additionaClientModeManagerRole, ConcreteClientModeManager additionalClientModeManager, ExternalClientModeManagerRequestListener externalRequestListener, String ssid, String bssid)2602 private Listener<ConcreteClientModeManager> requestAdditionalClientModeManager( 2603 ClientConnectivityRole additionaClientModeManagerRole, 2604 ConcreteClientModeManager additionalClientModeManager, 2605 ExternalClientModeManagerRequestListener externalRequestListener, 2606 String ssid, String bssid) 2607 throws Exception { 2608 enterClientModeActiveState(); 2609 2610 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 2611 new Mutable<>(); 2612 2613 // Connected to ssid1/bssid1 2614 WifiConfiguration config1 = new WifiConfiguration(); 2615 config1.SSID = TEST_SSID_1; 2616 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 2617 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 2618 2619 doAnswer((invocation) -> { 2620 Object[] args = invocation.getArguments(); 2621 additionalClientListener.value = 2622 (Listener<ConcreteClientModeManager>) args[0]; 2623 return additionalClientModeManager; 2624 }).when(mWifiInjector).makeClientModeManager( 2625 any(Listener.class), any(), any(), anyBoolean()); 2626 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 2627 when(additionalClientModeManager.getRole()).thenReturn(additionaClientModeManagerRole); 2628 2629 // request for ssid2/bssid2 2630 if (additionaClientModeManagerRole == ROLE_CLIENT_LOCAL_ONLY) { 2631 mActiveModeWarden.requestLocalOnlyClientModeManager( 2632 externalRequestListener, TEST_WORKSOURCE, ssid, bssid); 2633 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2634 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 2635 externalRequestListener, TEST_WORKSOURCE, ssid, bssid); 2636 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2637 mActiveModeWarden.requestSecondaryTransientClientModeManager( 2638 externalRequestListener, TEST_WORKSOURCE, ssid, bssid); 2639 } 2640 mLooper.dispatchAll(); 2641 verify(mWifiInjector) 2642 .makeClientModeManager(any(), eq(TEST_WORKSOURCE), 2643 eq(additionaClientModeManagerRole), anyBoolean()); 2644 additionalClientListener.value.onStarted(additionalClientModeManager); 2645 mLooper.dispatchAll(); 2646 // capture last use case set 2647 ArgumentCaptor<Integer> useCaseCaptor = ArgumentCaptor.forClass(Integer.class); 2648 verify(mWifiNative, atLeastOnce()).setMultiStaUseCase(useCaseCaptor.capture()); 2649 int lastUseCaseSet = useCaseCaptor.getValue().intValue(); 2650 // Ensure the hardware is correctly configured for STA + STA 2651 if (additionaClientModeManagerRole == ROLE_CLIENT_LOCAL_ONLY 2652 || additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2653 assertEquals(WifiNative.DUAL_STA_NON_TRANSIENT_UNBIASED, lastUseCaseSet); 2654 } else if (additionaClientModeManagerRole == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2655 assertEquals(WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY, lastUseCaseSet); 2656 } 2657 2658 // verify last set of primary connection is for WIFI_IFACE_NAME 2659 ArgumentCaptor<String> ifaceNameCaptor = ArgumentCaptor.forClass(String.class); 2660 verify(mWifiNative, atLeastOnce()).setMultiStaPrimaryConnection(ifaceNameCaptor.capture()); 2661 assertEquals(WIFI_IFACE_NAME, ifaceNameCaptor.getValue()); 2662 2663 // Returns the new local only client mode manager. 2664 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 2665 ArgumentCaptor.forClass(ClientModeManager.class); 2666 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 2667 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 2668 // the additional CMM never became primary 2669 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 2670 2671 return additionalClientListener.value; 2672 } 2673 requestRemoveAdditionalClientModeManager( ClientConnectivityRole role)2674 private void requestRemoveAdditionalClientModeManager( 2675 ClientConnectivityRole role) throws Exception { 2676 ConcreteClientModeManager additionalClientModeManager = 2677 mock(ConcreteClientModeManager.class); 2678 ExternalClientModeManagerRequestListener externalRequestListener = mock( 2679 ExternalClientModeManagerRequestListener.class); 2680 Listener<ConcreteClientModeManager> additionalClientListener = 2681 requestAdditionalClientModeManager(role, additionalClientModeManager, 2682 externalRequestListener, TEST_SSID_2, TEST_BSSID_2); 2683 2684 mActiveModeWarden.removeClientModeManager(additionalClientModeManager); 2685 mLooper.dispatchAll(); 2686 verify(additionalClientModeManager).stop(); 2687 additionalClientListener.onStopped(additionalClientModeManager); 2688 mLooper.dispatchAll(); 2689 verify(mModeChangeCallback).onActiveModeManagerRemoved(additionalClientModeManager); 2690 // the additional CMM still never became primary 2691 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 2692 } 2693 requestRemoveAdditionalClientModeManagerWhenNotAllowed( ClientConnectivityRole role)2694 private void requestRemoveAdditionalClientModeManagerWhenNotAllowed( 2695 ClientConnectivityRole role) throws Exception { 2696 enterClientModeActiveState(); 2697 2698 // Connected to ssid1/bssid1 2699 WifiConfiguration config1 = new WifiConfiguration(); 2700 config1.SSID = TEST_SSID_1; 2701 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 2702 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 2703 2704 ConcreteClientModeManager additionalClientModeManager = 2705 mock(ConcreteClientModeManager.class); 2706 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 2707 new Mutable<>(); 2708 doAnswer((invocation) -> { 2709 Object[] args = invocation.getArguments(); 2710 additionalClientListener.value = 2711 (Listener<ConcreteClientModeManager>) args[0]; 2712 return additionalClientModeManager; 2713 }).when(mWifiInjector).makeClientModeManager( 2714 any(Listener.class), any(), any(), anyBoolean()); 2715 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 2716 when(additionalClientModeManager.getRole()).thenReturn(role); 2717 2718 ExternalClientModeManagerRequestListener externalRequestListener = mock( 2719 ExternalClientModeManagerRequestListener.class); 2720 // request for ssid2/bssid2 2721 if (role == ROLE_CLIENT_LOCAL_ONLY) { 2722 mActiveModeWarden.requestLocalOnlyClientModeManager( 2723 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 2724 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2725 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 2726 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 2727 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2728 mActiveModeWarden.requestSecondaryTransientClientModeManager( 2729 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 2730 } 2731 mLooper.dispatchAll(); 2732 verifyNoMoreInteractions(additionalClientModeManager); 2733 // Returns the existing primary client mode manager. 2734 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 2735 ArgumentCaptor.forClass(ClientModeManager.class); 2736 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 2737 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 2738 2739 mActiveModeWarden.removeClientModeManager(requestedClientModeManager.getValue()); 2740 mLooper.dispatchAll(); 2741 verifyNoMoreInteractions(additionalClientModeManager); 2742 } 2743 requestAdditionalClientModeManagerWhenWifiIsOff( ClientConnectivityRole role)2744 private void requestAdditionalClientModeManagerWhenWifiIsOff( 2745 ClientConnectivityRole role) throws Exception { 2746 ExternalClientModeManagerRequestListener externalRequestListener = mock( 2747 ExternalClientModeManagerRequestListener.class); 2748 if (role == ROLE_CLIENT_LOCAL_ONLY) { 2749 mActiveModeWarden.requestLocalOnlyClientModeManager( 2750 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2751 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2752 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 2753 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2754 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2755 mActiveModeWarden.requestSecondaryTransientClientModeManager( 2756 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2757 } 2758 mLooper.dispatchAll(); 2759 2760 verify(externalRequestListener).onAnswer(null); 2761 } 2762 requestAdditionalClientModeManagerWhenAlreadyPresent( ClientConnectivityRole role)2763 public void requestAdditionalClientModeManagerWhenAlreadyPresent( 2764 ClientConnectivityRole role) throws Exception { 2765 ConcreteClientModeManager additionalClientModeManager = 2766 mock(ConcreteClientModeManager.class); 2767 ExternalClientModeManagerRequestListener externalRequestListener = mock( 2768 ExternalClientModeManagerRequestListener.class); 2769 requestAdditionalClientModeManager(role, additionalClientModeManager, 2770 externalRequestListener, TEST_SSID_2, TEST_BSSID_2); 2771 2772 // set additional CMM connected to ssid2/bssid2 2773 WifiConfiguration config2 = new WifiConfiguration(); 2774 config2.SSID = TEST_SSID_2; 2775 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 2776 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 2777 2778 // request for ssid3/bssid3 2779 // request for one more CMM (returns the existing one). 2780 if (role == ROLE_CLIENT_LOCAL_ONLY) { 2781 mActiveModeWarden.requestLocalOnlyClientModeManager( 2782 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3); 2783 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2784 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 2785 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3); 2786 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2787 mActiveModeWarden.requestSecondaryTransientClientModeManager( 2788 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_3, TEST_BSSID_3); 2789 } 2790 mLooper.dispatchAll(); 2791 2792 // Don't make another client mode manager. 2793 verify(mWifiInjector, times(1)) 2794 .makeClientModeManager(any(), any(), eq(role), anyBoolean()); 2795 // Returns the existing client mode manager. 2796 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 2797 ArgumentCaptor.forClass(ClientModeManager.class); 2798 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 2799 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 2800 } 2801 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( ClientConnectivityRole role)2802 private void requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 2803 ClientConnectivityRole role) throws Exception { 2804 enterClientModeActiveState(); 2805 2806 // Connected to ssid1/bssid1 2807 WifiConfiguration config1 = new WifiConfiguration(); 2808 config1.SSID = TEST_SSID_1; 2809 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 2810 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 2811 2812 ConcreteClientModeManager additionalClientModeManager = 2813 mock(ConcreteClientModeManager.class); 2814 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 2815 new Mutable<>(); 2816 doAnswer((invocation) -> { 2817 Object[] args = invocation.getArguments(); 2818 additionalClientListener.value = 2819 (Listener<ConcreteClientModeManager>) args[0]; 2820 return additionalClientModeManager; 2821 }).when(mWifiInjector).makeClientModeManager( 2822 any(Listener.class), any(), any(), anyBoolean()); 2823 when(additionalClientModeManager.getInterfaceName()).thenReturn(WIFI_IFACE_NAME_1); 2824 when(additionalClientModeManager.getRole()).thenReturn(role); 2825 2826 ExternalClientModeManagerRequestListener externalRequestListener = mock( 2827 ExternalClientModeManagerRequestListener.class); 2828 // request for same ssid1/bssid1 2829 if (role == ROLE_CLIENT_LOCAL_ONLY) { 2830 mActiveModeWarden.requestLocalOnlyClientModeManager( 2831 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2832 } else if (role == ROLE_CLIENT_SECONDARY_LONG_LIVED) { 2833 mActiveModeWarden.requestSecondaryLongLivedClientModeManager( 2834 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2835 } else if (role == ROLE_CLIENT_SECONDARY_TRANSIENT) { 2836 mActiveModeWarden.requestSecondaryTransientClientModeManager( 2837 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_1, TEST_BSSID_1); 2838 } 2839 mLooper.dispatchAll(); 2840 verifyNoMoreInteractions(additionalClientModeManager); 2841 // Returns the existing primary client mode manager. 2842 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 2843 ArgumentCaptor.forClass(ClientModeManager.class); 2844 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 2845 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 2846 } 2847 2848 @Test requestRemoveLocalOnlyClientModeManager()2849 public void requestRemoveLocalOnlyClientModeManager() throws Exception { 2850 // Ensure that we can create more client ifaces. 2851 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2852 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2853 .thenReturn(true); 2854 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2855 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2856 2857 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_LOCAL_ONLY); 2858 } 2859 2860 @Test requestRemoveLocalOnlyClientModeManagerWhenStaStaNotSupported()2861 public void requestRemoveLocalOnlyClientModeManagerWhenStaStaNotSupported() throws Exception { 2862 // Ensure that we cannot create more client ifaces. 2863 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 2864 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2865 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2866 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY); 2867 } 2868 2869 @Test requestRemoveLocalOnlyClientModeManagerWhenFeatureDisabled()2870 public void requestRemoveLocalOnlyClientModeManagerWhenFeatureDisabled() throws Exception { 2871 // Ensure that we can create more client ifaces. 2872 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2873 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2874 .thenReturn(false); 2875 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2876 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2877 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY); 2878 } 2879 2880 @Test requestLocalOnlyClientModeManagerWhenWifiIsOff()2881 public void requestLocalOnlyClientModeManagerWhenWifiIsOff() throws Exception { 2882 // Ensure that we can create more client ifaces. 2883 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2884 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2885 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2886 2887 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_LOCAL_ONLY); 2888 } 2889 2890 @Test requestLocalOnlyClientModeManagerWhenAlreadyPresent()2891 public void requestLocalOnlyClientModeManagerWhenAlreadyPresent() throws Exception { 2892 // Ensure that we can create more client ifaces. 2893 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2894 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2895 .thenReturn(true); 2896 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2897 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2898 2899 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_LOCAL_ONLY); 2900 } 2901 2902 @Test requestLocalOnlyClientModeManagerWhenConnectingToPrimaryBssid()2903 public void requestLocalOnlyClientModeManagerWhenConnectingToPrimaryBssid() throws Exception { 2904 // Ensure that we can create more client ifaces. 2905 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2906 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2907 .thenReturn(true); 2908 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2909 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2910 2911 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid(ROLE_CLIENT_LOCAL_ONLY); 2912 } 2913 2914 @Test requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkLessThanS()2915 public void requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkLessThanS() 2916 throws Exception { 2917 // Ensure that we can create more client ifaces. 2918 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2919 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2920 .thenReturn(true); 2921 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 2922 when(mWifiPermissionsUtil.isTargetSdkLessThan( 2923 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 2924 .thenReturn(true); 2925 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2926 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2927 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_LOCAL_ONLY); 2928 } 2929 2930 @Test requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkEqualToS()2931 public void requestRemoveLocalOnlyClientModeManagerWhenNotSystemAppAndTargetSdkEqualToS() 2932 throws Exception { 2933 // Ensure that we can create more client ifaces. 2934 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2935 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 2936 .thenReturn(true); 2937 when(mWifiPermissionsUtil.isSystem(TEST_PACKAGE, TEST_UID)).thenReturn(false); 2938 when(mWifiPermissionsUtil.isTargetSdkLessThan( 2939 TEST_PACKAGE, Build.VERSION_CODES.S, TEST_UID)) 2940 .thenReturn(false); 2941 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2942 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 2943 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_LOCAL_ONLY); 2944 } 2945 2946 @Test requestRemoveSecondaryLongLivedClientModeManager()2947 public void requestRemoveSecondaryLongLivedClientModeManager() throws Exception { 2948 // Ensure that we can create more client ifaces. 2949 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2950 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 2951 .thenReturn(true); 2952 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2953 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 2954 2955 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_LONG_LIVED); 2956 } 2957 2958 @Test requestRemoveSecondaryLongLivedClientModeManagerWhenStaStaNotSupported()2959 public void requestRemoveSecondaryLongLivedClientModeManagerWhenStaStaNotSupported() 2960 throws Exception { 2961 // Ensure that we cannot create more client ifaces. 2962 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 2963 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2964 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 2965 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_LONG_LIVED); 2966 } 2967 2968 @Test requestRemoveSecondaryLongLivedClientModeManagerWhenFeatureDisabled()2969 public void requestRemoveSecondaryLongLivedClientModeManagerWhenFeatureDisabled() 2970 throws Exception { 2971 // Ensure that we can create more client ifaces. 2972 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2973 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 2974 .thenReturn(false); 2975 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2976 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 2977 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_LONG_LIVED); 2978 } 2979 2980 @Test requestSecondaryLongLivedClientModeManagerWhenWifiIsOff()2981 public void requestSecondaryLongLivedClientModeManagerWhenWifiIsOff() throws Exception { 2982 // Ensure that we can create more client ifaces. 2983 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2984 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 2985 .thenReturn(true); 2986 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2987 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 2988 2989 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_SECONDARY_LONG_LIVED); 2990 } 2991 2992 @Test requestSecondaryLongLivedClientModeManagerWhenAlreadyPresent()2993 public void requestSecondaryLongLivedClientModeManagerWhenAlreadyPresent() throws Exception { 2994 // Ensure that we can create more client ifaces. 2995 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 2996 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 2997 .thenReturn(true); 2998 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 2999 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 3000 3001 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_SECONDARY_LONG_LIVED); 3002 } 3003 3004 @Test requestSecondaryLongLivedClientModeManagerWhenConnectingToPrimaryBssid()3005 public void requestSecondaryLongLivedClientModeManagerWhenConnectingToPrimaryBssid() 3006 throws Exception { 3007 // Ensure that we can create more client ifaces. 3008 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3009 when(mResources.getBoolean(R.bool.config_wifiMultiStaRestrictedConcurrencyEnabled)) 3010 .thenReturn(true); 3011 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3012 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_LONG_LIVED)); 3013 3014 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 3015 ROLE_CLIENT_SECONDARY_LONG_LIVED); 3016 } 3017 3018 @Test requestRemoveSecondaryTransientClientModeManager()3019 public void requestRemoveSecondaryTransientClientModeManager() throws Exception { 3020 // Ensure that we can create more client ifaces. 3021 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3022 when(mResources.getBoolean( 3023 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3024 .thenReturn(true); 3025 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3026 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3027 3028 requestRemoveAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_TRANSIENT); 3029 } 3030 3031 @Test requestRemoveSecondaryTransientClientModeManagerWhenStaStaNotSupported()3032 public void requestRemoveSecondaryTransientClientModeManagerWhenStaStaNotSupported() 3033 throws Exception { 3034 // Ensure that we cannot create more client ifaces. 3035 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3036 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3037 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3038 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_TRANSIENT); 3039 } 3040 3041 @Test requestRemoveSecondaryTransientClientModeManagerWhenFeatureDisabled()3042 public void requestRemoveSecondaryTransientClientModeManagerWhenFeatureDisabled() 3043 throws Exception { 3044 // Ensure that we can create more client ifaces. 3045 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3046 when(mResources.getBoolean( 3047 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3048 .thenReturn(false); 3049 assertFalse(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3050 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3051 requestRemoveAdditionalClientModeManagerWhenNotAllowed(ROLE_CLIENT_SECONDARY_TRANSIENT); 3052 } 3053 3054 @Test requestSecondaryTransientClientModeManagerWhenWifiIsOff()3055 public void requestSecondaryTransientClientModeManagerWhenWifiIsOff() throws Exception { 3056 // Ensure that we can create more client ifaces. 3057 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3058 when(mResources.getBoolean( 3059 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3060 .thenReturn(true); 3061 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3062 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3063 3064 requestAdditionalClientModeManagerWhenWifiIsOff(ROLE_CLIENT_SECONDARY_TRANSIENT); 3065 } 3066 3067 @Test requestSecondaryTransientClientModeManagerWhenAlreadyPresent()3068 public void requestSecondaryTransientClientModeManagerWhenAlreadyPresent() throws Exception { 3069 // Ensure that we can create more client ifaces. 3070 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3071 when(mResources.getBoolean( 3072 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3073 .thenReturn(true); 3074 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3075 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3076 3077 requestAdditionalClientModeManagerWhenAlreadyPresent(ROLE_CLIENT_SECONDARY_TRANSIENT); 3078 } 3079 3080 @Test requestSecondaryTransientClientModeManagerWhenConnectingToPrimaryBssid()3081 public void requestSecondaryTransientClientModeManagerWhenConnectingToPrimaryBssid() 3082 throws Exception { 3083 // Ensure that we can create more client ifaces. 3084 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3085 when(mResources.getBoolean( 3086 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3087 .thenReturn(true); 3088 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3089 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3090 3091 requestAdditionalClientModeManagerWhenConnectingToPrimaryBssid( 3092 ROLE_CLIENT_SECONDARY_TRANSIENT); 3093 } 3094 3095 @Test requestHighPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid()3096 public void requestHighPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid() 3097 throws Exception { 3098 // Ensure that we can create more client ifaces. 3099 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3100 when(mResources.getBoolean( 3101 R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3102 .thenReturn(true); 3103 when(mResources.getBoolean( 3104 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3105 .thenReturn(true); 3106 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3107 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 3108 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3109 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3110 3111 enterClientModeActiveState(); 3112 3113 // Primary Connected to ssid1/bssid1 3114 WifiConfiguration config1 = new WifiConfiguration(); 3115 config1.SSID = TEST_SSID_1; 3116 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3117 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3118 3119 ConcreteClientModeManager additionalClientModeManager = 3120 mock(ConcreteClientModeManager.class); 3121 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener1 = 3122 new Mutable<>(); 3123 doAnswer((invocation) -> { 3124 Object[] args = invocation.getArguments(); 3125 additionalClientListener1.value = 3126 (Listener<ConcreteClientModeManager>) args[0]; 3127 return additionalClientModeManager; 3128 }).when(mWifiInjector).makeClientModeManager( 3129 any(Listener.class), any(), eq(ROLE_CLIENT_LOCAL_ONLY), 3130 anyBoolean()); 3131 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 3132 3133 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3134 ExternalClientModeManagerRequestListener.class); 3135 // request for ssid2/bssid2 3136 mActiveModeWarden.requestLocalOnlyClientModeManager( 3137 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3138 mLooper.dispatchAll(); 3139 verify(mWifiInjector).makeClientModeManager( 3140 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 3141 additionalClientListener1.value.onStarted(additionalClientModeManager); 3142 mLooper.dispatchAll(); 3143 // Returns the new client mode manager. 3144 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3145 ArgumentCaptor.forClass(ClientModeManager.class); 3146 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3147 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3148 3149 // set additional CMM connected to ssid2/bssid2 3150 WifiConfiguration config2 = new WifiConfiguration(); 3151 config2.SSID = TEST_SSID_2; 3152 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3153 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3154 3155 // request for same ssid2/bssid2 for a different role. 3156 // request for one more CMM (should return the existing local only one). 3157 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3158 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3159 mLooper.dispatchAll(); 3160 3161 // Don't make another client mode manager, but should switch role of existing client mode 3162 // manager. 3163 verify(mWifiInjector, never()) 3164 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3165 anyBoolean()); 3166 ArgumentCaptor<Listener<ConcreteClientModeManager>> 3167 additionalClientListener2 = ArgumentCaptor.forClass( 3168 Listener.class); 3169 verify(additionalClientModeManager).setRole(eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3170 eq(TEST_WORKSOURCE), additionalClientListener2.capture()); 3171 3172 // Simulate completion of role switch. 3173 additionalClientListener2.getValue().onRoleChanged(additionalClientModeManager); 3174 3175 // Returns the existing client mode manager. 3176 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3177 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3178 } 3179 3180 @Test requestLowPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid()3181 public void requestLowPrioSecondaryTransientClientModeManagerWhenConnectedToLocalOnlyBssid() 3182 throws Exception { 3183 // Ensure that we can create more client ifaces. 3184 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3185 when(mResources.getBoolean( 3186 R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3187 .thenReturn(true); 3188 when(mResources.getBoolean( 3189 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3190 .thenReturn(true); 3191 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3192 TEST_WORKSOURCE, ROLE_CLIENT_LOCAL_ONLY)); 3193 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3194 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3195 3196 enterClientModeActiveState(); 3197 3198 // Primary Connected to ssid1/bssid1 3199 WifiConfiguration config1 = new WifiConfiguration(); 3200 config1.SSID = TEST_SSID_1; 3201 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3202 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3203 3204 ConcreteClientModeManager additionalClientModeManager = 3205 mock(ConcreteClientModeManager.class); 3206 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener1 = 3207 new Mutable<>(); 3208 doAnswer((invocation) -> { 3209 Object[] args = invocation.getArguments(); 3210 additionalClientListener1.value = 3211 (Listener<ConcreteClientModeManager>) args[0]; 3212 return additionalClientModeManager; 3213 }).when(mWifiInjector).makeClientModeManager( 3214 any(Listener.class), any(), eq(ROLE_CLIENT_LOCAL_ONLY), 3215 anyBoolean()); 3216 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 3217 3218 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3219 ExternalClientModeManagerRequestListener.class); 3220 // request for ssid2/bssid2 3221 mActiveModeWarden.requestLocalOnlyClientModeManager( 3222 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3223 mLooper.dispatchAll(); 3224 verify(mWifiInjector).makeClientModeManager( 3225 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_LOCAL_ONLY), anyBoolean()); 3226 additionalClientListener1.value.onStarted(additionalClientModeManager); 3227 mLooper.dispatchAll(); 3228 // Returns the new client mode manager. 3229 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3230 ArgumentCaptor.forClass(ClientModeManager.class); 3231 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3232 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3233 3234 // set additional CMM connected to ssid2/bssid2 3235 WifiConfiguration config2 = new WifiConfiguration(); 3236 config2.SSID = TEST_SSID_2; 3237 when(additionalClientModeManager.getConnectedWifiConfiguration()).thenReturn(config2); 3238 when(additionalClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_2); 3239 3240 // Now, deny the creation of STA for the new request 3241 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(false); 3242 3243 // request for same ssid2/bssid2 for a different role. 3244 // request for one more CMM (should return null). 3245 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3246 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3247 mLooper.dispatchAll(); 3248 3249 // Don't make another client mode manager or change role 3250 verify(mWifiInjector, never()) 3251 .makeClientModeManager(any(), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3252 anyBoolean()); 3253 verify(additionalClientModeManager, never()).setRole(eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3254 eq(TEST_WORKSOURCE), any()); 3255 3256 // Ensure the request is rejected. 3257 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3258 assertNull(requestedClientModeManager.getValue()); 3259 } 3260 3261 @Test requestSecondaryTransientClientModeManagerWhenDppInProgress()3262 public void requestSecondaryTransientClientModeManagerWhenDppInProgress() 3263 throws Exception { 3264 // Ensure that we can create more client ifaces. 3265 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3266 when(mResources.getBoolean( 3267 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3268 .thenReturn(true); 3269 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3270 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3271 3272 // Create primary STA. 3273 enterClientModeActiveState(); 3274 3275 // Start DPP session 3276 when(mDppManager.isSessionInProgress()).thenReturn(true); 3277 3278 // request secondary transient CMM creation. 3279 ConcreteClientModeManager additionalClientModeManager = 3280 mock(ConcreteClientModeManager.class); 3281 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3282 new Mutable<>(); 3283 doAnswer((invocation) -> { 3284 Object[] args = invocation.getArguments(); 3285 additionalClientListener.value = 3286 (Listener<ConcreteClientModeManager>) args[0]; 3287 return additionalClientModeManager; 3288 }).when(mWifiInjector).makeClientModeManager( 3289 any(Listener.class), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3290 anyBoolean()); 3291 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 3292 3293 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3294 ExternalClientModeManagerRequestListener.class); 3295 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3296 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3297 mLooper.dispatchAll(); 3298 3299 // verify that we did not create a secondary CMM. 3300 verifyNoMoreInteractions(additionalClientModeManager); 3301 // Returns the existing primary client mode manager. 3302 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3303 ArgumentCaptor.forClass(ClientModeManager.class); 3304 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3305 assertEquals(mClientModeManager, requestedClientModeManager.getValue()); 3306 3307 // Stop ongoing DPP session. 3308 when(mDppManager.isSessionInProgress()).thenReturn(false); 3309 3310 // request secondary transient CMM creation again, now it should be allowed. 3311 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3312 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3313 mLooper.dispatchAll(); 3314 verify(mWifiInjector) 3315 .makeClientModeManager(any(), eq(TEST_WORKSOURCE), 3316 eq(ROLE_CLIENT_SECONDARY_TRANSIENT), anyBoolean()); 3317 additionalClientListener.value.onStarted(additionalClientModeManager); 3318 mLooper.dispatchAll(); 3319 // Returns the new secondary client mode manager. 3320 verify(externalRequestListener, times(2)).onAnswer(requestedClientModeManager.capture()); 3321 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3322 } 3323 3324 @Test configureHwOnMbbSwitch()3325 public void configureHwOnMbbSwitch() 3326 throws Exception { 3327 // Ensure that we can create more client ifaces. 3328 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3329 when(mResources.getBoolean( 3330 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3331 .thenReturn(true); 3332 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3333 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3334 3335 ConcreteClientModeManager additionalClientModeManager = 3336 mock(ConcreteClientModeManager.class); 3337 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3338 ExternalClientModeManagerRequestListener.class); 3339 Listener<ConcreteClientModeManager> additionalClientListener = 3340 requestAdditionalClientModeManager(ROLE_CLIENT_SECONDARY_TRANSIENT, 3341 additionalClientModeManager, externalRequestListener, TEST_SSID_2, 3342 TEST_BSSID_2); 3343 3344 // Now simulate the MBB role switch. 3345 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 3346 mClientListener.onRoleChanged(mClientModeManager); 3347 3348 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 3349 additionalClientListener.onRoleChanged(additionalClientModeManager); 3350 3351 // verify last use case set is PREFER_PRIMARY 3352 ArgumentCaptor<Integer> useCaseCaptor = ArgumentCaptor.forClass(Integer.class); 3353 verify(mWifiNative, atLeastOnce()).setMultiStaUseCase(useCaseCaptor.capture()); 3354 int lastUseCaseSet = useCaseCaptor.getValue().intValue(); 3355 assertEquals(WifiNative.DUAL_STA_TRANSIENT_PREFER_PRIMARY, lastUseCaseSet); 3356 3357 // verify last set of primary connection is for WIFI_IFACE_NAME_1 3358 ArgumentCaptor<String> ifaceNameCaptor = ArgumentCaptor.forClass(String.class); 3359 verify(mWifiNative, atLeastOnce()).setMultiStaPrimaryConnection(ifaceNameCaptor.capture()); 3360 assertEquals(WIFI_IFACE_NAME_1, ifaceNameCaptor.getValue()); 3361 } 3362 3363 @Test airplaneModeToggleOnDisablesWifi()3364 public void airplaneModeToggleOnDisablesWifi() throws Exception { 3365 enterClientModeActiveState(); 3366 assertInEnabledState(); 3367 3368 assertWifiShutDown(() -> { 3369 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 3370 mActiveModeWarden.airplaneModeToggled(); 3371 mLooper.dispatchAll(); 3372 }); 3373 3374 mClientListener.onStopped(mClientModeManager); 3375 mLooper.dispatchAll(); 3376 assertInDisabledState(); 3377 } 3378 3379 @Test airplaneModeToggleOnDisablesSoftAp()3380 public void airplaneModeToggleOnDisablesSoftAp() throws Exception { 3381 enterSoftApActiveMode(); 3382 assertInEnabledState(); 3383 3384 assertWifiShutDown(() -> { 3385 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 3386 mActiveModeWarden.airplaneModeToggled(); 3387 mLooper.dispatchAll(); 3388 }); 3389 3390 mSoftApListener.onStopped(mSoftApManager); 3391 mLooper.dispatchAll(); 3392 assertInDisabledState(); 3393 } 3394 3395 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager()3396 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager() 3397 throws Exception { 3398 enterClientModeActiveState(); 3399 assertInEnabledState(); 3400 3401 // APM toggle on 3402 assertWifiShutDown(() -> { 3403 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 3404 mActiveModeWarden.airplaneModeToggled(); 3405 mLooper.dispatchAll(); 3406 }); 3407 3408 3409 // APM toggle off before the stop is complete. 3410 assertInEnabledState(); 3411 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 3412 mActiveModeWarden.airplaneModeToggled(); 3413 mLooper.dispatchAll(); 3414 3415 mClientListener.onStopped(mClientModeManager); 3416 mLooper.dispatchAll(); 3417 3418 verify(mWifiInjector, times(2)).makeClientModeManager( 3419 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 3420 3421 mClientListener.onStarted(mClientModeManager); 3422 mLooper.dispatchAll(); 3423 3424 // We should be back to enabled state. 3425 assertInEnabledState(); 3426 } 3427 3428 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2()3429 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager2() 3430 throws Exception { 3431 enterClientModeActiveState(); 3432 assertInEnabledState(); 3433 3434 // APM toggle on 3435 assertWifiShutDown(() -> { 3436 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 3437 mActiveModeWarden.airplaneModeToggled(); 3438 mLooper.dispatchAll(); 3439 }); 3440 3441 3442 // APM toggle off before the stop is complete. 3443 assertInEnabledState(); 3444 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 3445 mActiveModeWarden.airplaneModeToggled(); 3446 // This test is identical to 3447 // airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithOneModeManager, except the 3448 // dispatchAll() here is removed. There could be a race between airplaneModeToggled and 3449 // mClientListener.onStopped(). See b/160105640#comment5. 3450 3451 mClientListener.onStopped(mClientModeManager); 3452 mLooper.dispatchAll(); 3453 3454 verify(mWifiInjector, times(2)).makeClientModeManager( 3455 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 3456 3457 mClientListener.onStarted(mClientModeManager); 3458 mLooper.dispatchAll(); 3459 3460 // We should be back to enabled state. 3461 assertInEnabledState(); 3462 } 3463 3464 @Test airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager()3465 public void airplaneModeToggleOffIsDeferredWhileProcessingToggleOnWithTwoModeManager() 3466 throws Exception { 3467 enterClientModeActiveState(); 3468 enterSoftApActiveMode(); 3469 assertInEnabledState(); 3470 3471 // APM toggle on 3472 assertWifiShutDown(() -> { 3473 when(mSettingsStore.isAirplaneModeOn()).thenReturn(true); 3474 mActiveModeWarden.airplaneModeToggled(); 3475 mLooper.dispatchAll(); 3476 }); 3477 3478 3479 // APM toggle off before the stop is complete. 3480 assertInEnabledState(); 3481 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 3482 mActiveModeWarden.airplaneModeToggled(); 3483 mLooper.dispatchAll(); 3484 3485 // AP stopped, should not process APM toggle. 3486 mSoftApListener.onStopped(mSoftApManager); 3487 mLooper.dispatchAll(); 3488 verify(mWifiInjector, times(1)).makeClientModeManager( 3489 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 3490 3491 // STA also stopped, should process APM toggle. 3492 mClientListener.onStopped(mClientModeManager); 3493 mLooper.dispatchAll(); 3494 verify(mWifiInjector, times(2)).makeClientModeManager( 3495 any(), any(), eq(ROLE_CLIENT_PRIMARY), anyBoolean()); 3496 3497 mClientListener.onStarted(mClientModeManager); 3498 mLooper.dispatchAll(); 3499 3500 // We should be back to enabled state. 3501 assertInEnabledState(); 3502 } 3503 3504 @Test propagateVerboseLoggingFlagToClientModeManager()3505 public void propagateVerboseLoggingFlagToClientModeManager() throws Exception { 3506 mActiveModeWarden.enableVerboseLogging(true); 3507 enterClientModeActiveState(); 3508 assertInEnabledState(); 3509 verify(mWifiInjector).makeClientModeManager(any(), any(), any(), eq(true)); 3510 3511 mActiveModeWarden.enableVerboseLogging(false); 3512 verify(mClientModeManager).enableVerboseLogging(false); 3513 } 3514 3515 @Test propagateConnectedWifiScorerToPrimaryClientModeManager()3516 public void propagateConnectedWifiScorerToPrimaryClientModeManager() throws Exception { 3517 IBinder iBinder = mock(IBinder.class); 3518 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 3519 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer); 3520 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 3521 enterClientModeActiveState(); 3522 assertInEnabledState(); 3523 verify(mClientModeManager).setWifiConnectedNetworkScorer(iBinder, iScorer); 3524 3525 mActiveModeWarden.clearWifiConnectedNetworkScorer(); 3526 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 3527 3528 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer); 3529 verify(mClientModeManager, times(2)).setWifiConnectedNetworkScorer(iBinder, iScorer); 3530 } 3531 3532 @Test propagateConnectedWifiScorerToPrimaryClientModeManager_enterScanOnlyState()3533 public void propagateConnectedWifiScorerToPrimaryClientModeManager_enterScanOnlyState() 3534 throws Exception { 3535 IBinder iBinder = mock(IBinder.class); 3536 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 3537 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer); 3538 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 3539 enterClientModeActiveState(); 3540 assertInEnabledState(); 3541 verify(mClientModeManager).setWifiConnectedNetworkScorer(iBinder, iScorer); 3542 3543 enterScanOnlyModeActiveState(true); 3544 3545 verify(mClientModeManager).clearWifiConnectedNetworkScorer(); 3546 } 3547 3548 @Test handleWifiScorerSetScoreUpdateObserverFailure()3549 public void handleWifiScorerSetScoreUpdateObserverFailure() throws Exception { 3550 IBinder iBinder = mock(IBinder.class); 3551 IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class); 3552 doThrow(new RemoteException()).when(iScorer).onSetScoreUpdateObserver(any()); 3553 mActiveModeWarden.setWifiConnectedNetworkScorer(iBinder, iScorer); 3554 verify(iScorer).onSetScoreUpdateObserver(mExternalScoreUpdateObserverProxy); 3555 enterClientModeActiveState(); 3556 assertInEnabledState(); 3557 // Ensure we did not propagate the scorer. 3558 verify(mClientModeManager, never()).setWifiConnectedNetworkScorer(iBinder, iScorer); 3559 } 3560 3561 /** Verify that the primary changed callback is triggered when entering client mode. */ 3562 @Test testAddPrimaryClientModeManager()3563 public void testAddPrimaryClientModeManager() throws Exception { 3564 enterClientModeActiveState(); 3565 3566 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 3567 } 3568 3569 /** Verify the primary changed callback is not triggered when there is no primary. */ 3570 @Test testNoAddPrimaryClientModeManager()3571 public void testNoAddPrimaryClientModeManager() throws Exception { 3572 enterScanOnlyModeActiveState(); 3573 3574 verify(mPrimaryChangedCallback, never()).onChange(any(), any()); 3575 } 3576 3577 /** 3578 * Verify the primary changed callback is triggered when changing the primary from one 3579 * ClientModeManager to another. 3580 */ 3581 @Test testSwitchPrimaryClientModeManager()3582 public void testSwitchPrimaryClientModeManager() throws Exception { 3583 // Ensure that we can create more client ifaces. 3584 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3585 when(mResources.getBoolean( 3586 R.bool.config_wifiMultiStaNetworkSwitchingMakeBeforeBreakEnabled)) 3587 .thenReturn(true); 3588 assertTrue(mActiveModeWarden.canRequestMoreClientModeManagersInRole( 3589 TEST_WORKSOURCE, ROLE_CLIENT_SECONDARY_TRANSIENT)); 3590 3591 enterClientModeActiveState(); 3592 3593 verify(mPrimaryChangedCallback).onChange(null, mClientModeManager); 3594 3595 // Connected to ssid1/bssid1 3596 WifiConfiguration config1 = new WifiConfiguration(); 3597 config1.SSID = TEST_SSID_1; 3598 when(mClientModeManager.getConnectedWifiConfiguration()).thenReturn(config1); 3599 when(mClientModeManager.getConnectedBssid()).thenReturn(TEST_BSSID_1); 3600 3601 ConcreteClientModeManager additionalClientModeManager = 3602 mock(ConcreteClientModeManager.class); 3603 Mutable<Listener<ConcreteClientModeManager>> additionalClientListener = 3604 new Mutable<>(); 3605 doAnswer((invocation) -> { 3606 Object[] args = invocation.getArguments(); 3607 additionalClientListener.value = 3608 (Listener<ConcreteClientModeManager>) args[0]; 3609 return additionalClientModeManager; 3610 }).when(mWifiInjector).makeClientModeManager( 3611 any(Listener.class), any(), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), 3612 anyBoolean()); 3613 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 3614 3615 ExternalClientModeManagerRequestListener externalRequestListener = mock( 3616 ExternalClientModeManagerRequestListener.class); 3617 // request for ssid2/bssid2 3618 mActiveModeWarden.requestSecondaryTransientClientModeManager( 3619 externalRequestListener, TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3620 mLooper.dispatchAll(); 3621 verify(mWifiInjector).makeClientModeManager( 3622 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SECONDARY_TRANSIENT), anyBoolean()); 3623 additionalClientListener.value.onStarted(additionalClientModeManager); 3624 mLooper.dispatchAll(); 3625 // Returns the new client mode manager. 3626 ArgumentCaptor<ClientModeManager> requestedClientModeManager = 3627 ArgumentCaptor.forClass(ClientModeManager.class); 3628 verify(externalRequestListener).onAnswer(requestedClientModeManager.capture()); 3629 assertEquals(additionalClientModeManager, requestedClientModeManager.getValue()); 3630 3631 // primary didn't change yet 3632 verify(mPrimaryChangedCallback, never()).onChange(any(), eq(additionalClientModeManager)); 3633 3634 // change primary 3635 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SECONDARY_TRANSIENT); 3636 mClientListener.onRoleChanged(mClientModeManager); 3637 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 3638 additionalClientListener.value.onRoleChanged(additionalClientModeManager); 3639 3640 // verify callback triggered 3641 verify(mPrimaryChangedCallback).onChange(mClientModeManager, null); 3642 verify(mPrimaryChangedCallback).onChange(null, additionalClientModeManager); 3643 } 3644 3645 @Test testRegisterPrimaryCmmChangedCallbackWhenConnectModeActiveState()3646 public void testRegisterPrimaryCmmChangedCallbackWhenConnectModeActiveState() throws Exception { 3647 enterClientModeActiveState(); 3648 3649 // register a new primary cmm change callback. 3650 ActiveModeWarden.PrimaryClientModeManagerChangedCallback primarCmmCallback = mock( 3651 ActiveModeWarden.PrimaryClientModeManagerChangedCallback.class); 3652 mActiveModeWarden.registerPrimaryClientModeManagerChangedCallback(primarCmmCallback); 3653 // Ensure we get the callback immediately. 3654 verify(primarCmmCallback).onChange(null, mClientModeManager); 3655 } 3656 3657 @Test testGetCmmInRolesWithNullRoleInOneCmm()3658 public void testGetCmmInRolesWithNullRoleInOneCmm() throws Exception { 3659 enterClientModeActiveState(); 3660 3661 // Ensure that we can create more client ifaces. 3662 when(mWifiNative.isItPossibleToCreateStaIface(any())).thenReturn(true); 3663 when(mResources.getBoolean(R.bool.config_wifiMultiStaLocalOnlyConcurrencyEnabled)) 3664 .thenReturn(true); 3665 3666 ConcreteClientModeManager additionalClientModeManager = 3667 mock(ConcreteClientModeManager.class); 3668 when(mWifiInjector.makeClientModeManager( 3669 any(), any(), any(), anyBoolean())).thenReturn(additionalClientModeManager); 3670 3671 mActiveModeWarden.requestLocalOnlyClientModeManager( 3672 mock(ExternalClientModeManagerRequestListener.class), 3673 TEST_WORKSOURCE, TEST_SSID_2, TEST_BSSID_2); 3674 mLooper.dispatchAll(); 3675 3676 // No role set, should be ignored. 3677 when(additionalClientModeManager.getRole()).thenReturn(null); 3678 assertEquals(1, mActiveModeWarden.getClientModeManagersInRoles( 3679 ROLE_CLIENT_PRIMARY, ROLE_CLIENT_LOCAL_ONLY).size()); 3680 3681 // Role set, should be included. 3682 when(additionalClientModeManager.getRole()).thenReturn(ROLE_CLIENT_LOCAL_ONLY); 3683 assertEquals(2, mActiveModeWarden.getClientModeManagersInRoles( 3684 ROLE_CLIENT_PRIMARY, ROLE_CLIENT_LOCAL_ONLY).size()); 3685 } 3686 3687 /** 3688 * Helper method to enter the EnabledState and set ClientModeManager in ScanOnlyMode during 3689 * emergency scan processing. 3690 */ indicateStartOfEmergencyScan( boolean hasAnyOtherStaToggleEnabled, @Nullable ActiveModeManager.ClientRole expectedRole)3691 private void indicateStartOfEmergencyScan( 3692 boolean hasAnyOtherStaToggleEnabled, 3693 @Nullable ActiveModeManager.ClientRole expectedRole) 3694 throws Exception { 3695 String fromState = mActiveModeWarden.getCurrentMode(); 3696 mActiveModeWarden.setEmergencyScanRequestInProgress(true); 3697 mLooper.dispatchAll(); 3698 3699 if (!hasAnyOtherStaToggleEnabled) { 3700 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 3701 mClientListener.onStarted(mClientModeManager); 3702 mLooper.dispatchAll(); 3703 verify(mWifiInjector).makeClientModeManager( 3704 any(), eq(TEST_WORKSOURCE), eq(ROLE_CLIENT_SCAN_ONLY), anyBoolean()); 3705 verify(mModeChangeCallback).onActiveModeManagerAdded(mClientModeManager); 3706 verify(mScanRequestProxy).enableScanning(true, false); 3707 verify(mBatteryStats).reportWifiOn(); 3708 verify(mBatteryStats).reportWifiState( 3709 BatteryStatsManager.WIFI_STATE_OFF_SCANNING, null); 3710 } else { 3711 verify(mClientModeManager).setRole(eq(expectedRole), any()); 3712 verify(mClientModeManager, never()).stop(); 3713 assertEquals(fromState, mActiveModeWarden.getCurrentMode()); 3714 } 3715 assertInEnabledState(); 3716 } 3717 indicateEndOfEmergencyScan( boolean hasAnyOtherStaToggleEnabled, @Nullable ActiveModeManager.ClientRole expectedRole)3718 private void indicateEndOfEmergencyScan( 3719 boolean hasAnyOtherStaToggleEnabled, 3720 @Nullable ActiveModeManager.ClientRole expectedRole) { 3721 String fromState = mActiveModeWarden.getCurrentMode(); 3722 mActiveModeWarden.setEmergencyScanRequestInProgress(false); 3723 mLooper.dispatchAll(); 3724 if (!hasAnyOtherStaToggleEnabled) { 3725 mClientListener.onStopped(mClientModeManager); 3726 mLooper.dispatchAll(); 3727 verify(mModeChangeCallback).onActiveModeManagerRemoved(mClientModeManager); 3728 verify(mScanRequestProxy).enableScanning(false, false); 3729 assertInDisabledState(); 3730 } else { 3731 // Nothing changes. 3732 verify(mClientModeManager).setRole(eq(expectedRole), any()); 3733 verify(mClientModeManager, never()).stop(); 3734 assertEquals(fromState, mActiveModeWarden.getCurrentMode()); 3735 } 3736 } 3737 3738 @Test testEmergencyScanWhenWifiDisabled()3739 public void testEmergencyScanWhenWifiDisabled() throws Exception { 3740 // Wifi fully disabled. 3741 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 3742 when(mSettingsStore.isAirplaneModeOn()).thenReturn(false); 3743 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 3744 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 3745 3746 indicateStartOfEmergencyScan(false, null); 3747 3748 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3749 clearInvocations(mClientModeManager); 3750 3751 indicateEndOfEmergencyScan(false, null); 3752 } 3753 3754 @Test testEmergencyScanWhenWifiEnabled()3755 public void testEmergencyScanWhenWifiEnabled() throws Exception { 3756 // Wifi enabled. 3757 enterClientModeActiveState(); 3758 3759 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3760 3761 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3762 3763 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3764 clearInvocations(mClientModeManager); 3765 3766 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3767 } 3768 3769 @Test testEmergencyScanWhenScanOnlyModeEnabled()3770 public void testEmergencyScanWhenScanOnlyModeEnabled() throws Exception { 3771 // Scan only enabled. 3772 enterScanOnlyModeActiveState(); 3773 3774 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3775 3776 indicateStartOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 3777 3778 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3779 clearInvocations(mClientModeManager); 3780 3781 indicateEndOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 3782 } 3783 3784 @Test testEmergencyScanWhenEcmOnWithWifiDisableInEcbm()3785 public void testEmergencyScanWhenEcmOnWithWifiDisableInEcbm() throws Exception { 3786 // Wifi enabled. 3787 enterClientModeActiveState(); 3788 3789 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3790 3791 // Test with WifiDisableInECBM turned on 3792 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 3793 3794 assertWifiShutDown(() -> { 3795 // test ecm changed 3796 emergencyCallbackModeChanged(true); 3797 mLooper.dispatchAll(); 3798 // fully shutdown 3799 mClientListener.onStopped(mClientModeManager); 3800 mLooper.dispatchAll(); 3801 }); 3802 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3803 3804 indicateStartOfEmergencyScan(false, null); 3805 3806 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3807 clearInvocations(mClientModeManager); 3808 3809 indicateEndOfEmergencyScan(false, null); 3810 } 3811 3812 @Test testEmergencyScanWhenEcmOnWithoutWifiDisableInEcbm()3813 public void testEmergencyScanWhenEcmOnWithoutWifiDisableInEcbm() throws Exception { 3814 // Wifi enabled. 3815 enterClientModeActiveState(); 3816 3817 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3818 3819 // Test with WifiDisableInECBM turned off 3820 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 3821 3822 assertEnteredEcmMode(() -> { 3823 // test ecm changed 3824 emergencyCallbackModeChanged(true); 3825 mLooper.dispatchAll(); 3826 }); 3827 3828 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3829 3830 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3831 clearInvocations(mClientModeManager); 3832 3833 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3834 } 3835 3836 @Test testWifiDisableDuringEmergencyScan()3837 public void testWifiDisableDuringEmergencyScan() throws Exception { 3838 // Wifi enabled. 3839 enterClientModeActiveState(); 3840 3841 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3842 3843 indicateStartOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3844 3845 // Toggle off wifi 3846 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 3847 mActiveModeWarden.wifiToggled(TEST_WORKSOURCE); 3848 mLooper.dispatchAll(); 3849 3850 // Ensure that we switched the role to scan only state because of the emergency scan. 3851 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_SCAN_ONLY); 3852 mClientListener.onRoleChanged(mClientModeManager); 3853 mLooper.dispatchAll(); 3854 verify(mClientModeManager).setRole(ROLE_CLIENT_SCAN_ONLY, INTERNAL_REQUESTOR_WS); 3855 verify(mClientModeManager, never()).stop(); 3856 assertInEnabledState(); 3857 3858 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3859 clearInvocations(mClientModeManager); 3860 3861 indicateEndOfEmergencyScan(false, null); 3862 } 3863 3864 @Test testScanOnlyModeDisableDuringEmergencyScan()3865 public void testScanOnlyModeDisableDuringEmergencyScan() throws Exception { 3866 // Scan only enabled. 3867 enterScanOnlyModeActiveState(); 3868 3869 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3870 3871 indicateStartOfEmergencyScan(true, ROLE_CLIENT_SCAN_ONLY); 3872 3873 // To reset setRole invocation above which is checked below. 3874 clearInvocations(mClientModeManager); 3875 3876 // Toggle off scan only mode 3877 when(mWifiPermissionsUtil.isLocationModeEnabled()).thenReturn(false); 3878 when(mSettingsStore.isScanAlwaysAvailable()).thenReturn(false); 3879 mActiveModeWarden.scanAlwaysModeChanged(); 3880 mLooper.dispatchAll(); 3881 3882 // Ensure that we remained in scan only state because of the emergency scan. 3883 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_SCAN_ONLY), any()); 3884 verify(mClientModeManager, never()).stop(); 3885 assertInEnabledState(); 3886 3887 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3888 clearInvocations(mClientModeManager); 3889 3890 indicateEndOfEmergencyScan(false, null); 3891 } 3892 3893 @Test testEcmOffWithWifiDisabledStateDuringEmergencyScan()3894 public void testEcmOffWithWifiDisabledStateDuringEmergencyScan() throws Exception { 3895 // Wifi enabled. 3896 enterClientModeActiveState(); 3897 3898 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3899 3900 // Test with WifiDisableInECBM turned on 3901 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(true); 3902 3903 assertWifiShutDown(() -> { 3904 // test ecm changed 3905 emergencyCallbackModeChanged(true); 3906 mLooper.dispatchAll(); 3907 // fully shutdown 3908 mClientListener.onStopped(mClientModeManager); 3909 mLooper.dispatchAll(); 3910 }); 3911 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3912 3913 indicateStartOfEmergencyScan(false, null); 3914 3915 // Now turn off ECM 3916 emergencyCallbackModeChanged(false); 3917 mLooper.dispatchAll(); 3918 3919 // Ensure we turned wifi back on. 3920 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_PRIMARY), any()); 3921 when(mClientModeManager.getRole()).thenReturn(ROLE_CLIENT_PRIMARY); 3922 mClientListener.onRoleChanged(mClientModeManager); 3923 verify(mScanRequestProxy).enableScanning(true, true); 3924 assertInEnabledState(); 3925 3926 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3927 clearInvocations(mClientModeManager); 3928 3929 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3930 } 3931 3932 @Test testEcmOffWithoutWifiDisabledStateDuringEmergencyScan()3933 public void testEcmOffWithoutWifiDisabledStateDuringEmergencyScan() throws Exception { 3934 // Wifi enabled. 3935 enterClientModeActiveState(); 3936 3937 reset(mBatteryStats, mScanRequestProxy, mModeChangeCallback); 3938 3939 // Test with WifiDisableInECBM turned off 3940 when(mFacade.getConfigWiFiDisableInECBM(mContext)).thenReturn(false); 3941 3942 assertEnteredEcmMode(() -> { 3943 // test ecm changed 3944 emergencyCallbackModeChanged(true); 3945 mLooper.dispatchAll(); 3946 }); 3947 3948 // Now turn off ECM 3949 emergencyCallbackModeChanged(false); 3950 mLooper.dispatchAll(); 3951 3952 // Ensure that we remained in connected state. 3953 verify(mClientModeManager).setRole(eq(ROLE_CLIENT_PRIMARY), any()); 3954 verify(mClientModeManager, never()).stop(); 3955 assertInEnabledState(); 3956 3957 // To reset setRole invocation above which is checked inside |indicateEndOfEmergencyScan| 3958 clearInvocations(mClientModeManager); 3959 3960 indicateEndOfEmergencyScan(true, ROLE_CLIENT_PRIMARY); 3961 } 3962 } 3963