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