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