• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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.EXTRA_PREVIOUS_WIFI_STATE;
20 import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
21 import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;
22 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
23 import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
24 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
25 import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
26 import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
27 
28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
29 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_PRIMARY;
30 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SCAN_ONLY;
31 import static com.android.server.wifi.ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT;
32 
33 import static org.junit.Assert.assertEquals;
34 import static org.junit.Assert.assertNotNull;
35 import static org.junit.Assert.assertNull;
36 import static org.junit.Assert.assertTrue;
37 import static org.mockito.Mockito.*;
38 import static org.mockito.Mockito.any;
39 import static org.mockito.Mockito.anyInt;
40 import static org.mockito.Mockito.doAnswer;
41 import static org.mockito.Mockito.lenient;
42 
43 import android.app.test.MockAnswerUtil.AnswerWithArguments;
44 import android.content.Context;
45 import android.content.Intent;
46 import android.net.ConnectivityManager;
47 import android.net.ConnectivityManager.NetworkCallback;
48 import android.net.NetworkRequest;
49 import android.net.wifi.IWifiConnectedNetworkScorer;
50 import android.net.wifi.WifiManager;
51 import android.os.Handler;
52 import android.os.IBinder;
53 import android.os.PersistableBundle;
54 import android.os.UserHandle;
55 import android.os.WorkSource;
56 import android.os.test.TestLooper;
57 import android.telephony.AccessNetworkConstants;
58 import android.telephony.CarrierConfigManager;
59 import android.telephony.SubscriptionInfo;
60 import android.telephony.SubscriptionManager;
61 import android.telephony.ims.ImsMmTelManager;
62 import android.telephony.ims.RegistrationManager;
63 import android.test.suitebuilder.annotation.SmallTest;
64 import android.util.Log;
65 
66 import com.android.server.wifi.ClientModeManagerBroadcastQueue.QueuedBroadcast;
67 import com.android.wifi.resources.R;
68 
69 import org.junit.After;
70 import org.junit.Before;
71 import org.junit.Test;
72 import org.mockito.ArgumentCaptor;
73 import org.mockito.InOrder;
74 import org.mockito.Mock;
75 import org.mockito.MockitoAnnotations;
76 import org.mockito.MockitoSession;
77 
78 import java.util.ArrayList;
79 import java.util.List;
80 import java.util.concurrent.Executor;
81 
82 /**
83  * Unit tests for {@link ConcreteClientModeManager}.
84  */
85 @SmallTest
86 public class ConcreteClientModeManagerTest extends WifiBaseTest {
87     private static final String TAG = "ClientModeManagerTest";
88     private static final String TEST_INTERFACE_NAME = "testif0";
89     private static final String OTHER_INTERFACE_NAME = "notTestIf";
90     private static final int TEST_WIFI_OFF_DEFERRING_TIME_MS = 4000;
91     private static final int TEST_ACTIVE_SUBSCRIPTION_ID = 1;
92     private static final WorkSource TEST_WORKSOURCE = new WorkSource();
93     private static final WorkSource TEST_WORKSOURCE2 = new WorkSource();
94 
95     TestLooper mLooper;
96 
97     ConcreteClientModeManager mClientModeManager;
98 
99     @Mock Context mContext;
100     @Mock WifiMetrics mWifiMetrics;
101     @Mock WifiNative mWifiNative;
102     @Mock Clock mClock;
103     @Mock ActiveModeManager.Listener<ConcreteClientModeManager> mListener;
104     @Mock WakeupController mWakeupController;
105     @Mock WifiInjector mWifiInjector;
106     @Mock ClientModeImpl mClientModeImpl;
107     @Mock CarrierConfigManager mCarrierConfigManager;
108     @Mock PersistableBundle mCarrierConfigBundle;
109     @Mock ImsMmTelManager mImsMmTelManager;
110     @Mock ConnectivityManager mConnectivityManager;
111     @Mock SubscriptionManager mSubscriptionManager;
112     @Mock SubscriptionInfo mActiveSubscriptionInfo;
113     @Mock SelfRecovery mSelfRecovery;
114     @Mock WifiGlobals mWifiGlobals;
115     @Mock ScanOnlyModeImpl mScanOnlyModeImpl;
116     @Mock DefaultClientModeManager mDefaultClientModeManager;
117     @Mock ClientModeManagerBroadcastQueue mBroadcastQueue;
118 
119     private RegistrationManager.RegistrationCallback mImsMmTelManagerRegistrationCallback = null;
120     private @RegistrationManager.ImsRegistrationState int mCurrentImsRegistrationState =
121             RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
122     private @AccessNetworkConstants.TransportType int mCurrentImsConnectionType =
123             AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
124     private NetworkRequest mImsRequest = null;
125     private NetworkCallback mImsNetworkCallback = null;
126     private Handler mImsNetworkCallbackHandler = null;
127     private long mElapsedSinceBootMillis = 0L;
128     private List<SubscriptionInfo> mSubscriptionInfoList = new ArrayList<>();
129     private MockResources mResources;
130 
131     private MockitoSession mStaticMockSession = null;
132 
133     final ArgumentCaptor<WifiNative.InterfaceCallback> mInterfaceCallbackCaptor =
134             ArgumentCaptor.forClass(WifiNative.InterfaceCallback.class);
135 
136     /**
137      * If mContext is reset, call it again to ensure system services could be retrieved
138      * from the context.
139      */
setUpSystemServiceForContext()140     private void setUpSystemServiceForContext() {
141         when(mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE))
142                 .thenReturn(mCarrierConfigManager);
143         when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
144                 .thenReturn(mSubscriptionManager);
145         when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
146                 .thenReturn(mConnectivityManager);
147         when(mContext.getResources()).thenReturn(mResources);
148         when(mWifiInjector.makeClientModeImpl(any(), any(), anyBoolean()))
149                 .thenReturn(mClientModeImpl);
150         when(mWifiInjector.makeScanOnlyModeImpl(any())).thenReturn(mScanOnlyModeImpl);
151     }
152 
153     /*
154      * Use this helper to move mock looper and clock together.
155      */
moveTimeForward(long timeMillis)156     private void moveTimeForward(long timeMillis) {
157         mLooper.moveTimeForward(timeMillis);
158         mElapsedSinceBootMillis += timeMillis;
159     }
160 
161 
162     @Before
setUp()163     public void setUp() throws Exception {
164         MockitoAnnotations.initMocks(this);
165 
166         // Prepare data
167         mResources = new MockResources();
168         mResources.setInteger(R.integer.config_wifiDelayDisconnectOnImsLostMs, 0);
169         mSubscriptionInfoList.add(mActiveSubscriptionInfo);
170 
171         setUpSystemServiceForContext();
172 
173         /**
174          * default mock for IMS deregistration:
175          * * No wifi calling
176          * * No network
177          * * no deferring time for wifi off
178          */
179         mStaticMockSession = mockitoSession()
180             .mockStatic(ImsMmTelManager.class)
181             .mockStatic(SubscriptionManager.class)
182             .startMocking();
183         lenient().when(ImsMmTelManager.createForSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID)))
184                 .thenReturn(mImsMmTelManager);
185         lenient().when(SubscriptionManager.isValidSubscriptionId(eq(TEST_ACTIVE_SUBSCRIPTION_ID)))
186                 .thenReturn(true);
187         doAnswer(new AnswerWithArguments() {
188             public void answer(Executor executor, RegistrationManager.RegistrationCallback c) {
189                 mImsMmTelManagerRegistrationCallback = c;
190                 // When the callback is registered, it will initiate the callback c to
191                 // be called with the current registration state.
192                 switch (mCurrentImsRegistrationState) {
193                     case RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED:
194                         c.onUnregistered(null);
195                         break;
196                     case RegistrationManager.REGISTRATION_STATE_REGISTERED:
197                         c.onRegistered(mCurrentImsConnectionType);
198                         break;
199                 }
200             }
201         }).when(mImsMmTelManager).registerImsRegistrationCallback(
202                 any(Executor.class),
203                 any(RegistrationManager.RegistrationCallback.class));
204         doAnswer(new AnswerWithArguments() {
205             public void answer(RegistrationManager.RegistrationCallback c) {
206                 if (mImsMmTelManagerRegistrationCallback == c) {
207                     mImsMmTelManagerRegistrationCallback = null;
208                 }
209             }
210         }).when(mImsMmTelManager).unregisterImsRegistrationCallback(
211                 any(RegistrationManager.RegistrationCallback.class));
212         when(mImsMmTelManager.isAvailable(anyInt(), anyInt())).thenReturn(false);
213 
214         when(mActiveSubscriptionInfo.getSubscriptionId()).thenReturn(TEST_ACTIVE_SUBSCRIPTION_ID);
215         when(mSubscriptionManager.getActiveSubscriptionInfoList())
216                 .thenReturn(mSubscriptionInfoList);
217         when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(mCarrierConfigBundle);
218         when(mCarrierConfigBundle
219                 .getInt(eq(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT)))
220                 .thenReturn(0);
221         doAnswer(new AnswerWithArguments() {
222             public void answer(NetworkRequest req, NetworkCallback callback, Handler handler) {
223                 mImsRequest = req;
224                 mImsNetworkCallback = callback;
225                 mImsNetworkCallbackHandler = handler;
226             }
227         }).when(mConnectivityManager).registerNetworkCallback(any(), any(), any());
228         doAnswer(new AnswerWithArguments() {
229             public void answer(NetworkCallback callback) {
230                 if (mImsNetworkCallback == callback) mImsNetworkCallback = null;
231             }
232         }).when(mConnectivityManager).unregisterNetworkCallback(any(NetworkCallback.class));
233         doAnswer(new AnswerWithArguments() {
234             public long answer() {
235                 return mElapsedSinceBootMillis;
236             }
237         }).when(mClock).getElapsedSinceBootMillis();
238         when(mWifiNative.replaceStaIfaceRequestorWs(TEST_INTERFACE_NAME, TEST_WORKSOURCE))
239                 .thenReturn(true);
240         doAnswer(new AnswerWithArguments() {
241             public void answer(ClientModeManager manager, QueuedBroadcast broadcast) {
242                 broadcast.send();
243             }
244         }).when(mBroadcastQueue).queueOrSendBroadcast(any(), any());
245 
246         mLooper = new TestLooper();
247     }
248 
249     @After
cleanUp()250     public void cleanUp() throws Exception {
251         mStaticMockSession.finishMocking();
252     }
253 
createClientModeManager(ActiveModeManager.ClientRole role)254     private ConcreteClientModeManager createClientModeManager(ActiveModeManager.ClientRole role) {
255         return new ConcreteClientModeManager(mContext, mLooper.getLooper(), mClock, mWifiNative,
256                 mListener, mWifiMetrics, mWakeupController, mWifiInjector, mSelfRecovery,
257                 mWifiGlobals, mDefaultClientModeManager, 0, TEST_WORKSOURCE, role,
258                 mBroadcastQueue, false);
259     }
260 
startClientInScanOnlyModeAndVerifyEnabled()261     private void startClientInScanOnlyModeAndVerifyEnabled() throws Exception {
262         when(mWifiNative.setupInterfaceForClientInScanMode(any(), any()))
263                 .thenReturn(TEST_INTERFACE_NAME);
264         mClientModeManager = createClientModeManager(ROLE_CLIENT_SCAN_ONLY);
265         mLooper.dispatchAll();
266 
267         verify(mWifiNative).setupInterfaceForClientInScanMode(
268                 mInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE));
269         verify(mWifiInjector, never()).makeClientModeImpl(any(), any(), anyBoolean());
270 
271         // now mark the interface as up
272         mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
273         mLooper.dispatchAll();
274 
275         // Ensure that no public broadcasts were sent.
276         verifyNoMoreInteractions(mContext);
277         verify(mListener).onStarted(mClientModeManager);
278         verify(mWifiNative).setScanMode(TEST_INTERFACE_NAME, true);
279     }
280 
startClientInConnectModeAndVerifyEnabled()281     private void startClientInConnectModeAndVerifyEnabled() throws Exception {
282         when(mWifiNative.setupInterfaceForClientInScanMode(any(), any()))
283                 .thenReturn(TEST_INTERFACE_NAME);
284         when(mWifiNative.switchClientInterfaceToConnectivityMode(any(), any()))
285                 .thenReturn(true);
286         mClientModeManager = createClientModeManager(ROLE_CLIENT_PRIMARY);
287         mLooper.dispatchAll();
288 
289         verify(mWifiNative).setupInterfaceForClientInScanMode(
290                 mInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE));
291         verify(mWifiNative).switchClientInterfaceToConnectivityMode(
292                 TEST_INTERFACE_NAME, TEST_WORKSOURCE);
293         verify(mWifiInjector)
294                 .makeClientModeImpl(eq(TEST_INTERFACE_NAME), eq(mClientModeManager), anyBoolean());
295 
296         // now mark the interface as up
297         mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
298         mLooper.dispatchAll();
299 
300         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
301         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
302                 eq(UserHandle.ALL));
303 
304         List<Intent> intents = intentCaptor.getAllValues();
305         assertEquals(2, intents.size());
306         Log.d(TAG, "captured intents: " + intents);
307         checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
308                 WIFI_STATE_DISABLED);
309         checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED,
310                 WIFI_STATE_ENABLING);
311         assertEquals(WIFI_STATE_ENABLED, mClientModeManager.syncGetWifiState());
312 
313         verify(mListener).onStarted(mClientModeManager);
314     }
315 
checkWifiConnectModeStateChangedBroadcast( Intent intent, int expectedCurrentState, int expectedPrevState)316     private void checkWifiConnectModeStateChangedBroadcast(
317             Intent intent, int expectedCurrentState, int expectedPrevState) {
318         String action = intent.getAction();
319         assertEquals(WIFI_STATE_CHANGED_ACTION, action);
320         int currentState = intent.getIntExtra(EXTRA_WIFI_STATE, WIFI_STATE_UNKNOWN);
321         assertEquals(expectedCurrentState, currentState);
322         int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_STATE, WIFI_STATE_UNKNOWN);
323         assertEquals(expectedPrevState, prevState);
324     }
325 
verifyConnectModeNotificationsForCleanShutdown(int fromState)326     private void verifyConnectModeNotificationsForCleanShutdown(int fromState) {
327         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
328         verify(mContext, atLeastOnce())
329                 .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
330 
331         List<Intent> intents = intentCaptor.getAllValues();
332         assertTrue(intents.size() >= 2);
333         checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 2),
334                 WIFI_STATE_DISABLING, fromState);
335         checkWifiConnectModeStateChangedBroadcast(intents.get(intents.size() - 1),
336                 WIFI_STATE_DISABLED, WIFI_STATE_DISABLING);
337         assertEquals(WIFI_STATE_DISABLED, mClientModeManager.syncGetWifiState());
338     }
339 
verifyConnectModeNotificationsForFailure()340     private void verifyConnectModeNotificationsForFailure() {
341         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
342         verify(mContext, atLeastOnce())
343                 .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));
344 
345         List<Intent> intents = intentCaptor.getAllValues();
346         assertEquals(2, intents.size());
347         checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_DISABLING,
348                 WIFI_STATE_UNKNOWN);
349         checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED,
350                 WIFI_STATE_DISABLING);
351         assertEquals(WIFI_STATE_DISABLED, mClientModeManager.syncGetWifiState());
352     }
353 
354     /**
355      * ClientMode start sets up an interface in ClientMode.
356      */
357     @Test
clientInConnectModeStartCreatesClientInterface()358     public void clientInConnectModeStartCreatesClientInterface() throws Exception {
359         startClientInConnectModeAndVerifyEnabled();
360     }
361 
362     /**
363      * ClientMode start sets up an interface in ClientMode.
364      */
365     @Test
clientInScanOnlyModeStartCreatesClientInterface()366     public void clientInScanOnlyModeStartCreatesClientInterface() throws Exception {
367         startClientInScanOnlyModeAndVerifyEnabled();
368 
369         mClientModeManager.getFactoryMacAddress();
370         // in scan only mode, should get value from ScanOnlyModeImpl
371         verify(mScanOnlyModeImpl).getFactoryMacAddress();
372     }
373 
374     /**
375      * Switch ClientModeManager from ScanOnly mode To Connect mode.
376      */
377     @Test
switchFromScanOnlyModeToConnectMode()378     public void switchFromScanOnlyModeToConnectMode() throws Exception {
379         startClientInScanOnlyModeAndVerifyEnabled();
380 
381         when(mWifiNative.switchClientInterfaceToConnectivityMode(any(), any()))
382                 .thenReturn(true);
383         mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
384         mLooper.dispatchAll();
385 
386         verify(mWifiNative).setScanMode(TEST_INTERFACE_NAME, false);
387 
388         verify(mWifiInjector)
389                 .makeClientModeImpl(eq(TEST_INTERFACE_NAME), eq(mClientModeManager), anyBoolean());
390 
391         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
392         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
393                 eq(UserHandle.ALL));
394 
395         List<Intent> intents = intentCaptor.getAllValues();
396         assertEquals(2, intents.size());
397         Log.d(TAG, "captured intents: " + intents);
398         checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
399                 WIFI_STATE_DISABLED);
400         checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED,
401                 WIFI_STATE_ENABLING);
402         assertEquals(WIFI_STATE_ENABLED, mClientModeManager.syncGetWifiState());
403 
404         verify(mListener).onStarted(mClientModeManager);
405         verify(mListener).onRoleChanged(mClientModeManager);
406 
407         mClientModeManager.getFactoryMacAddress();
408         // in client mode, should get value from ClientModeImpl
409         verify(mClientModeImpl).getFactoryMacAddress();
410     }
411 
412     /**
413      * Verify that no more public broadcasts are sent out after
414      * setWifiStateChangeBroadcastEnabled(false) is called.
415      */
416     @Test
testDisableWifiStateChangedBroadcasts()417     public void testDisableWifiStateChangedBroadcasts() throws Exception {
418         startClientInConnectModeAndVerifyEnabled();
419 
420         mClientModeManager.setWifiStateChangeBroadcastEnabled(false);
421         mClientModeManager.stop();
422         mLooper.dispatchAll();
423 
424         verify(mClientModeImpl).stop();
425         assertEquals(WIFI_STATE_DISABLED, mClientModeManager.syncGetWifiState());
426 
427         // Ensure that only public broadcasts for the "start" events were sent.
428         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
429         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
430                 eq(UserHandle.ALL));
431 
432         List<Intent> intents = intentCaptor.getAllValues();
433         assertEquals(2, intents.size());
434         Log.d(TAG, "captured intents: " + intents);
435         checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
436                 WIFI_STATE_DISABLED);
437         checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_ENABLED,
438                 WIFI_STATE_ENABLING);
439     }
440 
441     /**
442      * Switch ClientModeManager from Connect mode to ScanOnly mode.
443      */
444     @Test
switchFromConnectModeToScanOnlyMode()445     public void switchFromConnectModeToScanOnlyMode() throws Exception {
446         startClientInConnectModeAndVerifyEnabled();
447 
448         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
449                 .thenReturn(true);
450         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
451         mLooper.dispatchAll();
452 
453         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
454         verify(mWifiNative).setupInterfaceForClientInScanMode(
455                 mInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE));
456         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
457         verify(mClientModeImpl).stop();
458 
459         verify(mContext).getSystemService(anyString());
460         verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any());
461         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
462 
463         // Ensure that no public broadcasts were sent.
464         verifyNoMoreInteractions(mContext);
465         verify(mListener).onStarted(mClientModeManager);
466         verify(mListener).onRoleChanged(mClientModeManager);
467     }
468 
469     /**
470      * ClientMode increments failure metrics when failing to setup client mode in connectivity mode.
471      */
472     @Test
detectAndReportErrorWhenSetupForClientInConnectivityModeWifiNativeFailure()473     public void detectAndReportErrorWhenSetupForClientInConnectivityModeWifiNativeFailure()
474             throws Exception {
475         when(mWifiNative.setupInterfaceForClientInScanMode(any(), any()))
476                 .thenReturn(TEST_INTERFACE_NAME);
477         when(mWifiNative.switchClientInterfaceToConnectivityMode(any(), any())).thenReturn(false);
478 
479         mClientModeManager = createClientModeManager(ROLE_CLIENT_PRIMARY);
480         mLooper.dispatchAll();
481 
482         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
483         verify(mContext, atLeastOnce()).sendStickyBroadcastAsUser(intentCaptor.capture(),
484                 eq(UserHandle.ALL));
485         List<Intent> intents = intentCaptor.getAllValues();
486         assertEquals(2, intents.size());
487         checkWifiConnectModeStateChangedBroadcast(intents.get(0), WIFI_STATE_ENABLING,
488                 WIFI_STATE_DISABLED);
489         checkWifiConnectModeStateChangedBroadcast(intents.get(1), WIFI_STATE_DISABLED,
490                 WIFI_STATE_UNKNOWN);
491         assertEquals(WIFI_STATE_DISABLED, mClientModeManager.syncGetWifiState());
492         verify(mListener).onStartFailure(mClientModeManager);
493     }
494 
495     /** Tests failure when setting up iface for scan only mode. */
496     @Test
detectAndReportErrorWhenSetupInterfaceForClientInScanModeWifiNativeFailure()497     public void detectAndReportErrorWhenSetupInterfaceForClientInScanModeWifiNativeFailure()
498             throws Exception {
499         // failed to setup iface in Scan Only mode
500         when(mWifiNative.setupInterfaceForClientInScanMode(any(), any())).thenReturn(null);
501 
502         mClientModeManager = createClientModeManager(ROLE_CLIENT_PRIMARY);
503         mLooper.dispatchAll();
504 
505         assertEquals(WIFI_STATE_DISABLED, mClientModeManager.syncGetWifiState());
506         verify(mListener).onStartFailure(mClientModeManager);
507 
508         mClientModeManager.getFactoryMacAddress();
509         // wifi is off, should get value from DefaultClientModeManager
510         verify(mDefaultClientModeManager).getFactoryMacAddress();
511     }
512 
513     /**
514      * ClientMode stop before start has been processed properly cleans up state & invokes the
515      * onStopped callback.
516      */
517     @Test
clientModeStopBeforeStartCleansUpState()518     public void clientModeStopBeforeStartCleansUpState() throws Exception {
519         mClientModeManager = createClientModeManager(ROLE_CLIENT_PRIMARY);
520         // Invoke stop before the internal start is processed by the state machine.
521         mClientModeManager.stop();
522         mLooper.dispatchAll();
523         when(mClientModeImpl.hasQuit()).thenReturn(true);
524         mClientModeManager.onClientModeImplQuit();
525         verify(mListener).onStopped(mClientModeManager);
526 
527         // Don't initiate wifi native setup.
528         verifyNoMoreInteractions(mListener, mWifiNative);
529         assertNull(mClientModeManager.getRole());
530         assertNull(mClientModeManager.getPreviousRole());
531     }
532 
533     /**
534      * ClientMode stop properly cleans up state & invokes the onStopped callback.
535      */
536     @Test
clientModeStopCleansUpState()537     public void clientModeStopCleansUpState() throws Exception {
538         startClientInConnectModeAndVerifyEnabled();
539         reset(mContext, mListener);
540         setUpSystemServiceForContext();
541         mClientModeManager.stop();
542         mLooper.dispatchAll();
543         // role has not been reset yet
544         ActiveModeManager.ClientRole lastRole = mClientModeManager.getRole();
545         assertNotNull(lastRole);
546         assertNull(mClientModeManager.getPreviousRole());
547 
548         long testChangeRoleTimestamp = 12234455L;
549         when(mClock.getElapsedSinceBootMillis()).thenReturn(testChangeRoleTimestamp);
550         when(mClientModeImpl.hasQuit()).thenReturn(true);
551         mClientModeManager.onClientModeImplQuit();
552         verify(mListener).onStopped(mClientModeManager);
553 
554         // then role will be reset
555         assertNull(mClientModeManager.getRole());
556         assertEquals("Should equal previous role", lastRole,
557                 mClientModeManager.getPreviousRole());
558         assertEquals("The role change timestamp should match", testChangeRoleTimestamp,
559                 mClientModeManager.getLastRoleChangeSinceBootMs());
560 
561         verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any());
562         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
563 
564         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
565 
566         // on an explicit stop, we should not trigger the callback
567         verifyNoMoreInteractions(mListener);
568     }
569 
570     /**
571      * Triggering interface down when ClientMode is active properly exits the active state.
572      */
573     @Test
clientModeStartedStopsWhenInterfaceDown()574     public void clientModeStartedStopsWhenInterfaceDown() throws Exception {
575         startClientInConnectModeAndVerifyEnabled();
576         reset(mContext);
577         setUpSystemServiceForContext();
578         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(false);
579         mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
580         mLooper.dispatchAll();
581         verify(mSelfRecovery).trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
582         verifyConnectModeNotificationsForFailure();
583         when(mClientModeImpl.hasQuit()).thenReturn(true);
584         mClientModeManager.onClientModeImplQuit();
585         verify(mListener).onStopped(mClientModeManager);
586     }
587 
588     /**
589      * Triggering interface down when ClientMode is active and Connected MacRandomization is enabled
590      * does not exit the active state.
591      */
592     @Test
clientModeStartedWithConnectedMacRandDoesNotStopWhenInterfaceDown()593     public void clientModeStartedWithConnectedMacRandDoesNotStopWhenInterfaceDown()
594             throws Exception {
595         startClientInConnectModeAndVerifyEnabled();
596         reset(mContext);
597         setUpSystemServiceForContext();
598         when(mWifiGlobals.isConnectedMacRandomizationEnabled()).thenReturn(true);
599         when(mClientModeImpl.isConnecting()).thenReturn(true);
600         mInterfaceCallbackCaptor.getValue().onDown(TEST_INTERFACE_NAME);
601         mLooper.dispatchAll();
602         verify(mSelfRecovery, never()).trigger(SelfRecovery.REASON_STA_IFACE_DOWN);
603         verify(mContext, never()).sendStickyBroadcastAsUser(any(), any());
604     }
605 
606     /**
607      * Testing the handling of an interface destroyed notification.
608      */
609     @Test
clientModeStartedStopsOnInterfaceDestroyed()610     public void clientModeStartedStopsOnInterfaceDestroyed() throws Exception {
611         startClientInConnectModeAndVerifyEnabled();
612         reset(mContext);
613         setUpSystemServiceForContext();
614         mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
615         mLooper.dispatchAll();
616         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
617         verify(mClientModeImpl).handleIfaceDestroyed();
618         when(mClientModeImpl.hasQuit()).thenReturn(true);
619         mClientModeManager.onClientModeImplQuit();
620         verify(mListener).onStopped(mClientModeManager);
621     }
622 
623     /**
624      * Verify that onDestroyed after client mode is stopped doesn't trigger a callback.
625      */
626     @Test
noCallbackOnInterfaceDestroyedWhenAlreadyStopped()627     public void noCallbackOnInterfaceDestroyedWhenAlreadyStopped() throws Exception {
628         startClientInConnectModeAndVerifyEnabled();
629 
630         reset(mListener);
631 
632         mClientModeManager.stop();
633         mLooper.dispatchAll();
634 
635         // now trigger interface destroyed and make sure callback doesn't get called
636         mInterfaceCallbackCaptor.getValue().onDestroyed(TEST_INTERFACE_NAME);
637         mLooper.dispatchAll();
638         when(mClientModeImpl.hasQuit()).thenReturn(true);
639         mClientModeManager.onClientModeImplQuit();
640         verify(mListener).onStopped(mClientModeManager);
641 
642         verifyNoMoreInteractions(mListener);
643         verify(mClientModeImpl, never()).handleIfaceDestroyed();
644     }
645 
646     /**
647      * Entering ScanOnly state starts the WakeupController.
648      */
649     @Test
scanModeEnterStartsWakeupController()650     public void scanModeEnterStartsWakeupController() throws Exception {
651         startClientInScanOnlyModeAndVerifyEnabled();
652 
653         verify(mWakeupController).start();
654     }
655 
656     /**
657      * Exiting ScanOnly state stops the WakeupController.
658      */
659     @Test
scanModeExitStopsWakeupController()660     public void scanModeExitStopsWakeupController() throws Exception {
661         startClientInScanOnlyModeAndVerifyEnabled();
662 
663         mClientModeManager.stop();
664         mLooper.dispatchAll();
665 
666         assertNull(mClientModeManager.getRole());
667 
668         InOrder inOrder = inOrder(mWakeupController, mWifiNative, mListener);
669 
670         inOrder.verify(mListener).onStarted(mClientModeManager);
671         inOrder.verify(mWakeupController).start();
672         inOrder.verify(mWakeupController).stop();
673         inOrder.verify(mWifiNative).teardownInterface(eq(TEST_INTERFACE_NAME));
674     }
675 
setUpVoWifiTest( boolean isWifiCallingAvailable, int wifiOffDeferringTimeMs)676     private void setUpVoWifiTest(
677             boolean isWifiCallingAvailable,
678             int wifiOffDeferringTimeMs) {
679         mCurrentImsRegistrationState = (isWifiCallingAvailable)
680             ? RegistrationManager.REGISTRATION_STATE_REGISTERED
681             : RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED;
682         mCurrentImsConnectionType = (isWifiCallingAvailable)
683             ? AccessNetworkConstants.TRANSPORT_TYPE_WLAN
684             : AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
685         when(mImsMmTelManager.isAvailable(anyInt(), anyInt())).thenReturn(isWifiCallingAvailable);
686         when(mCarrierConfigBundle
687                 .getInt(eq(CarrierConfigManager.Ims.KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT)))
688                 .thenReturn(wifiOffDeferringTimeMs);
689     }
690 
691     /**
692      * ClientMode stop properly with IMS deferring time without WifiCalling.
693      */
694     @Test
clientModeStopWithWifiOffDeferringTimeNoWifiCalling()695     public void clientModeStopWithWifiOffDeferringTimeNoWifiCalling() throws Exception {
696         setUpVoWifiTest(false,
697                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
698 
699         startClientInConnectModeAndVerifyEnabled();
700         reset(mContext, mListener);
701         setUpSystemServiceForContext();
702         mClientModeManager.stop();
703         mLooper.dispatchAll();
704         when(mClientModeImpl.hasQuit()).thenReturn(true);
705         mClientModeManager.onClientModeImplQuit();
706         verify(mListener).onStopped(mClientModeManager);
707 
708         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
709 
710         verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any());
711         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
712         verify(mWifiMetrics).noteWifiOff(eq(false), eq(false), anyInt());
713 
714         // on an explicit stop, we should not trigger the callback
715         verifyNoMoreInteractions(mListener);
716     }
717 
718     /**
719      * ClientMode stop properly with IMS deferring time and IMS is registered on WWAN.
720      */
721     @Test
clientModeStopWithWifiOffDeferringTimeAndImsOnWwan()722     public void clientModeStopWithWifiOffDeferringTimeAndImsOnWwan() throws Exception {
723         setUpVoWifiTest(true,
724                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
725         mCurrentImsConnectionType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
726 
727         startClientInConnectModeAndVerifyEnabled();
728         reset(mContext, mListener);
729         setUpSystemServiceForContext();
730         mClientModeManager.stop();
731         mLooper.dispatchAll();
732         when(mClientModeImpl.hasQuit()).thenReturn(true);
733         mClientModeManager.onClientModeImplQuit();
734         verify(mListener).onStopped(mClientModeManager);
735 
736         verify(mImsMmTelManager).registerImsRegistrationCallback(
737                 any(Executor.class),
738                 any(RegistrationManager.RegistrationCallback.class));
739         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
740                 any(RegistrationManager.RegistrationCallback.class));
741         assertNull(mImsMmTelManagerRegistrationCallback);
742         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
743 
744         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
745 
746         // on an explicit stop, we should not trigger the callback
747         verifyNoMoreInteractions(mListener);
748     }
749 
750     /**
751      * ClientMode stop properly with IMS deferring time, Wifi calling.
752      */
753     @Test
clientModeStopWithWifiOffDeferringTimeWithWifiCalling()754     public void clientModeStopWithWifiOffDeferringTimeWithWifiCalling() throws Exception {
755         setUpVoWifiTest(true,
756                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
757 
758         startClientInConnectModeAndVerifyEnabled();
759         reset(mContext, mListener);
760         setUpSystemServiceForContext();
761         mClientModeManager.stop();
762         mLooper.dispatchAll();
763 
764         // Not yet finish IMS deregistration.
765         verify(mImsMmTelManager).registerImsRegistrationCallback(
766                 any(Executor.class),
767                 any(RegistrationManager.RegistrationCallback.class));
768         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
769         verify(mListener, never()).onStopped(any());
770         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
771 
772         // Notify wifi service IMS service is de-registered.
773         assertNotNull(mImsMmTelManagerRegistrationCallback);
774         mImsMmTelManagerRegistrationCallback.onUnregistered(null);
775         assertNotNull(mImsNetworkCallback);
776         mImsNetworkCallback.onLost(null);
777         mLooper.dispatchAll();
778 
779         // Now Wifi could be turned off actually.
780         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
781                 any(RegistrationManager.RegistrationCallback.class));
782         assertNull(mImsMmTelManagerRegistrationCallback);
783         assertNull(mImsNetworkCallback);
784         when(mClientModeImpl.hasQuit()).thenReturn(true);
785         mClientModeManager.onClientModeImplQuit();
786         verify(mListener).onStopped(mClientModeManager);
787         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
788 
789         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
790 
791         // on an explicit stop, we should not trigger the callback
792         verifyNoMoreInteractions(mListener);
793     }
794 
795     /**
796      * ClientMode stop properly with IMS deferring time, Wifi calling.
797      *
798      * The network losts first and then IMS is de-registered.
799      * The WIFI should be off after IMS deregistration.
800      */
801     @Test
clientModeStopWithWifiOffDeferringTimeWithWifiCallingAndNetworkLostFirst()802     public void clientModeStopWithWifiOffDeferringTimeWithWifiCallingAndNetworkLostFirst()
803             throws Exception {
804         setUpVoWifiTest(true,
805                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
806 
807         startClientInConnectModeAndVerifyEnabled();
808         reset(mContext, mListener);
809         setUpSystemServiceForContext();
810         mClientModeManager.stop();
811         mLooper.dispatchAll();
812 
813         // Not yet finish IMS deregistration.
814         verify(mImsMmTelManager).registerImsRegistrationCallback(
815                 any(Executor.class),
816                 any(RegistrationManager.RegistrationCallback.class));
817         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
818         when(mClientModeImpl.hasQuit()).thenReturn(true);
819         mClientModeManager.onClientModeImplQuit();
820         verify(mListener, never()).onStopped(any());
821         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
822 
823         // Notify wifi service the network lost.
824         assertNotNull(mImsNetworkCallback);
825         mImsNetworkCallback.onLost(null);
826         mLooper.dispatchAll();
827 
828         // Since IMS service is not de-registered yet, wifi should be available.
829         moveTimeForward(1000);
830         mLooper.dispatchAll();
831         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
832         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
833         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
834 
835         // Notify wifi service IMS service is de-registered.
836         assertNotNull(mImsMmTelManagerRegistrationCallback);
837         mImsMmTelManagerRegistrationCallback.onUnregistered(null);
838         mLooper.dispatchAll();
839 
840         // Now Wifi could be turned off actually.
841         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
842                 any(RegistrationManager.RegistrationCallback.class));
843         assertNull(mImsMmTelManagerRegistrationCallback);
844         assertNull(mImsNetworkCallback);
845         when(mClientModeImpl.hasQuit()).thenReturn(true);
846         mClientModeManager.onClientModeImplQuit();
847         verify(mListener).onStopped(mClientModeManager);
848         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
849 
850         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
851 
852         // on an explicit stop, we should not trigger the callback
853         verifyNoMoreInteractions(mListener);
854     }
855 
856     /**
857      * ClientMode stop properly with IMS deferring time and Wifi calling.
858      *
859      * IMS deregistration is done before reaching the timeout.
860      */
861     @Test
clientModeStopWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered()862     public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered()
863             throws Exception {
864         setUpVoWifiTest(true,
865                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
866 
867         startClientInConnectModeAndVerifyEnabled();
868         reset(mContext, mListener);
869         setUpSystemServiceForContext();
870         mClientModeManager.stop();
871         mLooper.dispatchAll();
872 
873         // Not yet finish IMS deregistration.
874         verify(mImsMmTelManager).registerImsRegistrationCallback(
875                 any(Executor.class),
876                 any(RegistrationManager.RegistrationCallback.class));
877         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
878         when(mClientModeImpl.hasQuit()).thenReturn(true);
879         mClientModeManager.onClientModeImplQuit();
880         verify(mListener, never()).onStopped(any());
881         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
882 
883         // Notify wifi service IMS service is de-registered.
884         assertNotNull(mImsMmTelManagerRegistrationCallback);
885         mImsMmTelManagerRegistrationCallback.onRegistered(0);
886         mLooper.dispatchAll();
887 
888         // Now Wifi could be turned off actually.
889         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
890                 any(RegistrationManager.RegistrationCallback.class));
891         assertNull(mImsMmTelManagerRegistrationCallback);
892         when(mClientModeImpl.hasQuit()).thenReturn(true);
893         mClientModeManager.onClientModeImplQuit();
894         verify(mListener).onStopped(mClientModeManager);
895         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
896 
897         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
898 
899         // on an explicit stop, we should not trigger the callback
900         verifyNoMoreInteractions(mListener);
901     }
902 
903     /**
904      * ClientMode stop properly with IMS deferring time and Wifi calling.
905      *
906      * IMS deregistration is NOT done before reaching the timeout.
907      */
908     @Test
clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOut()909     public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOut()
910             throws Exception {
911         setUpVoWifiTest(true,
912                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
913 
914         startClientInConnectModeAndVerifyEnabled();
915         reset(mContext, mListener);
916         setUpSystemServiceForContext();
917         mClientModeManager.stop();
918         mLooper.dispatchAll();
919         verify(mImsMmTelManager).registerImsRegistrationCallback(
920                 any(Executor.class),
921                 any(RegistrationManager.RegistrationCallback.class));
922         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
923         when(mClientModeImpl.hasQuit()).thenReturn(true);
924         mClientModeManager.onClientModeImplQuit();
925         verify(mListener, never()).onStopped(any());
926 
927         // 1/2 deferring time passed, should be still waiting for the callback.
928         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2);
929         mLooper.dispatchAll();
930         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
931         verify(mListener, never()).onStopped(any());
932         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
933 
934         // Exceeding the timeout, wifi should be stopped.
935         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2 + 1000);
936         mLooper.dispatchAll();
937         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
938                 any(RegistrationManager.RegistrationCallback.class));
939         assertNull(mImsMmTelManagerRegistrationCallback);
940         when(mClientModeImpl.hasQuit()).thenReturn(true);
941         mClientModeManager.onClientModeImplQuit();
942         verify(mListener).onStopped(mClientModeManager);
943         verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt());
944 
945         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
946 
947         // on an explicit stop, we should not trigger the callback
948         verifyNoMoreInteractions(mListener);
949     }
950 
951     /**
952      * ClientMode stop properly with IMS deferring time and Wifi calling.
953      *
954      * IMS deregistration is NOT done before reaching the timeout with multiple stop calls.
955      */
956     @Test
clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleStop()957     public void clientModeStopWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleStop()
958             throws Exception {
959         setUpVoWifiTest(true,
960                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
961 
962         startClientInConnectModeAndVerifyEnabled();
963         reset(mContext, mListener);
964         setUpSystemServiceForContext();
965         mClientModeManager.stop();
966         mLooper.dispatchAll();
967         verify(mImsMmTelManager).registerImsRegistrationCallback(
968                 any(Executor.class),
969                 any(RegistrationManager.RegistrationCallback.class));
970         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
971         verify(mListener, never()).onStopped(any());
972 
973         mClientModeManager.stop();
974         mLooper.dispatchAll();
975         // should not register another listener.
976         verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback(
977                 any(Executor.class),
978                 any(RegistrationManager.RegistrationCallback.class));
979         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
980         verify(mListener, never()).onStopped(any());
981         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
982 
983         // Exceeding the timeout, wifi should be stopped.
984         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000);
985         mLooper.dispatchAll();
986         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
987                 any(RegistrationManager.RegistrationCallback.class));
988         assertNull(mImsMmTelManagerRegistrationCallback);
989         when(mClientModeImpl.hasQuit()).thenReturn(true);
990         mClientModeManager.onClientModeImplQuit();
991         verify(mListener).onStopped(mClientModeManager);
992         verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt());
993 
994         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
995 
996         // on an explicit stop, we should not trigger the callback
997         verifyNoMoreInteractions(mListener);
998     }
999 
1000     /**
1001      * Switch to scan mode properly with IMS deferring time without WifiCalling.
1002      */
1003     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeNoWifiCalling()1004     public void switchToScanOnlyModeWithWifiOffDeferringTimeNoWifiCalling() throws Exception {
1005         setUpVoWifiTest(false,
1006                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1007 
1008         startClientInConnectModeAndVerifyEnabled();
1009         reset(mContext, mListener);
1010         setUpSystemServiceForContext();
1011         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1012                 .thenReturn(true);
1013 
1014         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1015         mLooper.dispatchAll();
1016 
1017         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1018         verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any());
1019         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1020         verify(mWifiMetrics).noteWifiOff(eq(false), eq(false), anyInt());
1021     }
1022 
1023     /**
1024      * Switch to scan mode properly with IMS deferring time and IMS is registered on WWAN.
1025      */
1026     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeAndImsOnWwan()1027     public void switchToScanOnlyModeWithWifiOffDeferringTimeAndImsOnWwan() throws Exception {
1028         setUpVoWifiTest(true,
1029                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1030         mCurrentImsConnectionType = AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
1031 
1032         startClientInConnectModeAndVerifyEnabled();
1033         reset(mContext, mListener);
1034         setUpSystemServiceForContext();
1035         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1036                 .thenReturn(true);
1037 
1038         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1039         mLooper.dispatchAll();
1040 
1041         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1042 
1043         verify(mImsMmTelManager).registerImsRegistrationCallback(
1044                 any(Executor.class),
1045                 any(RegistrationManager.RegistrationCallback.class));
1046         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1047                 any(RegistrationManager.RegistrationCallback.class));
1048         assertNull(mImsMmTelManagerRegistrationCallback);
1049         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
1050     }
1051 
1052     /**
1053      * Switch to scan mode properly with IMS deferring time and Wifi calling.
1054      *
1055      * IMS deregistration is done before reaching the timeout.
1056      */
1057     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsUnregistered()1058     public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsUnregistered()
1059             throws Exception {
1060         setUpVoWifiTest(true,
1061                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1062 
1063         startClientInConnectModeAndVerifyEnabled();
1064         reset(mContext, mListener);
1065         setUpSystemServiceForContext();
1066         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1067                 .thenReturn(true);
1068 
1069         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1070         mLooper.dispatchAll();
1071 
1072         // Not yet finish IMS deregistration.
1073         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1074         verify(mImsMmTelManager).registerImsRegistrationCallback(
1075                 any(Executor.class),
1076                 any(RegistrationManager.RegistrationCallback.class));
1077         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1078         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1079 
1080         // Notify wifi service IMS service is de-registered.
1081         assertNotNull(mImsMmTelManagerRegistrationCallback);
1082         mImsMmTelManagerRegistrationCallback.onUnregistered(null);
1083         assertNotNull(mImsNetworkCallback);
1084         mImsNetworkCallback.onLost(null);
1085         mLooper.dispatchAll();
1086 
1087         // Now Wifi could be switched to scan mode actually.
1088         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1089         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1090                 any(RegistrationManager.RegistrationCallback.class));
1091         assertNull(mImsMmTelManagerRegistrationCallback);
1092         assertNull(mImsNetworkCallback);
1093         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
1094     }
1095 
1096     /**
1097      * Switch to scan mode properly with IMS deferring time and Wifi calling.
1098      *
1099      * Network lost before IMS deregistration is done. The wifi should be still available
1100      * until IMS is de-registered or time out.
1101      */
1102     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnNetworkLostFirst()1103     public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnNetworkLostFirst()
1104             throws Exception {
1105         setUpVoWifiTest(true,
1106                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1107 
1108         startClientInConnectModeAndVerifyEnabled();
1109         reset(mContext, mListener);
1110         setUpSystemServiceForContext();
1111         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1112                 .thenReturn(true);
1113 
1114         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1115         mLooper.dispatchAll();
1116 
1117         // Not yet finish IMS deregistration.
1118         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1119         verify(mImsMmTelManager).registerImsRegistrationCallback(
1120                 any(Executor.class),
1121                 any(RegistrationManager.RegistrationCallback.class));
1122         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1123         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1124 
1125         // Notify wifi service network lost
1126         assertNotNull(mImsNetworkCallback);
1127         mImsNetworkCallback.onLost(null);
1128         mLooper.dispatchAll();
1129 
1130         // Since IMS service is not de-registered yet, wifi should be available.
1131         moveTimeForward(1000);
1132         mLooper.dispatchAll();
1133         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1134         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1135         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1136 
1137         // Notify wifi service IMS service is de-registered.
1138         assertNotNull(mImsMmTelManagerRegistrationCallback);
1139         mImsMmTelManagerRegistrationCallback.onUnregistered(null);
1140         mLooper.dispatchAll();
1141 
1142         // Now Wifi could be switched to scan mode actually.
1143         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1144         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1145                 any(RegistrationManager.RegistrationCallback.class));
1146         assertNull(mImsMmTelManagerRegistrationCallback);
1147         assertNull(mImsNetworkCallback);
1148         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
1149     }
1150 
1151     /**
1152      * Switch to scan mode properly with IMS deferring time and Wifi calling.
1153      *
1154      * IMS deregistration is done before reaching the timeout.
1155      */
1156     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered()1157     public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingOnImsRegistered()
1158             throws Exception {
1159         setUpVoWifiTest(true,
1160                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1161 
1162         startClientInConnectModeAndVerifyEnabled();
1163         reset(mContext, mListener);
1164         setUpSystemServiceForContext();
1165         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1166                 .thenReturn(true);
1167 
1168         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1169         mLooper.dispatchAll();
1170 
1171         // Not yet finish IMS deregistration.
1172         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1173         verify(mImsMmTelManager).registerImsRegistrationCallback(
1174                 any(Executor.class),
1175                 any(RegistrationManager.RegistrationCallback.class));
1176         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1177         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1178 
1179         // Notify wifi service IMS service is de-registered.
1180         assertNotNull(mImsMmTelManagerRegistrationCallback);
1181         mImsMmTelManagerRegistrationCallback.onRegistered(0);
1182         mLooper.dispatchAll();
1183 
1184         // Now Wifi could be switched to scan mode actually.
1185         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1186         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1187                 any(RegistrationManager.RegistrationCallback.class));
1188         assertNull(mImsMmTelManagerRegistrationCallback);
1189         verify(mWifiMetrics).noteWifiOff(eq(true), eq(false), anyInt());
1190     }
1191 
1192     /**
1193      * Switch to scan mode properly with IMS deferring time and Wifi calling.
1194      *
1195      * IMS deregistration is NOT done before reaching the timeout.
1196      */
1197     @Test
switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOut()1198     public void switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOut()
1199             throws Exception {
1200         setUpVoWifiTest(true,
1201                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1202 
1203         startClientInConnectModeAndVerifyEnabled();
1204         reset(mContext, mListener);
1205         setUpSystemServiceForContext();
1206         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1207                 .thenReturn(true);
1208 
1209         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1210         mLooper.dispatchAll();
1211 
1212         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1213         verify(mImsMmTelManager).registerImsRegistrationCallback(
1214                 any(Executor.class),
1215                 any(RegistrationManager.RegistrationCallback.class));
1216         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1217 
1218         // 1/2 deferring time passed, should be still waiting for the callback.
1219         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2);
1220         mLooper.dispatchAll();
1221         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1222         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1223         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1224 
1225         // Exceeding the timeout, wifi should be stopped.
1226         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS / 2 + 1000);
1227         mLooper.dispatchAll();
1228         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1229         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1230                 any(RegistrationManager.RegistrationCallback.class));
1231         assertNull(mImsMmTelManagerRegistrationCallback);
1232         verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt());
1233     }
1234 
1235     /**
1236      * Switch to scan mode properly with IMS deferring time and Wifi calling.
1237      *
1238      * IMS deregistration is NOT done before reaching the timeout with multiple stop calls.
1239      */
1240     @Test
1241     public void
switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch()1242             switchToScanOnlyModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch()
1243             throws Exception {
1244         setUpVoWifiTest(true,
1245                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1246 
1247         startClientInConnectModeAndVerifyEnabled();
1248         reset(mContext, mListener);
1249         setUpSystemServiceForContext();
1250         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1251                 .thenReturn(true);
1252 
1253         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1254         mLooper.dispatchAll();
1255 
1256         verify(mImsMmTelManager).registerImsRegistrationCallback(
1257                 any(Executor.class),
1258                 any(RegistrationManager.RegistrationCallback.class));
1259         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1260 
1261         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1262         mLooper.dispatchAll();
1263         // should not register another listener.
1264         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1265         verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback(
1266                 any(Executor.class),
1267                 any(RegistrationManager.RegistrationCallback.class));
1268         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1269         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1270 
1271         // Exceeding the timeout, wifi should be stopped.
1272         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000);
1273         mLooper.dispatchAll();
1274         verify(mWifiNative).switchClientInterfaceToScanMode(TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1275         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1276                 any(RegistrationManager.RegistrationCallback.class));
1277         assertNull(mImsMmTelManagerRegistrationCallback);
1278         verify(mWifiMetrics).noteWifiOff(eq(true), eq(true), anyInt());
1279     }
1280 
1281     /**
1282      * Stay at connected mode with IMS deferring time and Wifi calling
1283      * when the target state is not ROLE_CLIENT_SCAN_ONLY.
1284      *
1285      * Simulate a user toggle wifi multiple times before doing wifi stop and stay at
1286      * ON position.
1287      */
1288     @Test
1289     public void
stayAtConnectedModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch()1290             stayAtConnectedModeWithWifiOffDeferringTimeAndWifiCallingTimedOutMultipleSwitch()
1291             throws Exception {
1292         setUpVoWifiTest(true,
1293                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1294 
1295         startClientInConnectModeAndVerifyEnabled();
1296         reset(mContext, mListener);
1297         setUpSystemServiceForContext();
1298         when(mWifiNative.switchClientInterfaceToScanMode(any(), any()))
1299                 .thenReturn(true);
1300 
1301         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1302         mLooper.dispatchAll();
1303         mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
1304         mLooper.dispatchAll();
1305         mClientModeManager.setRole(ROLE_CLIENT_SCAN_ONLY, TEST_WORKSOURCE);
1306         mLooper.dispatchAll();
1307         mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
1308         mLooper.dispatchAll();
1309 
1310         verify(mImsMmTelManager).registerImsRegistrationCallback(
1311                 any(Executor.class),
1312                 any(RegistrationManager.RegistrationCallback.class));
1313         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1314 
1315         // should not register another listener.
1316         verify(mWifiNative, never()).switchClientInterfaceToScanMode(any(), any());
1317         verify(mImsMmTelManager, times(1)).registerImsRegistrationCallback(
1318                 any(Executor.class),
1319                 any(RegistrationManager.RegistrationCallback.class));
1320         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1321         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1322 
1323         // Exceeding the timeout, wifi should NOT be stopped.
1324         moveTimeForward(TEST_WIFI_OFF_DEFERRING_TIME_MS + 1000);
1325         mLooper.dispatchAll();
1326         verify(mWifiNative, never()).switchClientInterfaceToScanMode(
1327                 TEST_INTERFACE_NAME, TEST_WORKSOURCE);
1328         verify(mImsMmTelManager).unregisterImsRegistrationCallback(
1329                 any(RegistrationManager.RegistrationCallback.class));
1330         assertNull(mImsMmTelManagerRegistrationCallback);
1331         verify(mWifiMetrics, never()).noteWifiOff(anyBoolean(), anyBoolean(), anyInt());
1332     }
1333 
1334     /**
1335      * ClientMode stop properly with IMS deferring time without WifiCalling.
1336      */
1337     @Test
clientModeStopWithImsManagerException()1338     public void clientModeStopWithImsManagerException() throws Exception {
1339         setUpVoWifiTest(true,
1340                 TEST_WIFI_OFF_DEFERRING_TIME_MS);
1341         when(mImsMmTelManager.isAvailable(anyInt(), anyInt()))
1342                 .thenThrow(new RuntimeException("Test Runtime Exception"));
1343 
1344         startClientInConnectModeAndVerifyEnabled();
1345         reset(mContext, mListener);
1346         setUpSystemServiceForContext();
1347         mClientModeManager.stop();
1348         mLooper.dispatchAll();
1349         when(mClientModeImpl.hasQuit()).thenReturn(true);
1350         mClientModeManager.onClientModeImplQuit();
1351         verify(mListener).onStopped(mClientModeManager);
1352 
1353         verifyConnectModeNotificationsForCleanShutdown(WIFI_STATE_ENABLED);
1354 
1355         verify(mImsMmTelManager, never()).registerImsRegistrationCallback(any(), any());
1356         verify(mImsMmTelManager, never()).unregisterImsRegistrationCallback(any());
1357         verify(mWifiMetrics).noteWifiOff(eq(false), eq(false), anyInt());
1358 
1359         // on an explicit stop, we should not trigger the callback
1360         verifyNoMoreInteractions(mListener);
1361     }
1362 
1363     /**
1364      * ClientMode starts up in connect mode and then change connectivity roles.
1365      */
1366     @Test
clientInConnectModeChangeRoles()1367     public void clientInConnectModeChangeRoles() throws Exception {
1368         startClientInConnectModeAndVerifyEnabled();
1369         reset(mListener);
1370 
1371         // Set the same role again, no-op.
1372         assertEquals(ActiveModeManager.ROLE_CLIENT_PRIMARY, mClientModeManager.getRole());
1373         mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
1374         mLooper.dispatchAll();
1375         verify(mWifiNative).replaceStaIfaceRequestorWs(
1376                 eq(TEST_INTERFACE_NAME), same(TEST_WORKSOURCE));
1377         verify(mListener, never()).onRoleChanged(any()); // no callback sent.
1378 
1379         // Change the connectivity role.
1380         ActiveModeManager.Listener<ConcreteClientModeManager> newListener =
1381                 mock(ActiveModeManager.Listener.class);
1382         mClientModeManager.setRole(
1383                 ActiveModeManager.ROLE_CLIENT_SECONDARY_TRANSIENT, TEST_WORKSOURCE, newListener);
1384         mLooper.dispatchAll();
1385         verify(mWifiNative, times(2)).replaceStaIfaceRequestorWs(
1386                 eq(TEST_INTERFACE_NAME), same(TEST_WORKSOURCE));
1387         verify(newListener).onRoleChanged(mClientModeManager); // callback sent on new listener.
1388         verifyNoMoreInteractions(mListener); // no callback sent on older listener.
1389     }
1390 
1391     @Test
clientInConnectModeChangeRolesNewWorkSource_WifiNativeFailed_noCallback()1392     public void clientInConnectModeChangeRolesNewWorkSource_WifiNativeFailed_noCallback()
1393             throws Exception {
1394         startClientInConnectModeAndVerifyEnabled();
1395         reset(mListener);
1396 
1397         when(mWifiNative.replaceStaIfaceRequestorWs(TEST_INTERFACE_NAME, TEST_WORKSOURCE2))
1398                 .thenReturn(false);
1399 
1400         // set new mode with new WorkSource
1401         mClientModeManager.setRole(ROLE_CLIENT_SECONDARY_TRANSIENT, TEST_WORKSOURCE2);
1402         mLooper.dispatchAll();
1403 
1404         verify(mWifiNative).replaceStaIfaceRequestorWs(
1405                 eq(TEST_INTERFACE_NAME), same(TEST_WORKSOURCE2));
1406         // no callback sent since replaceStaIfaceRequestorWs failed
1407         verify(mListener, never()).onRoleChanged(any());
1408     }
1409 
1410     @Test
setRoleBeforeInvokingListener()1411     public void setRoleBeforeInvokingListener() throws Exception {
1412         when(mWifiNative.setupInterfaceForClientInScanMode(any(), any()))
1413                 .thenReturn(TEST_INTERFACE_NAME);
1414         when(mWifiNative.switchClientInterfaceToConnectivityMode(any(), any()))
1415                 .thenReturn(true);
1416 
1417         doAnswer(new AnswerWithArguments() {
1418             public void answer(ActiveModeManager clientModeManager) throws Exception {
1419                 assertEquals(ROLE_CLIENT_SCAN_ONLY, clientModeManager.getRole());
1420             }
1421         }).when(mListener).onStarted(mClientModeManager);
1422         mClientModeManager = createClientModeManager(ROLE_CLIENT_SCAN_ONLY);
1423         mLooper.dispatchAll();
1424 
1425         ActiveModeManager.ClientRole lastRole = mClientModeManager.getRole();
1426         assertEquals(ROLE_CLIENT_SCAN_ONLY, lastRole);
1427         assertNull(mClientModeManager.getPreviousRole());
1428 
1429         verify(mWifiNative).setupInterfaceForClientInScanMode(
1430                 mInterfaceCallbackCaptor.capture(), eq(TEST_WORKSOURCE));
1431         mInterfaceCallbackCaptor.getValue().onUp(TEST_INTERFACE_NAME);
1432         mLooper.dispatchAll();
1433         verify(mListener).onStarted(mClientModeManager); // callback sent.
1434 
1435         // Change to connectivity role.
1436         long testChangeRoleTimestamp = 12234455L;
1437         when(mClock.getElapsedSinceBootMillis()).thenReturn(testChangeRoleTimestamp);
1438         doAnswer(new AnswerWithArguments() {
1439             public void answer(ActiveModeManager clientModeManager) throws Exception {
1440                 assertEquals(ActiveModeManager.ROLE_CLIENT_PRIMARY, clientModeManager.getRole());
1441             }
1442         }).when(mListener).onRoleChanged(mClientModeManager);
1443         mClientModeManager.setRole(ActiveModeManager.ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
1444         mLooper.dispatchAll();
1445         verify(mListener).onRoleChanged(mClientModeManager); // callback sent.
1446 
1447         // Verify the role is changed and previousRole is updated.
1448         assertEquals("Should equal previous role", lastRole,
1449                 mClientModeManager.getPreviousRole());
1450         assertEquals("The role change timestamp should match", testChangeRoleTimestamp,
1451                 mClientModeManager.getLastRoleChangeSinceBootMs());
1452     }
1453 
1454     @Test
propagateSettingsToClientModeImpl()1455     public void propagateSettingsToClientModeImpl() throws Exception {
1456         startClientInConnectModeAndVerifyEnabled();
1457         verify(mWifiInjector).makeClientModeImpl(any(), any(), eq(false));
1458         verify(mClientModeImpl).setShouldReduceNetworkScore(false);
1459 
1460         mClientModeManager.enableVerboseLogging(true);
1461         verify(mClientModeImpl).enableVerboseLogging(true);
1462 
1463         mClientModeManager.enableVerboseLogging(false);
1464         verify(mClientModeImpl).enableVerboseLogging(false);
1465 
1466         mClientModeManager.setShouldReduceNetworkScore(true);
1467         verify(mClientModeImpl).setShouldReduceNetworkScore(true);
1468 
1469         mClientModeManager.setShouldReduceNetworkScore(false);
1470         verify(mClientModeImpl, times(2)).setShouldReduceNetworkScore(false);
1471     }
1472 
1473     @Test
propagateConnectedWifiScorerToPrimaryClientModeImpl()1474     public void propagateConnectedWifiScorerToPrimaryClientModeImpl() throws Exception {
1475         startClientInConnectModeAndVerifyEnabled();
1476 
1477         IBinder iBinder = mock(IBinder.class);
1478         IWifiConnectedNetworkScorer iScorer = mock(IWifiConnectedNetworkScorer.class);
1479         mClientModeManager.setWifiConnectedNetworkScorer(iBinder, iScorer);
1480         verify(mClientModeImpl).setWifiConnectedNetworkScorer(iBinder, iScorer);
1481 
1482         mClientModeManager.clearWifiConnectedNetworkScorer();
1483         verify(mClientModeImpl).clearWifiConnectedNetworkScorer();
1484 
1485         mClientModeManager.setWifiConnectedNetworkScorer(iBinder, iScorer);
1486         verify(mClientModeImpl, times(2)).setWifiConnectedNetworkScorer(iBinder, iScorer);
1487     }
1488 
1489     @Test
updateConnectModeStateInAllRoles()1490     public void updateConnectModeStateInAllRoles() throws Exception {
1491         startClientInConnectModeAndVerifyEnabled();
1492         mClientModeManager.setRole(ROLE_CLIENT_SECONDARY_TRANSIENT, TEST_WORKSOURCE);
1493         mLooper.dispatchAll();
1494         mClientModeManager.stop();
1495         // disabling broadcast wasn't sent out (since role is secondary)
1496         verify(mContext, never()).sendStickyBroadcastAsUser(
1497                 argThat(intent ->
1498                         intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, -1)
1499                                 == WifiManager.WIFI_STATE_DISABLING),
1500                 any());
1501         // but wifi state was updated (should be updated no matter the role)
1502         assertEquals(WifiManager.WIFI_STATE_DISABLING, mClientModeManager.syncGetWifiState());
1503     }
1504 
1505     @Test
changeRoleResetsSettings()1506     public void changeRoleResetsSettings() throws Exception {
1507         startClientInConnectModeAndVerifyEnabled();
1508 
1509         verify(mClientModeImpl).setShouldReduceNetworkScore(false);
1510 
1511         mClientModeManager.setRole(ROLE_CLIENT_SECONDARY_TRANSIENT, TEST_WORKSOURCE);
1512         mLooper.dispatchAll();
1513 
1514         // reset upon role change
1515         verify(mClientModeImpl, times(2)).setShouldReduceNetworkScore(false);
1516     }
1517 
1518     @Test
sameRoleDoesntResetsSettings()1519     public void sameRoleDoesntResetsSettings() throws Exception {
1520         startClientInConnectModeAndVerifyEnabled();
1521 
1522         verify(mClientModeImpl).setShouldReduceNetworkScore(false);
1523 
1524         mClientModeManager.setRole(ROLE_CLIENT_PRIMARY, TEST_WORKSOURCE);
1525         mLooper.dispatchAll();
1526 
1527         // no role change, no reset
1528         verify(mClientModeImpl).setShouldReduceNetworkScore(false);
1529     }
1530 }
1531