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