1 /*
2  * Copyright (C) 2017 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 android.net.wifi;
18 
19 import static android.net.wifi.WifiConfiguration.METERED_OVERRIDE_METERED;
20 import static android.net.wifi.WifiManager.ActionListener;
21 import static android.net.wifi.WifiManager.BUSY;
22 import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP;
23 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE;
24 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT;
25 import static android.net.wifi.WifiManager.ERROR;
26 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
27 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
28 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
29 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
30 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
31 import static android.net.wifi.WifiManager.NOT_AUTHORIZED;
32 import static android.net.wifi.WifiManager.OnWifiActivityEnergyInfoListener;
33 import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
34 import static android.net.wifi.WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS;
35 import static android.net.wifi.WifiManager.STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
36 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
37 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
38 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
39 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY;
40 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB;
41 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED;
42 import static android.net.wifi.WifiManager.WIFI_FEATURE_AP_STA;
43 import static android.net.wifi.WifiManager.WIFI_FEATURE_DECORATED_IDENTITY;
44 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
45 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER;
46 import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
47 import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P;
48 import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT;
49 import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS;
50 import static android.net.wifi.WifiManager.WIFI_FEATURE_SCANNER;
51 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
52 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
53 import static android.net.wifi.WifiManager.WpsCallback;
54 
55 import static org.junit.Assert.assertArrayEquals;
56 import static org.junit.Assert.assertEquals;
57 import static org.junit.Assert.assertFalse;
58 import static org.junit.Assert.assertNotNull;
59 import static org.junit.Assert.assertNull;
60 import static org.junit.Assert.assertTrue;
61 import static org.junit.Assert.fail;
62 import static org.junit.Assume.assumeTrue;
63 import static org.mockito.ArgumentMatchers.anyBoolean;
64 import static org.mockito.ArgumentMatchers.nullable;
65 import static org.mockito.Mockito.any;
66 import static org.mockito.Mockito.anyInt;
67 import static org.mockito.Mockito.anyList;
68 import static org.mockito.Mockito.anyString;
69 import static org.mockito.Mockito.argThat;
70 import static org.mockito.Mockito.doThrow;
71 import static org.mockito.Mockito.eq;
72 import static org.mockito.Mockito.inOrder;
73 import static org.mockito.Mockito.mock;
74 import static org.mockito.Mockito.never;
75 import static org.mockito.Mockito.reset;
76 import static org.mockito.Mockito.spy;
77 import static org.mockito.Mockito.times;
78 import static org.mockito.Mockito.verify;
79 import static org.mockito.Mockito.verifyNoMoreInteractions;
80 import static org.mockito.Mockito.verifyZeroInteractions;
81 import static org.mockito.Mockito.when;
82 
83 import android.annotation.NonNull;
84 import android.app.ActivityManager;
85 import android.content.Context;
86 import android.content.pm.ApplicationInfo;
87 import android.net.DhcpInfo;
88 import android.net.MacAddress;
89 import android.net.wifi.WifiManager.CoexCallback;
90 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
91 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
92 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
93 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
94 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
95 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
96 import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
97 import android.net.wifi.WifiManager.ScanResultsCallback;
98 import android.net.wifi.WifiManager.SoftApCallback;
99 import android.net.wifi.WifiManager.SubsystemRestartTrackingCallback;
100 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener;
101 import android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener;
102 import android.net.wifi.WifiManager.TrafficStateCallback;
103 import android.net.wifi.WifiManager.WifiConnectedNetworkScorer;
104 import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats;
105 import android.net.wifi.WifiUsabilityStatsEntry.RadioStats;
106 import android.net.wifi.WifiUsabilityStatsEntry.RateStats;
107 import android.os.Build;
108 import android.os.Handler;
109 import android.os.HandlerExecutor;
110 import android.os.IBinder;
111 import android.os.RemoteException;
112 import android.os.connectivity.WifiActivityEnergyInfo;
113 import android.os.test.TestLooper;
114 import android.util.SparseArray;
115 
116 import androidx.test.filters.SmallTest;
117 
118 import com.android.modules.utils.build.SdkLevel;
119 
120 import org.junit.Before;
121 import org.junit.Test;
122 import org.mockito.ArgumentCaptor;
123 import org.mockito.InOrder;
124 import org.mockito.Mock;
125 import org.mockito.Mockito;
126 import org.mockito.MockitoAnnotations;
127 
128 import java.util.ArrayList;
129 import java.util.Collections;
130 import java.util.HashMap;
131 import java.util.List;
132 import java.util.Map;
133 import java.util.Objects;
134 import java.util.concurrent.Executor;
135 
136 /**
137  * Unit tests for {@link android.net.wifi.WifiManager}.
138  */
139 @SmallTest
140 public class WifiManagerTest {
141 
142     private static final int ERROR_NOT_SET = -1;
143     private static final int ERROR_TEST_REASON = 5;
144     private static final int TEST_UID = 14553;
145     private static final int TEST_NETWORK_ID = 143;
146     private static final String TEST_PACKAGE_NAME = "TestPackage";
147     private static final String TEST_FEATURE_ID = "TestFeature";
148     private static final String TEST_COUNTRY_CODE = "US";
149     private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
150     private static final int TEST_SUB_ID = 3;
151     private static final String[] TEST_AP_INSTANCES = new String[] {"wlan1", "wlan2"};
152     private static final int[] TEST_AP_FREQS = new int[] {2412, 5220};
153     private static final int[] TEST_AP_BWS = new int[] {SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT,
154             SoftApInfo.CHANNEL_WIDTH_80MHZ};
155     private static final MacAddress[] TEST_AP_BSSIDS = new MacAddress[] {
156             MacAddress.fromString("22:33:44:55:66:77"),
157             MacAddress.fromString("aa:bb:cc:dd:ee:ff")};
158     private static final MacAddress[] TEST_AP_CLIENTS = new MacAddress[] {
159             MacAddress.fromString("22:33:44:aa:aa:77"),
160             MacAddress.fromString("aa:bb:cc:11:11:ff"),
161             MacAddress.fromString("22:bb:cc:11:aa:ff")};
162 
163     @Mock Context mContext;
164     @Mock android.net.wifi.IWifiManager mWifiService;
165     @Mock ApplicationInfo mApplicationInfo;
166     @Mock WifiConfiguration mApConfig;
167     @Mock SoftApCallback mSoftApCallback;
168     @Mock TrafficStateCallback mTrafficStateCallback;
169     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
170     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
171     @Mock OnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
172     @Mock SuggestionConnectionStatusListener mSuggestionConnectionListener;
173     @Mock Runnable mRunnable;
174     @Mock Executor mExecutor;
175     @Mock Executor mAnotherExecutor;
176     @Mock ActivityManager mActivityManager;
177     @Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
178     @Mock SuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener;
179 
180     private Handler mHandler;
181     private TestLooper mLooper;
182     private WifiManager mWifiManager;
183     private WifiNetworkSuggestion mWifiNetworkSuggestion;
184     private ScanResultsCallback mScanResultsCallback;
185     private CoexCallback mCoexCallback;
186     private SubsystemRestartTrackingCallback mRestartCallback;
187     private int mRestartCallbackMethodRun = 0; // 1: restarting, 2: restarted
188     private WifiActivityEnergyInfo mWifiActivityEnergyInfo;
189 
190     private HashMap<String, SoftApInfo> mTestSoftApInfoMap = new HashMap<>();
191     private HashMap<String, List<WifiClient>> mTestWifiClientsMap = new HashMap<>();
192     private SoftApInfo mTestApInfo1 = new SoftApInfo();
193     private SoftApInfo mTestApInfo2 = new SoftApInfo();
194 
195     /**
196      * Util function to check public field which used for softap  in WifiConfiguration
197      * same as the value in SoftApConfiguration.
198      *
199      */
compareWifiAndSoftApConfiguration( SoftApConfiguration softApConfig, WifiConfiguration wifiConfig)200     private boolean compareWifiAndSoftApConfiguration(
201             SoftApConfiguration softApConfig, WifiConfiguration wifiConfig) {
202         if (!Objects.equals(wifiConfig.SSID, softApConfig.getSsid())) {
203             return false;
204         }
205         if (!Objects.equals(wifiConfig.BSSID, softApConfig.getBssid())) {
206             return false;
207         }
208         if (!Objects.equals(wifiConfig.preSharedKey, softApConfig.getPassphrase())) {
209             return false;
210         }
211 
212         if (wifiConfig.hiddenSSID != softApConfig.isHiddenSsid()) {
213             return false;
214         }
215         switch (softApConfig.getSecurityType()) {
216             case SoftApConfiguration.SECURITY_TYPE_OPEN:
217                 if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.NONE) {
218                     return false;
219                 }
220                 break;
221             case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK:
222                 if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.WPA2_PSK) {
223                     return false;
224                 }
225                 break;
226             default:
227                 return false;
228         }
229         return true;
230     }
231 
generatorTestSoftApConfig()232     private SoftApConfiguration generatorTestSoftApConfig() {
233         return new SoftApConfiguration.Builder()
234                 .setSsid("TestSSID")
235                 .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
236                 .build();
237     }
238 
initTestInfoAndAddToTestMap(int numberOfInfos)239     private void initTestInfoAndAddToTestMap(int numberOfInfos) {
240         if (numberOfInfos > 2) return;
241         for (int i = 0; i < numberOfInfos; i++) {
242             SoftApInfo info = mTestApInfo1;
243             if (i == 1) info = mTestApInfo2;
244             info.setFrequency(TEST_AP_FREQS[i]);
245             info.setBandwidth(TEST_AP_BWS[i]);
246             info.setBssid(TEST_AP_BSSIDS[i]);
247             info.setApInstanceIdentifier(TEST_AP_INSTANCES[i]);
248             mTestSoftApInfoMap.put(TEST_AP_INSTANCES[i], info);
249         }
250     }
251 
initWifiClientAndAddToTestMap(String targetInstance, int numberOfClients, int startIdx)252     private List<WifiClient> initWifiClientAndAddToTestMap(String targetInstance,
253             int numberOfClients, int startIdx) {
254         if (numberOfClients > 3) return null;
255         List<WifiClient> clients = new ArrayList<>();
256         for (int i = startIdx; i < startIdx + numberOfClients; i++) {
257             WifiClient client = new WifiClient(TEST_AP_CLIENTS[i], targetInstance);
258             clients.add(client);
259         }
260         mTestWifiClientsMap.put(targetInstance, clients);
261         return clients;
262     }
263 
264     @Before
setUp()265     public void setUp() throws Exception {
266         MockitoAnnotations.initMocks(this);
267         mLooper = new TestLooper();
268         mHandler = spy(new Handler(mLooper.getLooper()));
269         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
270         when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
271         when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
272         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
273         verify(mWifiService).getVerboseLoggingLevel();
274         mWifiNetworkSuggestion = new WifiNetworkSuggestion();
275         mScanResultsCallback = new ScanResultsCallback() {
276             @Override
277             public void onScanResultsAvailable() {
278                 mRunnable.run();
279             }
280         };
281         if (SdkLevel.isAtLeastS()) {
282             mCoexCallback = new CoexCallback() {
283                 @Override
284                 public void onCoexUnsafeChannelsChanged(
285                         @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) {
286                     mRunnable.run();
287                 }
288             };
289         }
290         mRestartCallback = new SubsystemRestartTrackingCallback() {
291             @Override
292             public void onSubsystemRestarting() {
293                 mRestartCallbackMethodRun = 1;
294                 mRunnable.run();
295             }
296 
297             @Override
298             public void onSubsystemRestarted() {
299                 mRestartCallbackMethodRun = 2;
300                 mRunnable.run();
301             }
302         };
303         mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
304         mTestSoftApInfoMap.clear();
305         mTestWifiClientsMap.clear();
306     }
307 
308     /**
309      * Check the call to setCoexUnsafeChannels calls WifiServiceImpl to setCoexUnsafeChannels with
310      * the provided CoexUnsafeChannels and restrictions bitmask.
311      */
312     @Test
testSetCoexUnsafeChannelsGoesToWifiServiceImpl()313     public void testSetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception {
314         assumeTrue(SdkLevel.isAtLeastS());
315         List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
316         int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP
317                 | COEX_RESTRICTION_WIFI_AWARE;
318 
319         mWifiManager.setCoexUnsafeChannels(unsafeChannels, restrictions);
320 
321         verify(mWifiService).setCoexUnsafeChannels(unsafeChannels, restrictions);
322     }
323 
324     /**
325      * Verify an IllegalArgumentException if passed a null value for unsafeChannels.
326      */
327     @Test
testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels()328     public void testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels() {
329         assumeTrue(SdkLevel.isAtLeastS());
330         try {
331             mWifiManager.setCoexUnsafeChannels(null, 0);
332             fail("expected IllegalArgumentException");
333         } catch (IllegalArgumentException expected) {
334         }
335     }
336 
337     /**
338      * Verify an IllegalArgumentException is thrown if callback is not provided.
339      */
340     @Test(expected = IllegalArgumentException.class)
testRegisterCoexCallbackWithNullCallback()341     public void testRegisterCoexCallbackWithNullCallback() throws Exception {
342         assumeTrue(SdkLevel.isAtLeastS());
343         mWifiManager.registerCoexCallback(mExecutor, null);
344     }
345 
346     /**
347      * Verify an IllegalArgumentException is thrown if executor is not provided.
348      */
349     @Test(expected = IllegalArgumentException.class)
testRegisterCoexCallbackWithNullExecutor()350     public void testRegisterCoexCallbackWithNullExecutor() throws Exception {
351         assumeTrue(SdkLevel.isAtLeastS());
352         mWifiManager.registerCoexCallback(null, mCoexCallback);
353     }
354 
355     /**
356      * Verify client provided callback is being called to the right callback.
357      */
358     @Test
testAddCoexCallbackAndReceiveEvent()359     public void testAddCoexCallbackAndReceiveEvent() throws Exception {
360         assumeTrue(SdkLevel.isAtLeastS());
361         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
362                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
363         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
364         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
365         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
366         verify(mRunnable).run();
367     }
368 
369     /**
370      * Verify client provided callback is being called to the right executor.
371      */
372     @Test
testRegisterCoexCallbackWithTheTargetExecutor()373     public void testRegisterCoexCallbackWithTheTargetExecutor() throws Exception {
374         assumeTrue(SdkLevel.isAtLeastS());
375         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
376                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
377         mWifiManager.registerCoexCallback(mExecutor, mCoexCallback);
378         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
379         mWifiManager.registerCoexCallback(mAnotherExecutor, mCoexCallback);
380         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
381         verify(mExecutor, never()).execute(any(Runnable.class));
382         verify(mAnotherExecutor).execute(any(Runnable.class));
383     }
384 
385     /**
386      * Verify client register unregister then register again, to ensure callback still works.
387      */
388     @Test
testRegisterUnregisterThenRegisterAgainWithCoexCallback()389     public void testRegisterUnregisterThenRegisterAgainWithCoexCallback() throws Exception {
390         assumeTrue(SdkLevel.isAtLeastS());
391         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
392                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
393         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
394         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
395         mWifiManager.unregisterCoexCallback(mCoexCallback);
396         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
397         verify(mRunnable, never()).run();
398         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
399         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
400         verify(mRunnable).run();
401     }
402 
403     /**
404      * Verify client unregisterCoexCallback.
405      */
406     @Test
testUnregisterCoexCallback()407     public void testUnregisterCoexCallback() throws Exception {
408         assumeTrue(SdkLevel.isAtLeastS());
409         mWifiManager.unregisterCoexCallback(mCoexCallback);
410         verify(mWifiService).unregisterCoexCallback(any());
411     }
412 
413     /**
414      * Verify client unregisterCoexCallback with null callback will cause an exception.
415      */
416     @Test(expected = IllegalArgumentException.class)
testUnregisterCoexCallbackWithNullCallback()417     public void testUnregisterCoexCallbackWithNullCallback() throws Exception {
418         assumeTrue(SdkLevel.isAtLeastS());
419         mWifiManager.unregisterCoexCallback(null);
420     }
421 
422     /**
423      * Verify that call is passed to binder.
424      */
425     @Test
testRestartWifiSubsystem()426     public void testRestartWifiSubsystem() throws Exception {
427         assumeTrue(SdkLevel.isAtLeastS());
428         mWifiManager.restartWifiSubsystem();
429         verify(mWifiService).restartWifiSubsystem();
430     }
431 
432     /**
433      * Verify that can register a subsystem restart tracking callback and that calls are passed
434      * through when registered and blocked once unregistered.
435      */
436     @Test
testRegisterSubsystemRestartTrackingCallback()437     public void testRegisterSubsystemRestartTrackingCallback() throws Exception {
438         assumeTrue(SdkLevel.isAtLeastS());
439         mRestartCallbackMethodRun = 0; // none
440         ArgumentCaptor<ISubsystemRestartCallback.Stub> callbackCaptor =
441                 ArgumentCaptor.forClass(ISubsystemRestartCallback.Stub.class);
442         mWifiManager.registerSubsystemRestartTrackingCallback(new SynchronousExecutor(),
443                 mRestartCallback);
444         verify(mWifiService).registerSubsystemRestartCallback(callbackCaptor.capture());
445         mWifiManager.unregisterSubsystemRestartTrackingCallback(mRestartCallback);
446         verify(mWifiService).unregisterSubsystemRestartCallback(callbackCaptor.capture());
447         callbackCaptor.getValue().onSubsystemRestarting();
448         verify(mRunnable, never()).run();
449         mWifiManager.registerSubsystemRestartTrackingCallback(new SynchronousExecutor(),
450                 mRestartCallback);
451         callbackCaptor.getValue().onSubsystemRestarting();
452         assertEquals(mRestartCallbackMethodRun, 1); // restarting
453         callbackCaptor.getValue().onSubsystemRestarted();
454         verify(mRunnable, times(2)).run();
455         assertEquals(mRestartCallbackMethodRun, 2); // restarted
456     }
457 
458     /**
459      * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
460      * WifiConfiguration.  Verify that the return value is propagated to the caller.
461      */
462     @Test
testStartSoftApCallsServiceWithWifiConfig()463     public void testStartSoftApCallsServiceWithWifiConfig() throws Exception {
464         when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(true);
465         assertTrue(mWifiManager.startSoftAp(mApConfig));
466 
467         when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(false);
468         assertFalse(mWifiManager.startSoftAp(mApConfig));
469     }
470 
471     /**
472      * Check the call to startSoftAp calls WifiService to startSoftAp with a null config.  Verify
473      * that the return value is propagated to the caller.
474      */
475     @Test
testStartSoftApCallsServiceWithNullConfig()476     public void testStartSoftApCallsServiceWithNullConfig() throws Exception {
477         when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(true);
478         assertTrue(mWifiManager.startSoftAp(null));
479 
480         when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(false);
481         assertFalse(mWifiManager.startSoftAp(null));
482     }
483 
484     /**
485      * Check the call to stopSoftAp calls WifiService to stopSoftAp.
486      */
487     @Test
testStopSoftApCallsService()488     public void testStopSoftApCallsService() throws Exception {
489         when(mWifiService.stopSoftAp()).thenReturn(true);
490         assertTrue(mWifiManager.stopSoftAp());
491 
492         when(mWifiService.stopSoftAp()).thenReturn(false);
493         assertFalse(mWifiManager.stopSoftAp());
494     }
495 
496     /**
497      * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
498      * WifiConfiguration.  Verify that the return value is propagated to the caller.
499      */
500     @Test
testStartTetheredHotspotCallsServiceWithSoftApConfig()501     public void testStartTetheredHotspotCallsServiceWithSoftApConfig() throws Exception {
502         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
503         when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
504                 .thenReturn(true);
505         assertTrue(mWifiManager.startTetheredHotspot(softApConfig));
506 
507         when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
508                 .thenReturn(false);
509         assertFalse(mWifiManager.startTetheredHotspot(softApConfig));
510     }
511 
512     /**
513      * Check the call to startSoftAp calls WifiService to startSoftAp with a null config.  Verify
514      * that the return value is propagated to the caller.
515      */
516     @Test
testStartTetheredHotspotCallsServiceWithNullConfig()517     public void testStartTetheredHotspotCallsServiceWithNullConfig() throws Exception {
518         when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(true);
519         assertTrue(mWifiManager.startTetheredHotspot(null));
520 
521         when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(false);
522         assertFalse(mWifiManager.startTetheredHotspot(null));
523     }
524 
525     /**
526      * Test creation of a LocalOnlyHotspotReservation and verify that close properly calls
527      * WifiService.stopLocalOnlyHotspot.
528      */
529     @Test
testCreationAndCloseOfLocalOnlyHotspotReservation()530     public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
531         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
532         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
533         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
534                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
535         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
536 
537         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
538 
539         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
540         WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
541         assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
542 
543         callback.mRes.close();
544         verify(mWifiService).stopLocalOnlyHotspot();
545     }
546 
547     /**
548      * Verify stopLOHS is called when try-with-resources is used properly.
549      */
550     @Test
testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()551     public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()
552             throws Exception {
553         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
554         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
555         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
556                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
557         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
558 
559         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
560 
561         try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) {
562             assertEquals(softApConfig, res.getSoftApConfiguration());
563             WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
564             assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
565         }
566 
567         verify(mWifiService).stopLocalOnlyHotspot();
568     }
569 
570     /**
571      * Test creation of a LocalOnlyHotspotSubscription.
572      * TODO: when registrations are tracked, verify removal on close.
573      */
574     @Test
testCreationOfLocalOnlyHotspotSubscription()575     public void testCreationOfLocalOnlyHotspotSubscription() throws Exception {
576         try (WifiManager.LocalOnlyHotspotSubscription sub =
577                      mWifiManager.new LocalOnlyHotspotSubscription()) {
578             sub.close();
579         }
580     }
581 
582     public class TestLocalOnlyHotspotCallback extends LocalOnlyHotspotCallback {
583         public boolean mOnStartedCalled = false;
584         public boolean mOnStoppedCalled = false;
585         public int mFailureReason = -1;
586         public LocalOnlyHotspotReservation mRes = null;
587         public long mCallingThreadId = -1;
588 
589         @Override
onStarted(LocalOnlyHotspotReservation r)590         public void onStarted(LocalOnlyHotspotReservation r) {
591             mRes = r;
592             mOnStartedCalled = true;
593             mCallingThreadId = Thread.currentThread().getId();
594         }
595 
596         @Override
onStopped()597         public void onStopped() {
598             mOnStoppedCalled = true;
599             mCallingThreadId = Thread.currentThread().getId();
600         }
601 
602         @Override
onFailed(int reason)603         public void onFailed(int reason) {
604             mFailureReason = reason;
605             mCallingThreadId = Thread.currentThread().getId();
606         }
607     }
608 
609     /**
610      * Verify callback is properly plumbed when called.
611      */
612     @Test
testLocalOnlyHotspotCallback()613     public void testLocalOnlyHotspotCallback() {
614         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
615         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
616         assertFalse(callback.mOnStartedCalled);
617         assertFalse(callback.mOnStoppedCalled);
618         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
619         assertEquals(null, callback.mRes);
620 
621         // test onStarted
622         WifiManager.LocalOnlyHotspotReservation res =
623                 mWifiManager.new LocalOnlyHotspotReservation(softApConfig);
624         callback.onStarted(res);
625         assertEquals(res, callback.mRes);
626         assertTrue(callback.mOnStartedCalled);
627         assertFalse(callback.mOnStoppedCalled);
628         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
629 
630         // test onStopped
631         callback.onStopped();
632         assertEquals(res, callback.mRes);
633         assertTrue(callback.mOnStartedCalled);
634         assertTrue(callback.mOnStoppedCalled);
635         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
636 
637         // test onFailed
638         callback.onFailed(ERROR_TEST_REASON);
639         assertEquals(res, callback.mRes);
640         assertTrue(callback.mOnStartedCalled);
641         assertTrue(callback.mOnStoppedCalled);
642         assertEquals(ERROR_TEST_REASON, callback.mFailureReason);
643     }
644 
645     public class TestLocalOnlyHotspotObserver extends LocalOnlyHotspotObserver {
646         public boolean mOnRegistered = false;
647         public boolean mOnStartedCalled = false;
648         public boolean mOnStoppedCalled = false;
649         public SoftApConfiguration mConfig = null;
650         public LocalOnlyHotspotSubscription mSub = null;
651         public long mCallingThreadId = -1;
652 
653         @Override
onRegistered(LocalOnlyHotspotSubscription sub)654         public void onRegistered(LocalOnlyHotspotSubscription sub) {
655             mOnRegistered = true;
656             mSub = sub;
657             mCallingThreadId = Thread.currentThread().getId();
658         }
659 
660         @Override
onStarted(SoftApConfiguration config)661         public void onStarted(SoftApConfiguration config) {
662             mOnStartedCalled = true;
663             mConfig = config;
664             mCallingThreadId = Thread.currentThread().getId();
665         }
666 
667         @Override
onStopped()668         public void onStopped() {
669             mOnStoppedCalled = true;
670             mCallingThreadId = Thread.currentThread().getId();
671         }
672     }
673 
674     /**
675      * Verify observer is properly plumbed when called.
676      */
677     @Test
testLocalOnlyHotspotObserver()678     public void testLocalOnlyHotspotObserver() {
679         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
680         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
681         assertFalse(observer.mOnRegistered);
682         assertFalse(observer.mOnStartedCalled);
683         assertFalse(observer.mOnStoppedCalled);
684         assertEquals(null, observer.mConfig);
685         assertEquals(null, observer.mSub);
686 
687         WifiManager.LocalOnlyHotspotSubscription sub =
688                 mWifiManager.new LocalOnlyHotspotSubscription();
689         observer.onRegistered(sub);
690         assertTrue(observer.mOnRegistered);
691         assertFalse(observer.mOnStartedCalled);
692         assertFalse(observer.mOnStoppedCalled);
693         assertEquals(null, observer.mConfig);
694         assertEquals(sub, observer.mSub);
695 
696         observer.onStarted(softApConfig);
697         assertTrue(observer.mOnRegistered);
698         assertTrue(observer.mOnStartedCalled);
699         assertFalse(observer.mOnStoppedCalled);
700         assertEquals(softApConfig, observer.mConfig);
701         assertEquals(sub, observer.mSub);
702 
703         observer.onStopped();
704         assertTrue(observer.mOnRegistered);
705         assertTrue(observer.mOnStartedCalled);
706         assertTrue(observer.mOnStoppedCalled);
707         assertEquals(softApConfig, observer.mConfig);
708         assertEquals(sub, observer.mSub);
709     }
710 
711     /**
712      * Verify call to startLocalOnlyHotspot goes to WifiServiceImpl.
713      */
714     @Test
testStartLocalOnlyHotspot()715     public void testStartLocalOnlyHotspot() throws Exception {
716         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
717         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
718 
719         verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
720                 anyString(), nullable(String.class), eq(null));
721     }
722 
723     /**
724      * Verify a SecurityException is thrown for callers without proper permissions for
725      * startLocalOnlyHotspot.
726      */
727     @Test(expected = SecurityException.class)
testStartLocalOnlyHotspotThrowsSecurityException()728     public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception {
729         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
730         doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
731                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
732                 eq(null));
733         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
734     }
735 
736     /**
737      * Verify an IllegalStateException is thrown for callers that already have a pending request for
738      * startLocalOnlyHotspot.
739      */
740     @Test(expected = IllegalStateException.class)
testStartLocalOnlyHotspotThrowsIllegalStateException()741     public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
742         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
743         doThrow(new IllegalStateException()).when(mWifiService).startLocalOnlyHotspot(
744                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
745                 eq(null));
746         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
747     }
748 
749     /**
750      * Verify that the handler provided by the caller is used for the callbacks.
751      */
752     @Test
testCorrectLooperIsUsedForHandler()753     public void testCorrectLooperIsUsedForHandler() throws Exception {
754         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
755         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
756                 nullable(String.class), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
757         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
758         mLooper.dispatchAll();
759         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
760         verify(mContext, never()).getMainLooper();
761         verify(mContext, never()).getMainExecutor();
762     }
763 
764     /**
765      * Verify that the main looper's thread is used if a handler is not provided by the reqiestomg
766      * application.
767      */
768     @Test
testMainLooperIsUsedWhenHandlerNotProvided()769     public void testMainLooperIsUsedWhenHandlerNotProvided() throws Exception {
770         // record thread from looper.getThread and check ids.
771         TestLooper altLooper = new TestLooper();
772         when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
773         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
774         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
775                 nullable(String.class), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
776         mWifiManager.startLocalOnlyHotspot(callback, null);
777         altLooper.dispatchAll();
778         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
779         assertEquals(altLooper.getLooper().getThread().getId(), callback.mCallingThreadId);
780         verify(mContext).getMainExecutor();
781     }
782 
783     /**
784      * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED
785      * message from WifiServiceImpl.
786      */
787     @Test
testOnStartedIsCalledWithReservation()788     public void testOnStartedIsCalledWithReservation() throws Exception {
789         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
790         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
791         TestLooper callbackLooper = new TestLooper();
792         Handler callbackHandler = new Handler(callbackLooper.getLooper());
793         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
794                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
795         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
796                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
797         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
798         callbackLooper.dispatchAll();
799         mLooper.dispatchAll();
800         assertFalse(callback.mOnStartedCalled);
801         assertEquals(null, callback.mRes);
802         // now trigger the callback
803         internalCallback.getValue().onHotspotStarted(softApConfig);
804         mLooper.dispatchAll();
805         callbackLooper.dispatchAll();
806         assertTrue(callback.mOnStartedCalled);
807         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
808         WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
809         assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
810     }
811 
812     /**
813      * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED
814      * message from WifiServiceImpl when softap enabled with SAE security type.
815      */
816     @Test
testOnStartedIsCalledWithReservationAndSaeSoftApConfig()817     public void testOnStartedIsCalledWithReservationAndSaeSoftApConfig() throws Exception {
818         SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
819                 .setSsid("TestSSID")
820                 .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)
821                 .build();
822         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
823         TestLooper callbackLooper = new TestLooper();
824         Handler callbackHandler = new Handler(callbackLooper.getLooper());
825         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
826                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
827         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
828                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
829         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
830         callbackLooper.dispatchAll();
831         mLooper.dispatchAll();
832         assertFalse(callback.mOnStartedCalled);
833         assertEquals(null, callback.mRes);
834         // now trigger the callback
835         internalCallback.getValue().onHotspotStarted(softApConfig);
836         mLooper.dispatchAll();
837         callbackLooper.dispatchAll();
838         assertTrue(callback.mOnStartedCalled);
839         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
840         assertEquals(null, callback.mRes.getWifiConfiguration());
841     }
842 
843     /**
844      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_STARTED message with a null
845      * config.
846      */
847     @Test
testOnStartedIsCalledWithNullConfig()848     public void testOnStartedIsCalledWithNullConfig() throws Exception {
849         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
850         TestLooper callbackLooper = new TestLooper();
851         Handler callbackHandler = new Handler(callbackLooper.getLooper());
852         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
853                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
854         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
855                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
856         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
857         callbackLooper.dispatchAll();
858         mLooper.dispatchAll();
859         assertFalse(callback.mOnStartedCalled);
860         assertEquals(null, callback.mRes);
861         // now trigger the callback
862         internalCallback.getValue().onHotspotStarted(null);
863         mLooper.dispatchAll();
864         callbackLooper.dispatchAll();
865         assertFalse(callback.mOnStartedCalled);
866         assertEquals(ERROR_GENERIC, callback.mFailureReason);
867     }
868 
869     /**
870      * Verify onStopped is called if WifiServiceImpl sends a HOTSPOT_STOPPED message.
871      */
872     @Test
testOnStoppedIsCalled()873     public void testOnStoppedIsCalled() throws Exception {
874         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
875         TestLooper callbackLooper = new TestLooper();
876         Handler callbackHandler = new Handler(callbackLooper.getLooper());
877         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
878                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
879         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
880                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
881         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
882         callbackLooper.dispatchAll();
883         mLooper.dispatchAll();
884         assertFalse(callback.mOnStoppedCalled);
885         // now trigger the callback
886         internalCallback.getValue().onHotspotStopped();
887         mLooper.dispatchAll();
888         callbackLooper.dispatchAll();
889         assertTrue(callback.mOnStoppedCalled);
890     }
891 
892     /**
893      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_FAILED message.
894      */
895     @Test
testOnFailedIsCalled()896     public void testOnFailedIsCalled() throws Exception {
897         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
898         TestLooper callbackLooper = new TestLooper();
899         Handler callbackHandler = new Handler(callbackLooper.getLooper());
900         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
901                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
902         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
903                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
904         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
905         callbackLooper.dispatchAll();
906         mLooper.dispatchAll();
907         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
908         // now trigger the callback
909         internalCallback.getValue().onHotspotFailed(ERROR_NO_CHANNEL);
910         mLooper.dispatchAll();
911         callbackLooper.dispatchAll();
912         assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
913     }
914 
915     /**
916      * Verify callback triggered from startLocalOnlyHotspot with an incompatible mode failure.
917      */
918     @Test
testLocalOnlyHotspotCallbackFullOnIncompatibleMode()919     public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
920         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
921         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
922                 nullable(String.class), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
923         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
924         mLooper.dispatchAll();
925         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
926         assertFalse(callback.mOnStartedCalled);
927         assertFalse(callback.mOnStoppedCalled);
928         assertEquals(null, callback.mRes);
929     }
930 
931     /**
932      * Verify callback triggered from startLocalOnlyHotspot with a tethering disallowed failure.
933      */
934     @Test
testLocalOnlyHotspotCallbackFullOnTetheringDisallowed()935     public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
936         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
937         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
938                 nullable(String.class), eq(null))).thenReturn(ERROR_TETHERING_DISALLOWED);
939         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
940         mLooper.dispatchAll();
941         assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
942         assertFalse(callback.mOnStartedCalled);
943         assertFalse(callback.mOnStoppedCalled);
944         assertEquals(null, callback.mRes);
945     }
946 
947     /**
948      * Verify a SecurityException resulting from an application without necessary permissions will
949      * bubble up through the call to start LocalOnlyHotspot and will not trigger other callbacks.
950      */
951     @Test(expected = SecurityException.class)
testLocalOnlyHotspotCallbackFullOnSecurityException()952     public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception {
953         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
954         doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
955                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
956                 eq(null));
957         try {
958             mWifiManager.startLocalOnlyHotspot(callback, mHandler);
959         } catch (SecurityException e) {
960             assertEquals(ERROR_NOT_SET, callback.mFailureReason);
961             assertFalse(callback.mOnStartedCalled);
962             assertFalse(callback.mOnStoppedCalled);
963             assertEquals(null, callback.mRes);
964             throw e;
965         }
966 
967     }
968 
969     /**
970      * Verify the handler passed to startLocalOnlyHotspot is correctly used for callbacks when
971      * SoftApMode fails due to a underlying error.
972      */
973     @Test
testLocalOnlyHotspotCallbackFullOnNoChannelError()974     public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
975         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
976         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
977                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
978         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
979         mLooper.dispatchAll();
980         //assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
981         assertFalse(callback.mOnStartedCalled);
982         assertFalse(callback.mOnStoppedCalled);
983         assertEquals(null, callback.mRes);
984     }
985 
986     /**
987      * Verify that the call to cancel a LOHS request does call stopLOHS.
988      */
989     @Test
testCancelLocalOnlyHotspotRequestCallsStopOnWifiService()990     public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
991         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
992         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
993                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
994         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
995         mWifiManager.cancelLocalOnlyHotspotRequest();
996         verify(mWifiService).stopLocalOnlyHotspot();
997     }
998 
999     /**
1000      * Verify that we do not crash if cancelLocalOnlyHotspotRequest is called without an existing
1001      * callback stored.
1002      */
1003     @Test
testCancelLocalOnlyHotspotReturnsWithoutExistingRequest()1004     public void testCancelLocalOnlyHotspotReturnsWithoutExistingRequest() {
1005         mWifiManager.cancelLocalOnlyHotspotRequest();
1006     }
1007 
1008     /**
1009      * Verify that the callback is not triggered if the LOHS request was already cancelled.
1010      */
1011     @Test
testCallbackAfterLocalOnlyHotspotWasCancelled()1012     public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
1013         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1014         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1015                 nullable(String.class), eq(null))).thenReturn(REQUEST_REGISTERED);
1016         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1017         mWifiManager.cancelLocalOnlyHotspotRequest();
1018         verify(mWifiService).stopLocalOnlyHotspot();
1019         mLooper.dispatchAll();
1020         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
1021         assertFalse(callback.mOnStartedCalled);
1022         assertFalse(callback.mOnStoppedCalled);
1023         assertEquals(null, callback.mRes);
1024     }
1025 
1026     /**
1027      * Verify that calling cancel LOHS request does not crash if an error callback was already
1028      * handled.
1029      */
1030     @Test
testCancelAfterLocalOnlyHotspotCallbackTriggered()1031     public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
1032         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1033         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1034                 nullable(String.class), eq(null))).thenReturn(ERROR_INCOMPATIBLE_MODE);
1035         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1036         mLooper.dispatchAll();
1037         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
1038         assertFalse(callback.mOnStartedCalled);
1039         assertFalse(callback.mOnStoppedCalled);
1040         assertEquals(null, callback.mRes);
1041         mWifiManager.cancelLocalOnlyHotspotRequest();
1042         verify(mWifiService, never()).stopLocalOnlyHotspot();
1043     }
1044 
1045     @Test
testStartLocalOnlyHotspotForwardsCustomConfig()1046     public void testStartLocalOnlyHotspotForwardsCustomConfig() throws Exception {
1047         SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
1048                 .setSsid("customSsid")
1049                 .build();
1050         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1051         mWifiManager.startLocalOnlyHotspot(customConfig, mExecutor, callback);
1052         verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
1053                 anyString(), nullable(String.class), eq(customConfig));
1054     }
1055 
1056     /**
1057      * Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl.
1058      */
1059     @Test
testWatchLocalOnlyHotspot()1060     public void testWatchLocalOnlyHotspot() throws Exception {
1061         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1062 
1063         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1064         verify(mWifiService).startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1065     }
1066 
1067     /**
1068      * Verify a SecurityException is thrown for callers without proper permissions for
1069      * startWatchLocalOnlyHotspot.
1070      */
1071     @Test(expected = SecurityException.class)
testStartWatchLocalOnlyHotspotThrowsSecurityException()1072     public void testStartWatchLocalOnlyHotspotThrowsSecurityException() throws Exception {
1073         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1074         doThrow(new SecurityException()).when(mWifiService)
1075                 .startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1076         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1077     }
1078 
1079     /**
1080      * Verify an IllegalStateException is thrown for callers that already have a pending request for
1081      * watchLocalOnlyHotspot.
1082      */
1083     @Test(expected = IllegalStateException.class)
testStartWatchLocalOnlyHotspotThrowsIllegalStateException()1084     public void testStartWatchLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
1085         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1086         doThrow(new IllegalStateException()).when(mWifiService)
1087                 .startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1088         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1089     }
1090 
1091     /**
1092      * Verify an IllegalArgumentException is thrown if a callback or executor is not provided.
1093      */
1094     @Test
testAddWifiVerboseLoggingStatusChangedListenerIllegalArguments()1095     public void testAddWifiVerboseLoggingStatusChangedListenerIllegalArguments() throws Exception {
1096         try {
1097             mWifiManager.addWifiVerboseLoggingStatusChangedListener(
1098                     new HandlerExecutor(mHandler), null);
1099             fail("expected IllegalArgumentException - null callback");
1100         } catch (IllegalArgumentException expected) {
1101         }
1102         try {
1103             WifiManager.WifiVerboseLoggingStatusChangedListener listener =
1104                     new WifiManager.WifiVerboseLoggingStatusChangedListener() {
1105                         @Override
1106                         public void onWifiVerboseLoggingStatusChanged(boolean enabled) {
1107 
1108                         }
1109                     };
1110             mWifiManager.addWifiVerboseLoggingStatusChangedListener(null, listener);
1111             fail("expected IllegalArgumentException - null executor");
1112         } catch (IllegalArgumentException expected) {
1113         }
1114     }
1115 
1116     /**
1117      * Verify the call to addWifiVerboseLoggingStatusChangedListener and
1118      * removeWifiVerboseLoggingStatusChangedListener goes to WifiServiceImpl.
1119      */
1120     @Test
testWifiVerboseLoggingStatusChangedListenerGoesToWifiServiceImpl()1121     public void testWifiVerboseLoggingStatusChangedListenerGoesToWifiServiceImpl()
1122             throws Exception {
1123         WifiManager.WifiVerboseLoggingStatusChangedListener listener =
1124                 new WifiManager.WifiVerboseLoggingStatusChangedListener() {
1125                     @Override
1126                     public void onWifiVerboseLoggingStatusChanged(boolean enabled) {
1127 
1128                     }
1129                 };
1130         mWifiManager.addWifiVerboseLoggingStatusChangedListener(new HandlerExecutor(mHandler),
1131                 listener);
1132         verify(mWifiService).addWifiVerboseLoggingStatusChangedListener(
1133                 any(IWifiVerboseLoggingStatusChangedListener.Stub.class));
1134         mWifiManager.removeWifiVerboseLoggingStatusChangedListener(listener);
1135         verify(mWifiService).removeWifiVerboseLoggingStatusChangedListener(
1136                 any(IWifiVerboseLoggingStatusChangedListener.Stub.class));
1137     }
1138 
1139     /**
1140      * Verify an IllegalArgumentException is thrown if a callback is not provided.
1141      */
1142     @Test
testRemoveWifiVerboseLoggingStatusChangedListenerIllegalArguments()1143     public void testRemoveWifiVerboseLoggingStatusChangedListenerIllegalArguments()
1144             throws Exception {
1145         try {
1146             mWifiManager.removeWifiVerboseLoggingStatusChangedListener(null);
1147             fail("expected IllegalArgumentException - null callback");
1148         } catch (IllegalArgumentException expected) {
1149         }
1150     }
1151 
1152     /**
1153      * Verify an IllegalArgumentException is thrown if callback is not provided.
1154      */
1155     @Test
registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback()1156     public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
1157         try {
1158             mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), null);
1159             fail("expected IllegalArgumentException");
1160         } catch (IllegalArgumentException expected) {
1161         }
1162     }
1163 
1164     /**
1165      * Verify an IllegalArgumentException is thrown if executor is null.
1166      */
1167     @Test
registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForExecutor()1168     public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForExecutor() {
1169         try {
1170             mWifiManager.registerSoftApCallback(null, mSoftApCallback);
1171             fail("expected IllegalArgumentException");
1172         } catch (IllegalArgumentException expected) {
1173         }
1174     }
1175 
1176     /**
1177      * Verify an IllegalArgumentException is thrown if callback is not provided.
1178      */
1179     @Test
unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback()1180     public void unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
1181         try {
1182             mWifiManager.unregisterSoftApCallback(null);
1183             fail("expected IllegalArgumentException");
1184         } catch (IllegalArgumentException expected) {
1185         }
1186     }
1187 
1188     /**
1189      * Verify the call to registerSoftApCallback goes to WifiServiceImpl.
1190      */
1191     @Test
registerSoftApCallbackCallGoesToWifiServiceImpl()1192     public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
1193         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1194         verify(mWifiService).registerSoftApCallback(any(ISoftApCallback.Stub.class));
1195     }
1196 
1197     /**
1198      * Verify the call to unregisterSoftApCallback goes to WifiServiceImpl.
1199      */
1200     @Test
unregisterSoftApCallbackCallGoesToWifiServiceImpl()1201     public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
1202         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1203                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1204         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1205         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1206 
1207         mWifiManager.unregisterSoftApCallback(mSoftApCallback);
1208         verify(mWifiService).unregisterSoftApCallback(callbackCaptor.getValue());
1209     }
1210 
1211     /*
1212      * Verify client-provided callback is being called through callback proxy
1213      */
1214     @Test
softApCallbackProxyCallsOnStateChanged()1215     public void softApCallbackProxyCallsOnStateChanged() throws Exception {
1216         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1217                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1218         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1219         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1220 
1221         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
1222         mLooper.dispatchAll();
1223         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
1224     }
1225 
1226     /*
1227      * Verify client-provided callback is being called through callback proxy when registration.
1228      */
1229     @Test
softApCallbackProxyCallsOnRegistrationAndApStartedWithClientsConnected()1230     public void softApCallbackProxyCallsOnRegistrationAndApStartedWithClientsConnected()
1231             throws Exception {
1232         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1233                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1234         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1235         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1236         // Prepare test info and clients
1237         initTestInfoAndAddToTestMap(1);
1238         List<WifiClient> clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1239         // Trigger callback with registration in AP started and clients connected.
1240         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1241                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1242                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1243 
1244         mLooper.dispatchAll();
1245         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1246         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1247         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1248         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1249                         infos.contains(mTestApInfo1)));
1250     }
1251 
1252 
1253     /*
1254      * Verify client-provided callback is being called through callback proxy
1255      */
1256     @Test
softApCallbackProxyCallsOnConnectedClientsChangedEvenIfNoInfoChanged()1257     public void softApCallbackProxyCallsOnConnectedClientsChangedEvenIfNoInfoChanged()
1258             throws Exception {
1259         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1260                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1261         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1262         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1263         List<WifiClient> clientList;
1264         // Verify the register callback in disable state.
1265         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1266                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1267                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1268         mLooper.dispatchAll();
1269         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1270         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1271         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1272         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1273         // After verify, reset mSoftApCallback for nex test
1274         reset(mSoftApCallback);
1275 
1276         // Test first client connected
1277         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1278         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1279                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1280                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1281         mLooper.dispatchAll();
1282         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1283         // and InfoChanged(List<SoftApInfo>)
1284         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1285         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1286         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1287         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1288         // After verify, reset mSoftApCallback for nex test
1289         reset(mSoftApCallback);
1290 
1291         // Test second client connected
1292         mTestWifiClientsMap.clear();
1293         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
1294         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1295                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1296                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1297         mLooper.dispatchAll();
1298         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1299         // and InfoChanged(List<SoftApInfo>)
1300         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1301         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1302         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1303         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1304         // After verify, reset mSoftApCallback for nex test
1305         reset(mSoftApCallback);
1306 
1307         // Test second client disconnect
1308         mTestWifiClientsMap.clear();
1309         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1310         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1311                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1312                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1313         mLooper.dispatchAll();
1314         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1315         // and InfoChanged(List<SoftApInfo>)
1316         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1317         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1318         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1319         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1320         // After verify, reset mSoftApCallback for nex test
1321         reset(mSoftApCallback);
1322     }
1323 
1324     /*
1325      * Verify client-provided callback is being called through callback proxy
1326      */
1327     @Test
softApCallbackProxyCallsOnConnectedClientsChanged()1328     public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception {
1329         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1330                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1331         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1332         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1333         List<WifiClient> clientList;
1334         // Verify the register callback in disable state.
1335         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1336                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1337                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1338         mLooper.dispatchAll();
1339         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1340         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1341         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1342         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1343         // After verify, reset mSoftApCallback for nex test
1344         reset(mSoftApCallback);
1345 
1346         // Single AP mode Test
1347         // Test info update
1348         initTestInfoAndAddToTestMap(1);
1349         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1350                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1351                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1352         mLooper.dispatchAll();
1353         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1354         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1355                         infos.contains(mTestApInfo1)));
1356         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1357         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1358         // After verify, reset mSoftApCallback for nex test
1359         reset(mSoftApCallback);
1360 
1361         // Test first client connected
1362         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1363         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1364                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1365                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1366         mLooper.dispatchAll();
1367         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1368         // and InfoChanged(List<SoftApInfo>)
1369         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1370         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1371         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1372         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1373         // After verify, reset mSoftApCallback for nex test
1374         reset(mSoftApCallback);
1375 
1376         // Test second client connected
1377         mTestWifiClientsMap.clear();
1378         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
1379         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1380                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1381                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1382         mLooper.dispatchAll();
1383         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1384         // and InfoChanged(List<SoftApInfo>)
1385         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1386         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1387         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1388         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1389         // After verify, reset mSoftApCallback for nex test
1390         reset(mSoftApCallback);
1391 
1392         // Test second client disconnect
1393         mTestWifiClientsMap.clear();
1394         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1395         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1396                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1397                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1398         mLooper.dispatchAll();
1399         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1400         // and InfoChanged(List<SoftApInfo>)
1401         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1402         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1403         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1404         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1405         // After verify, reset mSoftApCallback for nex test
1406         reset(mSoftApCallback);
1407 
1408         // Test bridged mode case
1409         mTestSoftApInfoMap.clear();
1410         initTestInfoAndAddToTestMap(2);
1411         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1412                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1413                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1414         mLooper.dispatchAll();
1415         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1416         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1417                   infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
1418                   ));
1419         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1420         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1421         // After verify, reset mSoftApCallback for nex test
1422         reset(mSoftApCallback);
1423 
1424         // Test client connect to second instance
1425         List<WifiClient> clientListOnSecond =
1426                 initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[1], 1, 2); // client3 to wlan2
1427         List<WifiClient> totalList = new ArrayList<>();
1428         totalList.addAll(clientList);
1429         totalList.addAll(clientListOnSecond);
1430         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1431                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1432                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1433         mLooper.dispatchAll();
1434         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1435         // and InfoChanged(List<SoftApInfo>)
1436         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1437         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1438         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo2, clientListOnSecond);
1439         verify(mSoftApCallback).onConnectedClientsChanged(totalList);
1440         // After verify, reset mSoftApCallback for nex test
1441         reset(mSoftApCallback);
1442 
1443         // Test shutdown on second instance
1444         mTestSoftApInfoMap.clear();
1445         mTestWifiClientsMap.clear();
1446         initTestInfoAndAddToTestMap(1);
1447         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1448         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1449                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1450                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1451         mLooper.dispatchAll();
1452         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1453         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1454                         infos.contains(mTestApInfo1)));
1455         // second instance have client connected before, thus it should send empty list
1456         verify(mSoftApCallback).onConnectedClientsChanged(
1457                 mTestApInfo2, new ArrayList<WifiClient>());
1458         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1459         // After verify, reset mSoftApCallback for nex test
1460         reset(mSoftApCallback);
1461 
1462         // Test bridged mode disable when client connected
1463         mTestSoftApInfoMap.clear();
1464         mTestWifiClientsMap.clear();
1465         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1466                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1467                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1468         mLooper.dispatchAll();
1469         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1470         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1471         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1472         verify(mSoftApCallback).onConnectedClientsChanged(
1473                 mTestApInfo1, new ArrayList<WifiClient>());
1474         // After verify, reset mSoftApCallback for nex test
1475         reset(mSoftApCallback);
1476     }
1477 
1478 
1479     /*
1480      * Verify client-provided callback is being called through callback proxy
1481      */
1482     @Test
softApCallbackProxyCallsOnSoftApInfoChanged()1483     public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
1484         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1485                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1486         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1487         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1488         // Verify the register callback in disable state.
1489         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1490                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1491                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1492         mLooper.dispatchAll();
1493         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1494         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1495         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1496         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1497         // After verify, reset mSoftApCallback for nex test
1498         reset(mSoftApCallback);
1499 
1500         // Single AP mode Test
1501         // Test info update
1502         initTestInfoAndAddToTestMap(1);
1503         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1504                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1505                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1506         mLooper.dispatchAll();
1507         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1508         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1509                         infos.contains(mTestApInfo1)));
1510         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1511         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1512         // After verify, reset mSoftApCallback for nex test
1513         reset(mSoftApCallback);
1514 
1515         // Test info changed
1516         SoftApInfo changedInfo = new SoftApInfo(mTestSoftApInfoMap.get(TEST_AP_INSTANCES[0]));
1517         changedInfo.setFrequency(2422);
1518         mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfo);
1519         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1520                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1521                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1522         mLooper.dispatchAll();
1523         verify(mSoftApCallback).onInfoChanged(changedInfo);
1524         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1525                         infos.contains(changedInfo)));
1526         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1527         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1528 
1529         // Test Stop, all of infos is empty
1530         mTestSoftApInfoMap.clear();
1531         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1532                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1533                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1534         mLooper.dispatchAll();
1535         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1536         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1537         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1538         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1539         // After verify, reset mSoftApCallback for nex test
1540         reset(mSoftApCallback);
1541     }
1542 
1543     /*
1544      * Verify client-provided callback is being called through callback proxy
1545      */
1546     @Test
softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode()1547     public void softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode() throws Exception {
1548         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1549                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1550         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1551         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1552 
1553         // Test bridged mode case
1554         initTestInfoAndAddToTestMap(2);
1555         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1556                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1557                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1558         mLooper.dispatchAll();
1559         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1560         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1561                   infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
1562                   ));
1563         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1564         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1565         // After verify, reset mSoftApCallback for nex test
1566         reset(mSoftApCallback);
1567 
1568         // Test bridged mode case but an info changed
1569         SoftApInfo changedInfoBridgedMode = new SoftApInfo(mTestSoftApInfoMap.get(
1570                 TEST_AP_INSTANCES[0]));
1571         changedInfoBridgedMode.setFrequency(2422);
1572         mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfoBridgedMode);
1573         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1574                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1575                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1576         mLooper.dispatchAll();
1577         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1578         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1579                   infos.contains(changedInfoBridgedMode) && infos.contains(mTestApInfo2)
1580                   ));
1581         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1582         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1583         // After verify, reset mSoftApCallback for nex test
1584         reset(mSoftApCallback);
1585 
1586         // Test bridged mode case but an instance shutdown
1587         mTestSoftApInfoMap.clear();
1588         initTestInfoAndAddToTestMap(1);
1589         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1590                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1591                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1592         mLooper.dispatchAll();
1593         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1594         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1595                   infos.contains(mTestApInfo1)
1596                   ));
1597         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1598         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1599         // After verify, reset mSoftApCallback for nex test
1600         reset(mSoftApCallback);
1601 
1602         // Test bridged mode disable case
1603         mTestSoftApInfoMap.clear();
1604         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1605                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1606                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1607         mLooper.dispatchAll();
1608         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1609         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1610         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1611         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1612         // After verify, reset mSoftApCallback for nex test
1613         reset(mSoftApCallback);
1614     }
1615 
1616     /*
1617      * Verify client-provided callback is being called through callback proxy
1618      */
1619     @Test
softApCallbackProxyCallsOnCapabilityChanged()1620     public void softApCallbackProxyCallsOnCapabilityChanged() throws Exception {
1621         SoftApCapability testSoftApCapability = new SoftApCapability(0);
1622         testSoftApCapability.setMaxSupportedClients(10);
1623         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1624                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1625         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1626         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1627 
1628         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
1629         mLooper.dispatchAll();
1630         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
1631     }
1632 
1633     /*
1634      * Verify client-provided callback is being called through callback proxy
1635      */
1636     @Test
softApCallbackProxyCallsOnBlockedClientConnecting()1637     public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
1638         WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
1639                 TEST_AP_INSTANCES[0]);
1640         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1641                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1642         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1643         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1644 
1645         callbackCaptor.getValue().onBlockedClientConnecting(testWifiClient,
1646                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
1647         mLooper.dispatchAll();
1648         verify(mSoftApCallback).onBlockedClientConnecting(testWifiClient,
1649                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
1650     }
1651 
1652     /*
1653      * Verify client-provided callback is being called through callback proxy on multiple events
1654      */
1655     @Test
softApCallbackProxyCallsOnMultipleUpdates()1656     public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
1657         SoftApCapability testSoftApCapability = new SoftApCapability(0);
1658         testSoftApCapability.setMaxSupportedClients(10);
1659         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1660                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1661         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1662         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1663 
1664         final List<WifiClient> testClients = new ArrayList();
1665         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLING, 0);
1666         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
1667         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
1668 
1669 
1670         mLooper.dispatchAll();
1671         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLING, 0);
1672         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL);
1673         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
1674     }
1675 
1676     /*
1677      * Verify client-provided callback is being called on the correct thread
1678      */
1679     @Test
softApCallbackIsCalledOnCorrectThread()1680     public void softApCallbackIsCalledOnCorrectThread() throws Exception {
1681         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1682                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1683         TestLooper altLooper = new TestLooper();
1684         Handler altHandler = new Handler(altLooper.getLooper());
1685         mWifiManager.registerSoftApCallback(new HandlerExecutor(altHandler), mSoftApCallback);
1686         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1687 
1688         callbackCaptor.getValue().onStateChanged(WIFI_AP_STATE_ENABLED, 0);
1689         altLooper.dispatchAll();
1690         verify(mSoftApCallback).onStateChanged(WIFI_AP_STATE_ENABLED, 0);
1691     }
1692 
1693     /**
1694      * Verify that the handler provided by the caller is used for registering soft AP callback.
1695      */
1696     @Test
testCorrectLooperIsUsedForSoftApCallbackHandler()1697     public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception {
1698         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1699         mLooper.dispatchAll();
1700         verify(mWifiService).registerSoftApCallback(any(ISoftApCallback.Stub.class));
1701         verify(mContext, never()).getMainLooper();
1702         verify(mContext, never()).getMainExecutor();
1703     }
1704 
1705     /**
1706      * Verify that the handler provided by the caller is used for the observer.
1707      */
1708     @Test
testCorrectLooperIsUsedForObserverHandler()1709     public void testCorrectLooperIsUsedForObserverHandler() throws Exception {
1710         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1711         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1712         mLooper.dispatchAll();
1713         assertTrue(observer.mOnRegistered);
1714         verify(mContext, never()).getMainLooper();
1715         verify(mContext, never()).getMainExecutor();
1716     }
1717 
1718     /**
1719      * Verify that the main looper's thread is used if a handler is not provided by the requesting
1720      * application.
1721      */
1722     @Test
testMainLooperIsUsedWhenHandlerNotProvidedForObserver()1723     public void testMainLooperIsUsedWhenHandlerNotProvidedForObserver() throws Exception {
1724         // record thread from looper.getThread and check ids.
1725         TestLooper altLooper = new TestLooper();
1726         when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
1727         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1728         mWifiManager.watchLocalOnlyHotspot(observer, null);
1729         altLooper.dispatchAll();
1730         assertTrue(observer.mOnRegistered);
1731         assertEquals(altLooper.getLooper().getThread().getId(), observer.mCallingThreadId);
1732         verify(mContext).getMainExecutor();
1733     }
1734 
1735     /**
1736      * Verify the LOHS onRegistered observer callback is triggered when WifiManager receives a
1737      * HOTSPOT_OBSERVER_REGISTERED message from WifiServiceImpl.
1738      */
1739     @Test
testOnRegisteredIsCalledWithSubscription()1740     public void testOnRegisteredIsCalledWithSubscription() throws Exception {
1741         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1742         TestLooper observerLooper = new TestLooper();
1743         Handler observerHandler = new Handler(observerLooper.getLooper());
1744         assertFalse(observer.mOnRegistered);
1745         assertEquals(null, observer.mSub);
1746         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1747         verify(mWifiService).startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1748         // now trigger the callback
1749         observerLooper.dispatchAll();
1750         mLooper.dispatchAll();
1751         assertTrue(observer.mOnRegistered);
1752         assertNotNull(observer.mSub);
1753     }
1754 
1755     /**
1756      * Verify the LOHS onStarted observer callback is triggered when WifiManager receives a
1757      * HOTSPOT_STARTED message from WifiServiceImpl.
1758      */
1759     @Test
testObserverOnStartedIsCalledWithWifiConfig()1760     public void testObserverOnStartedIsCalledWithWifiConfig() throws Exception {
1761         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
1762         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1763         TestLooper observerLooper = new TestLooper();
1764         Handler observerHandler = new Handler(observerLooper.getLooper());
1765         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1766         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1767                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1768         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1769         observerLooper.dispatchAll();
1770         mLooper.dispatchAll();
1771         assertFalse(observer.mOnStartedCalled);
1772         // now trigger the callback
1773         internalCallback.getValue().onHotspotStarted(softApConfig);
1774         mLooper.dispatchAll();
1775         observerLooper.dispatchAll();
1776         assertTrue(observer.mOnStartedCalled);
1777         assertEquals(softApConfig, observer.mConfig);
1778     }
1779 
1780     /**
1781      * Verify the LOHS onStarted observer callback is triggered not when WifiManager receives a
1782      * HOTSPOT_STARTED message from WifiServiceImpl with a null config.
1783      */
1784     @Test
testObserverOnStartedNotCalledWithNullConfig()1785     public void testObserverOnStartedNotCalledWithNullConfig() throws Exception {
1786         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1787         TestLooper observerLooper = new TestLooper();
1788         Handler observerHandler = new Handler(observerLooper.getLooper());
1789         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1790         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1791                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1792         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1793         observerLooper.dispatchAll();
1794         mLooper.dispatchAll();
1795         assertFalse(observer.mOnStartedCalled);
1796         // now trigger the callback
1797         internalCallback.getValue().onHotspotStarted(null);
1798         mLooper.dispatchAll();
1799         observerLooper.dispatchAll();
1800         assertFalse(observer.mOnStartedCalled);
1801         assertEquals(null, observer.mConfig);
1802     }
1803 
1804 
1805     /**
1806      * Verify the LOHS onStopped observer callback is triggered when WifiManager receives a
1807      * HOTSPOT_STOPPED message from WifiServiceImpl.
1808      */
1809     @Test
testObserverOnStoppedIsCalled()1810     public void testObserverOnStoppedIsCalled() throws Exception {
1811         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1812         TestLooper observerLooper = new TestLooper();
1813         Handler observerHandler = new Handler(observerLooper.getLooper());
1814         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1815         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1816                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1817         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1818         observerLooper.dispatchAll();
1819         mLooper.dispatchAll();
1820         assertFalse(observer.mOnStoppedCalled);
1821         // now trigger the callback
1822         internalCallback.getValue().onHotspotStopped();
1823         mLooper.dispatchAll();
1824         observerLooper.dispatchAll();
1825         assertTrue(observer.mOnStoppedCalled);
1826     }
1827 
1828     /**
1829      * Verify WifiServiceImpl is not called if there is not a registered LOHS observer callback.
1830      */
1831     @Test
testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver()1832     public void testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver() throws Exception {
1833         mWifiManager.unregisterLocalOnlyHotspotObserver();
1834         verifyZeroInteractions(mWifiService);
1835     }
1836 
1837     /**
1838      * Verify WifiServiceImpl is called when there is a registered LOHS observer callback.
1839      */
1840     @Test
testUnregisterWifiServiceImplCalledWithRegisteredObserver()1841     public void testUnregisterWifiServiceImplCalledWithRegisteredObserver() throws Exception {
1842         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1843         TestLooper observerLooper = new TestLooper();
1844         Handler observerHandler = new Handler(observerLooper.getLooper());
1845         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1846         mWifiManager.unregisterLocalOnlyHotspotObserver();
1847         verify(mWifiService).stopWatchLocalOnlyHotspot();
1848     }
1849 
1850     /**
1851      * Test that calls to get the current WPS config token return null and do not have any
1852      * interactions with WifiServiceImpl.
1853      */
1854     @Test
testGetCurrentNetworkWpsNfcConfigurationTokenReturnsNull()1855     public void testGetCurrentNetworkWpsNfcConfigurationTokenReturnsNull() {
1856         assertNull(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken());
1857         verifyNoMoreInteractions(mWifiService);
1858     }
1859 
1860 
1861     class WpsCallbackTester extends WpsCallback {
1862         public boolean mStarted = false;
1863         public boolean mSucceeded = false;
1864         public boolean mFailed = false;
1865         public int mFailureCode = -1;
1866 
1867         @Override
onStarted(String pin)1868         public void onStarted(String pin) {
1869             mStarted = true;
1870         }
1871 
1872         @Override
onSucceeded()1873         public void onSucceeded() {
1874             mSucceeded = true;
1875         }
1876 
1877         @Override
onFailed(int reason)1878         public void onFailed(int reason) {
1879             mFailed = true;
1880             mFailureCode = reason;
1881         }
1882 
1883     }
1884 
1885     /**
1886      * Verify that a call to start WPS immediately returns a failure.
1887      */
1888     @Test
testStartWpsImmediatelyFailsWithCallback()1889     public void testStartWpsImmediatelyFailsWithCallback() {
1890         WpsCallbackTester wpsCallback = new WpsCallbackTester();
1891         mWifiManager.startWps(null, wpsCallback);
1892         assertTrue(wpsCallback.mFailed);
1893         assertEquals(ERROR, wpsCallback.mFailureCode);
1894         assertFalse(wpsCallback.mStarted);
1895         assertFalse(wpsCallback.mSucceeded);
1896         verifyNoMoreInteractions(mWifiService);
1897     }
1898 
1899     /**
1900      * Verify that a call to start WPS does not go to WifiServiceImpl if we do not have a callback.
1901      */
1902     @Test
testStartWpsDoesNotCallWifiServiceImpl()1903     public void testStartWpsDoesNotCallWifiServiceImpl() {
1904         mWifiManager.startWps(null, null);
1905         verifyNoMoreInteractions(mWifiService);
1906     }
1907 
1908     /**
1909      * Verify that a call to cancel WPS immediately returns a failure.
1910      */
1911     @Test
testCancelWpsImmediatelyFailsWithCallback()1912     public void testCancelWpsImmediatelyFailsWithCallback() {
1913         WpsCallbackTester wpsCallback = new WpsCallbackTester();
1914         mWifiManager.cancelWps(wpsCallback);
1915         assertTrue(wpsCallback.mFailed);
1916         assertEquals(ERROR, wpsCallback.mFailureCode);
1917         assertFalse(wpsCallback.mStarted);
1918         assertFalse(wpsCallback.mSucceeded);
1919         verifyNoMoreInteractions(mWifiService);
1920     }
1921 
1922     /**
1923      * Verify that a call to cancel WPS does not go to WifiServiceImpl if we do not have a callback.
1924      */
1925     @Test
testCancelWpsDoesNotCallWifiServiceImpl()1926     public void testCancelWpsDoesNotCallWifiServiceImpl() {
1927         mWifiManager.cancelWps(null);
1928         verifyNoMoreInteractions(mWifiService);
1929     }
1930 
1931     /**
1932      * Verify that a successful call properly returns true.
1933      */
1934     @Test
testSetWifiApConfigurationSuccessReturnsTrue()1935     public void testSetWifiApConfigurationSuccessReturnsTrue() throws Exception {
1936         WifiConfiguration apConfig = new WifiConfiguration();
1937 
1938         when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
1939                 .thenReturn(true);
1940         assertTrue(mWifiManager.setWifiApConfiguration(apConfig));
1941     }
1942 
1943     /**
1944      * Verify that a failed call properly returns false.
1945      */
1946     @Test
testSetWifiApConfigurationFailureReturnsFalse()1947     public void testSetWifiApConfigurationFailureReturnsFalse() throws Exception {
1948         WifiConfiguration apConfig = new WifiConfiguration();
1949 
1950         when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
1951                 .thenReturn(false);
1952         assertFalse(mWifiManager.setWifiApConfiguration(apConfig));
1953     }
1954 
1955     /**
1956      * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
1957      */
1958     @Test
testSetWifiApConfigurationRethrowsException()1959     public void testSetWifiApConfigurationRethrowsException() throws Exception {
1960         doThrow(new SecurityException()).when(mWifiService).setWifiApConfiguration(any(), any());
1961 
1962         try {
1963             mWifiManager.setWifiApConfiguration(new WifiConfiguration());
1964             fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
1965         } catch (SecurityException e) { }
1966     }
1967 
1968     /**
1969      * Verify that a successful call properly returns true.
1970      */
1971     @Test
testSetSoftApConfigurationSuccessReturnsTrue()1972     public void testSetSoftApConfigurationSuccessReturnsTrue() throws Exception {
1973         SoftApConfiguration apConfig = generatorTestSoftApConfig();
1974 
1975         when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
1976                 .thenReturn(true);
1977         assertTrue(mWifiManager.setSoftApConfiguration(apConfig));
1978     }
1979 
1980     /**
1981      * Verify that a failed call properly returns false.
1982      */
1983     @Test
testSetSoftApConfigurationFailureReturnsFalse()1984     public void testSetSoftApConfigurationFailureReturnsFalse() throws Exception {
1985         SoftApConfiguration apConfig = generatorTestSoftApConfig();
1986 
1987         when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
1988                 .thenReturn(false);
1989         assertFalse(mWifiManager.setSoftApConfiguration(apConfig));
1990     }
1991 
1992     /**
1993      * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
1994      */
1995     @Test
testSetSoftApConfigurationRethrowsException()1996     public void testSetSoftApConfigurationRethrowsException() throws Exception {
1997         doThrow(new SecurityException()).when(mWifiService).setSoftApConfiguration(any(), any());
1998 
1999         try {
2000             mWifiManager.setSoftApConfiguration(generatorTestSoftApConfig());
2001             fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
2002         } catch (SecurityException e) { }
2003     }
2004 
2005     /**
2006      * Check the call to startScan calls WifiService.
2007      */
2008     @Test
testStartScan()2009     public void testStartScan() throws Exception {
2010         when(mWifiService.startScan(eq(TEST_PACKAGE_NAME), nullable(String.class))).thenReturn(
2011                 true);
2012         assertTrue(mWifiManager.startScan());
2013 
2014         when(mWifiService.startScan(eq(TEST_PACKAGE_NAME), nullable(String.class))).thenReturn(
2015                 false);
2016         assertFalse(mWifiManager.startScan());
2017     }
2018 
2019     /**
2020      * Verify main looper is used when handler is not provided.
2021      */
2022     @Test
registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()2023     public void registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()
2024             throws Exception {
2025         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2026                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2027         mWifiManager.registerTrafficStateCallback(
2028                 new HandlerExecutor(new Handler(mLooper.getLooper())), mTrafficStateCallback);
2029         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2030 
2031         assertEquals(0, mLooper.dispatchAll());
2032         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2033         assertEquals(1, mLooper.dispatchAll());
2034         verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2035     }
2036 
2037     /**
2038      * Verify the call to unregisterTrafficStateCallback goes to WifiServiceImpl.
2039      */
2040     @Test
unregisterTrafficStateCallbackCallGoesToWifiServiceImpl()2041     public void unregisterTrafficStateCallbackCallGoesToWifiServiceImpl() throws Exception {
2042         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2043                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2044         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(mHandler),
2045                 mTrafficStateCallback);
2046         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2047 
2048         mWifiManager.unregisterTrafficStateCallback(mTrafficStateCallback);
2049         verify(mWifiService).unregisterTrafficStateCallback(callbackCaptor.getValue());
2050     }
2051 
2052     /*
2053      * Verify client-provided callback is being called through callback proxy on multiple events
2054      */
2055     @Test
trafficStateCallbackProxyCallsOnMultipleUpdates()2056     public void trafficStateCallbackProxyCallsOnMultipleUpdates() throws Exception {
2057         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2058                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2059         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(mHandler),
2060                 mTrafficStateCallback);
2061         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2062 
2063         InOrder inOrder = inOrder(mTrafficStateCallback);
2064 
2065         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN);
2066         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2067         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT);
2068 
2069         mLooper.dispatchAll();
2070         inOrder.verify(mTrafficStateCallback).onStateChanged(
2071                 TrafficStateCallback.DATA_ACTIVITY_IN);
2072         inOrder.verify(mTrafficStateCallback).onStateChanged(
2073                 TrafficStateCallback.DATA_ACTIVITY_INOUT);
2074         inOrder.verify(mTrafficStateCallback).onStateChanged(
2075                 TrafficStateCallback.DATA_ACTIVITY_OUT);
2076     }
2077 
2078     /**
2079      * Verify client-provided callback is being called on the correct thread
2080      */
2081     @Test
trafficStateCallbackIsCalledOnCorrectThread()2082     public void trafficStateCallbackIsCalledOnCorrectThread() throws Exception {
2083         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2084                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2085         TestLooper altLooper = new TestLooper();
2086         Handler altHandler = new Handler(altLooper.getLooper());
2087         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(altHandler),
2088                 mTrafficStateCallback);
2089         verify(mContext, never()).getMainLooper();
2090         verify(mContext, never()).getMainExecutor();
2091         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2092 
2093         assertEquals(0, altLooper.dispatchAll());
2094         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2095         assertEquals(1, altLooper.dispatchAll());
2096         verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2097     }
2098 
2099     /**
2100      * Verify the call to registerNetworkRequestMatchCallback goes to WifiServiceImpl.
2101      */
2102     @Test
registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()2103     public void registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()
2104             throws Exception {
2105         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2106                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2107         mWifiManager.registerNetworkRequestMatchCallback(
2108                 new HandlerExecutor(new Handler(mLooper.getLooper())),
2109                 mNetworkRequestMatchCallback);
2110         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2111 
2112         INetworkRequestUserSelectionCallback iUserSelectionCallback =
2113                 mock(INetworkRequestUserSelectionCallback.class);
2114 
2115         assertEquals(0, mLooper.dispatchAll());
2116 
2117         callbackCaptor.getValue().onAbort();
2118         assertEquals(1, mLooper.dispatchAll());
2119         verify(mNetworkRequestMatchCallback).onAbort();
2120 
2121         callbackCaptor.getValue().onMatch(new ArrayList<ScanResult>());
2122         assertEquals(1, mLooper.dispatchAll());
2123         verify(mNetworkRequestMatchCallback).onMatch(anyList());
2124 
2125         callbackCaptor.getValue().onUserSelectionConnectSuccess(new WifiConfiguration());
2126         assertEquals(1, mLooper.dispatchAll());
2127         verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
2128                 any(WifiConfiguration.class));
2129 
2130         callbackCaptor.getValue().onUserSelectionConnectFailure(new WifiConfiguration());
2131         assertEquals(1, mLooper.dispatchAll());
2132         verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
2133                 any(WifiConfiguration.class));
2134     }
2135 
2136     /**
2137      * Verify the call to unregisterNetworkRequestMatchCallback goes to WifiServiceImpl.
2138      */
2139     @Test
unregisterNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()2140     public void unregisterNetworkRequestMatchCallbackCallGoesToWifiServiceImpl() throws Exception {
2141         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2142                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2143         mWifiManager.registerNetworkRequestMatchCallback(new HandlerExecutor(mHandler),
2144                 mNetworkRequestMatchCallback);
2145         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2146 
2147         mWifiManager.unregisterNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
2148         verify(mWifiService).unregisterNetworkRequestMatchCallback(callbackCaptor.getValue());
2149     }
2150 
2151     /**
2152      * Verify the call to NetworkRequestUserSelectionCallback goes to
2153      * WifiServiceImpl.
2154      */
2155     @Test
networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()2156     public void networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()
2157             throws Exception {
2158         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2159                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2160         mWifiManager.registerNetworkRequestMatchCallback(
2161                 new HandlerExecutor(new Handler(mLooper.getLooper())),
2162                 mNetworkRequestMatchCallback);
2163         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2164 
2165         INetworkRequestUserSelectionCallback iUserSelectionCallback =
2166                 mock(INetworkRequestUserSelectionCallback.class);
2167         ArgumentCaptor<NetworkRequestUserSelectionCallback> userSelectionCallbackCaptor =
2168                 ArgumentCaptor.forClass(NetworkRequestUserSelectionCallback.class);
2169         callbackCaptor.getValue().onUserSelectionCallbackRegistration(
2170                 iUserSelectionCallback);
2171         assertEquals(1, mLooper.dispatchAll());
2172         verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
2173                 userSelectionCallbackCaptor.capture());
2174 
2175         WifiConfiguration selected = new WifiConfiguration();
2176         userSelectionCallbackCaptor.getValue().select(selected);
2177         verify(iUserSelectionCallback).select(selected);
2178 
2179         userSelectionCallbackCaptor.getValue().reject();
2180         verify(iUserSelectionCallback).reject();
2181     }
2182 
2183     /**
2184      * Check the call to getAllMatchingWifiConfigs calls getAllMatchingFqdnsForScanResults and
2185      * getWifiConfigsForPasspointProfiles of WifiService in order.
2186      */
2187     @Test
testGetAllMatchingWifiConfigs()2188     public void testGetAllMatchingWifiConfigs() throws Exception {
2189         Map<String, List<ScanResult>> passpointProfiles = new HashMap<>();
2190         passpointProfiles.put("www.test.com_987a69bca26", new ArrayList<>());
2191         when(mWifiService.getAllMatchingPasspointProfilesForScanResults(
2192                 any(List.class))).thenReturn(passpointProfiles);
2193         InOrder inOrder = inOrder(mWifiService);
2194 
2195         mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>());
2196 
2197         inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any(List.class));
2198         inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any(List.class));
2199     }
2200 
2201     /**
2202      * Check the call to getMatchingOsuProviders calls getMatchingOsuProviders of WifiService
2203      * with the provided a list of ScanResult.
2204      */
2205     @Test
testGetMatchingOsuProviders()2206     public void testGetMatchingOsuProviders() throws Exception {
2207         mWifiManager.getMatchingOsuProviders(new ArrayList<>());
2208 
2209         verify(mWifiService).getMatchingOsuProviders(any(List.class));
2210     }
2211 
2212     /**
2213      * Verify calls to {@link WifiManager#addNetworkSuggestions(List)},
2214      * {@link WifiManager#getNetworkSuggestions()} and
2215      * {@link WifiManager#removeNetworkSuggestions(List)}.
2216      */
2217     @Test
addGetRemoveNetworkSuggestions()2218     public void addGetRemoveNetworkSuggestions() throws Exception {
2219         List<WifiNetworkSuggestion> testList = new ArrayList<>();
2220         when(mWifiService.addNetworkSuggestions(any(List.class), anyString(),
2221                 nullable(String.class))).thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS);
2222         when(mWifiService.removeNetworkSuggestions(any(List.class), anyString())).thenReturn(
2223                 STATUS_NETWORK_SUGGESTIONS_SUCCESS);
2224         when(mWifiService.getNetworkSuggestions(anyString()))
2225                 .thenReturn(testList);
2226 
2227         assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS,
2228                 mWifiManager.addNetworkSuggestions(testList));
2229         verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME),
2230                 nullable(String.class));
2231 
2232         assertEquals(testList, mWifiManager.getNetworkSuggestions());
2233         verify(mWifiService).getNetworkSuggestions(eq(TEST_PACKAGE_NAME));
2234 
2235         assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS,
2236                 mWifiManager.removeNetworkSuggestions(new ArrayList<>()));
2237         verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME));
2238     }
2239 
2240     /**
2241      * Verify call to {@link WifiManager#getMaxNumberOfNetworkSuggestionsPerApp()}.
2242      */
2243     @Test
getMaxNumberOfNetworkSuggestionsPerApp()2244     public void getMaxNumberOfNetworkSuggestionsPerApp() {
2245         when(mContext.getSystemServiceName(ActivityManager.class))
2246                 .thenReturn(Context.ACTIVITY_SERVICE);
2247         when(mContext.getSystemService(Context.ACTIVITY_SERVICE))
2248                 .thenReturn(mActivityManager);
2249         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2250         assertEquals(256, mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp());
2251 
2252         when(mActivityManager.isLowRamDevice()).thenReturn(false);
2253         assertEquals(1024, mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp());
2254     }
2255 
2256     /**
2257      * Verify getting the factory MAC address.
2258      */
2259     @Test
testGetFactoryMacAddress()2260     public void testGetFactoryMacAddress() throws Exception {
2261         when(mWifiService.getFactoryMacAddresses()).thenReturn(TEST_MAC_ADDRESSES);
2262         assertArrayEquals(TEST_MAC_ADDRESSES, mWifiManager.getFactoryMacAddresses());
2263         verify(mWifiService).getFactoryMacAddresses();
2264     }
2265 
2266     /**
2267      * Verify the call to getCallerConfiguredNetworks goes to WifiServiceImpl.
2268      */
2269     @Test
testGetCallerConfiguredNetworks()2270     public void testGetCallerConfiguredNetworks() throws Exception {
2271         mWifiManager.getCallerConfiguredNetworks();
2272         verify(mWifiService).getConfiguredNetworks(any(), any(), eq(true));
2273     }
2274 
2275     /**
2276      * Verify the call to startRestrictingAutoJoinToSubscriptionId goes to WifiServiceImpl.
2277      */
2278     @Test
testStartRestrictAutoJoinToSubscriptionId()2279     public void testStartRestrictAutoJoinToSubscriptionId() throws Exception {
2280         assumeTrue(SdkLevel.isAtLeastS());
2281         mWifiManager.startRestrictingAutoJoinToSubscriptionId(1);
2282         verify(mWifiService).startRestrictingAutoJoinToSubscriptionId(1);
2283     }
2284 
2285     /**
2286      * Verify the call to stopRestrictingAutoJoinToSubscriptionId goes to WifiServiceImpl.
2287      */
2288     @Test
testStopTemporarilyDisablingAllNonCarrierMergedWifi()2289     public void testStopTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception {
2290         assumeTrue(SdkLevel.isAtLeastS());
2291         mWifiManager.stopRestrictingAutoJoinToSubscriptionId();
2292         verify(mWifiService).stopRestrictingAutoJoinToSubscriptionId();
2293     }
2294 
2295     /**
2296      * Verify the call to addOnWifiUsabilityStatsListener goes to WifiServiceImpl.
2297      */
2298     @Test
addOnWifiUsabilityStatsListenerGoesToWifiServiceImpl()2299     public void addOnWifiUsabilityStatsListenerGoesToWifiServiceImpl() throws Exception {
2300         mExecutor = new SynchronousExecutor();
2301         ArgumentCaptor<IOnWifiUsabilityStatsListener.Stub> callbackCaptor =
2302                 ArgumentCaptor.forClass(IOnWifiUsabilityStatsListener.Stub.class);
2303         mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
2304         verify(mWifiService).addOnWifiUsabilityStatsListener(callbackCaptor.capture());
2305         ContentionTimeStats[] contentionTimeStats = new ContentionTimeStats[4];
2306         contentionTimeStats[0] = new ContentionTimeStats(1, 2, 3, 4);
2307         contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8);
2308         contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12);
2309         contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16);
2310         RateStats[] rateStats = new RateStats[2];
2311         rateStats[0] = new RateStats(1, 3, 5, 7, 9, 11, 13, 15, 17);
2312         rateStats[1] = new RateStats(2, 4, 6, 8, 10, 12, 14, 16, 18);
2313         RadioStats[] radioStats = new RadioStats[2];
2314         radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18);
2315         radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28);
2316         callbackCaptor.getValue().onWifiUsabilityStats(1, true,
2317                 new WifiUsabilityStatsEntry(System.currentTimeMillis(), -50, 100, 10, 0, 5, 5,
2318                         100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1, 100, 10,
2319                         100, 27, contentionTimeStats, rateStats, radioStats, 101, true, true, true,
2320                         0, 10, 10, true));
2321         verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
2322                 any(WifiUsabilityStatsEntry.class));
2323     }
2324 
2325     /**
2326      * Verify the call to removeOnWifiUsabilityStatsListener goes to WifiServiceImpl.
2327      */
2328     @Test
removeOnWifiUsabilityListenerGoesToWifiServiceImpl()2329     public void removeOnWifiUsabilityListenerGoesToWifiServiceImpl() throws Exception {
2330         mExecutor = new SynchronousExecutor();
2331         ArgumentCaptor<IOnWifiUsabilityStatsListener.Stub> callbackCaptor =
2332                 ArgumentCaptor.forClass(IOnWifiUsabilityStatsListener.Stub.class);
2333         mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
2334         verify(mWifiService).addOnWifiUsabilityStatsListener(callbackCaptor.capture());
2335 
2336         mWifiManager.removeOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
2337         verify(mWifiService).removeOnWifiUsabilityStatsListener(callbackCaptor.getValue());
2338     }
2339 
2340     /**
2341      * Test behavior of isEnhancedOpenSupported
2342      */
2343     @Test
testIsEnhancedOpenSupported()2344     public void testIsEnhancedOpenSupported() throws Exception {
2345         when(mWifiService.getSupportedFeatures())
2346                 .thenReturn(new Long(WIFI_FEATURE_OWE));
2347         assertTrue(mWifiManager.isEnhancedOpenSupported());
2348         when(mWifiService.getSupportedFeatures())
2349                 .thenReturn(new Long(~WIFI_FEATURE_OWE));
2350         assertFalse(mWifiManager.isEnhancedOpenSupported());
2351     }
2352 
2353     /**
2354      * Test behavior of isWpa3SaeSupported
2355      */
2356     @Test
testIsWpa3SaeSupported()2357     public void testIsWpa3SaeSupported() throws Exception {
2358         when(mWifiService.getSupportedFeatures())
2359                 .thenReturn(new Long(WIFI_FEATURE_WPA3_SAE));
2360         assertTrue(mWifiManager.isWpa3SaeSupported());
2361         when(mWifiService.getSupportedFeatures())
2362                 .thenReturn(new Long(~WIFI_FEATURE_WPA3_SAE));
2363         assertFalse(mWifiManager.isWpa3SaeSupported());
2364     }
2365 
2366     /**
2367      * Test behavior of isWpa3SuiteBSupported
2368      */
2369     @Test
testIsWpa3SuiteBSupported()2370     public void testIsWpa3SuiteBSupported() throws Exception {
2371         when(mWifiService.getSupportedFeatures())
2372                 .thenReturn(new Long(WIFI_FEATURE_WPA3_SUITE_B));
2373         assertTrue(mWifiManager.isWpa3SuiteBSupported());
2374         when(mWifiService.getSupportedFeatures())
2375                 .thenReturn(new Long(~WIFI_FEATURE_WPA3_SUITE_B));
2376         assertFalse(mWifiManager.isWpa3SuiteBSupported());
2377     }
2378 
2379     /**
2380      * Test behavior of isEasyConnectSupported
2381      */
2382     @Test
testIsEasyConnectSupported()2383     public void testIsEasyConnectSupported() throws Exception {
2384         when(mWifiService.getSupportedFeatures())
2385                 .thenReturn(new Long(WIFI_FEATURE_DPP));
2386         assertTrue(mWifiManager.isEasyConnectSupported());
2387         when(mWifiService.getSupportedFeatures())
2388                 .thenReturn(new Long(~WIFI_FEATURE_DPP));
2389         assertFalse(mWifiManager.isEasyConnectSupported());
2390     }
2391 
2392     /**
2393      * Test behavior of isEasyConnectEnrolleeResponderModeSupported
2394      */
2395     @Test
testIsEasyConnectEnrolleeResponderModeSupported()2396     public void testIsEasyConnectEnrolleeResponderModeSupported() throws Exception {
2397         assumeTrue(SdkLevel.isAtLeastS());
2398 
2399         when(mWifiService.getSupportedFeatures())
2400                 .thenReturn(new Long(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
2401         assertTrue(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
2402         when(mWifiService.getSupportedFeatures())
2403                 .thenReturn(new Long(~WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
2404         assertFalse(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
2405     }
2406 
2407     /**
2408      * Test behavior of isStaApConcurrencySupported
2409      */
2410     @Test
testIsStaApConcurrencyOpenSupported()2411     public void testIsStaApConcurrencyOpenSupported() throws Exception {
2412         when(mWifiService.getSupportedFeatures())
2413                 .thenReturn(new Long(WIFI_FEATURE_AP_STA));
2414         assertTrue(mWifiManager.isStaApConcurrencySupported());
2415         when(mWifiService.getSupportedFeatures())
2416                 .thenReturn(new Long(~WIFI_FEATURE_AP_STA));
2417         assertFalse(mWifiManager.isStaApConcurrencySupported());
2418     }
2419 
2420     /**
2421      * Test behavior of isStaConcurrencySupported
2422      */
2423     @Test
testIsStaConcurrencySupported()2424     public void testIsStaConcurrencySupported() throws Exception {
2425         when(mWifiService.getSupportedFeatures()).thenReturn(0L);
2426         assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2427         assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2428         assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2429 
2430         when(mWifiService.getSupportedFeatures())
2431                 .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY));
2432         assertTrue(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2433         assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2434         assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2435 
2436         when(mWifiService.getSupportedFeatures())
2437                 .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MBB
2438                         | WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED));
2439         assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2440         assertTrue(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2441         assertTrue(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2442     }
2443 
2444     /**
2445      * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)}
2446      */
2447     @Test
testAddNetwork()2448     public void testAddNetwork() throws Exception {
2449         WifiConfiguration configuration = new WifiConfiguration();
2450         when(mWifiService.addOrUpdateNetwork(any(), anyString()))
2451                 .thenReturn(TEST_NETWORK_ID);
2452 
2453         assertEquals(mWifiManager.addNetwork(configuration), TEST_NETWORK_ID);
2454         verify(mWifiService).addOrUpdateNetwork(configuration, mContext.getOpPackageName());
2455 
2456         // send a null config
2457         assertEquals(mWifiManager.addNetwork(null), -1);
2458     }
2459 
2460     /**
2461      * Test {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} goes to WifiService.
2462      * Also verify that an IllegalArgumentException is thrown if the input is null.
2463      */
2464     @Test
testAddNetworkPrivileged()2465     public void testAddNetworkPrivileged() throws Exception {
2466         WifiConfiguration configuration = new WifiConfiguration();
2467         mWifiManager.addNetworkPrivileged(configuration);
2468         verify(mWifiService).addOrUpdateNetworkPrivileged(configuration,
2469                 mContext.getOpPackageName());
2470 
2471         // send a null config and verify an exception is thrown
2472         try {
2473             mWifiManager.addNetworkPrivileged(null);
2474             fail("configuration is null - IllegalArgumentException is expected.");
2475         } catch (IllegalArgumentException e) {
2476         }
2477     }
2478 
2479     /**
2480      * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)}
2481      */
2482     @Test
testUpdateNetwork()2483     public void testUpdateNetwork() throws Exception {
2484         WifiConfiguration configuration = new WifiConfiguration();
2485         when(mWifiService.addOrUpdateNetwork(any(), anyString()))
2486                 .thenReturn(TEST_NETWORK_ID);
2487 
2488         configuration.networkId = TEST_NETWORK_ID;
2489         assertEquals(mWifiManager.updateNetwork(configuration), TEST_NETWORK_ID);
2490         verify(mWifiService).addOrUpdateNetwork(configuration, mContext.getOpPackageName());
2491 
2492         // config with invalid network ID
2493         configuration.networkId = -1;
2494         assertEquals(mWifiManager.updateNetwork(configuration), -1);
2495 
2496         // send a null config
2497         assertEquals(mWifiManager.updateNetwork(null), -1);
2498     }
2499 
2500     /**
2501      * Test behavior of {@link WifiManager#enableNetwork(int, boolean)}
2502      */
2503     @Test
testEnableNetwork()2504     public void testEnableNetwork() throws Exception {
2505         when(mWifiService.enableNetwork(anyInt(), anyBoolean(), anyString()))
2506                 .thenReturn(true);
2507         assertTrue(mWifiManager.enableNetwork(TEST_NETWORK_ID, true));
2508         verify(mWifiService).enableNetwork(TEST_NETWORK_ID, true, mContext.getOpPackageName());
2509     }
2510 
2511     /**
2512      * Test behavior of {@link WifiManager#disableNetwork(int)}
2513      */
2514     @Test
testDisableNetwork()2515     public void testDisableNetwork() throws Exception {
2516         when(mWifiService.disableNetwork(anyInt(), anyString()))
2517                 .thenReturn(true);
2518         assertTrue(mWifiManager.disableNetwork(TEST_NETWORK_ID));
2519         verify(mWifiService).disableNetwork(TEST_NETWORK_ID, mContext.getOpPackageName());
2520     }
2521 
2522     /**
2523      * Test behavior of {@link WifiManager#allowAutojoin(int, boolean)}
2524      * @throws Exception
2525      */
2526     @Test
testAllowAutojoin()2527     public void testAllowAutojoin() throws Exception {
2528         mWifiManager.allowAutojoin(1, true);
2529         verify(mWifiService).allowAutojoin(1, true);
2530     }
2531 
2532     /**
2533      * Test behavior of {@link WifiManager#allowAutojoinPasspoint(String, boolean)}
2534      * @throws Exception
2535      */
2536     @Test
testAllowAutojoinPasspoint()2537     public void testAllowAutojoinPasspoint() throws Exception {
2538         final String fqdn = "FullyQualifiedDomainName";
2539         mWifiManager.allowAutojoinPasspoint(fqdn, true);
2540         verify(mWifiService).allowAutojoinPasspoint(fqdn, true);
2541     }
2542 
2543     /**
2544      * Test behavior of
2545      * {@link WifiManager#setMacRandomizationSettingPasspointEnabled(String, boolean)}
2546      */
2547     @Test
testSetMacRandomizationSettingPasspointEnabled()2548     public void testSetMacRandomizationSettingPasspointEnabled() throws Exception {
2549         final String fqdn = "FullyQualifiedDomainName";
2550         mWifiManager.setMacRandomizationSettingPasspointEnabled(fqdn, true);
2551         verify(mWifiService).setMacRandomizationSettingPasspointEnabled(fqdn, true);
2552     }
2553 
2554     /**
2555      * Test behavior of
2556      * {@link WifiManager#setMacRandomizationSettingPasspointEnabled(String, boolean)}
2557      */
2558     @Test
testSetPasspointMeteredOverride()2559     public void testSetPasspointMeteredOverride() throws Exception {
2560         final String fqdn = "FullyQualifiedDomainName";
2561         mWifiManager.setPasspointMeteredOverride(fqdn, METERED_OVERRIDE_METERED);
2562         verify(mWifiService).setPasspointMeteredOverride(fqdn, METERED_OVERRIDE_METERED);
2563     }
2564 
2565     /**
2566      * Test behavior of {@link WifiManager#disconnect()}
2567      */
2568     @Test
testDisconnect()2569     public void testDisconnect() throws Exception {
2570         when(mWifiService.disconnect(anyString())).thenReturn(true);
2571         assertTrue(mWifiManager.disconnect());
2572         verify(mWifiService).disconnect(mContext.getOpPackageName());
2573     }
2574 
2575     /**
2576      * Test behavior of {@link WifiManager#reconnect()}
2577      */
2578     @Test
testReconnect()2579     public void testReconnect() throws Exception {
2580         when(mWifiService.reconnect(anyString())).thenReturn(true);
2581         assertTrue(mWifiManager.reconnect());
2582         verify(mWifiService).reconnect(mContext.getOpPackageName());
2583     }
2584 
2585     /**
2586      * Test behavior of {@link WifiManager#reassociate()}
2587      */
2588     @Test
testReassociate()2589     public void testReassociate() throws Exception {
2590         when(mWifiService.reassociate(anyString())).thenReturn(true);
2591         assertTrue(mWifiManager.reassociate());
2592         verify(mWifiService).reassociate(mContext.getOpPackageName());
2593     }
2594 
2595     /**
2596      * Test behavior of {@link WifiManager#getSupportedFeatures()}
2597      */
2598     @Test
testGetSupportedFeatures()2599     public void testGetSupportedFeatures() throws Exception {
2600         long supportedFeatures =
2601                 WIFI_FEATURE_SCANNER
2602                         | WIFI_FEATURE_PASSPOINT
2603                         | WIFI_FEATURE_P2P;
2604         when(mWifiService.getSupportedFeatures())
2605                 .thenReturn(Long.valueOf(supportedFeatures));
2606 
2607         assertTrue(mWifiManager.isWifiScannerSupported());
2608         assertTrue(mWifiManager.isPasspointSupported());
2609         assertTrue(mWifiManager.isP2pSupported());
2610         assertFalse(mWifiManager.isPortableHotspotSupported());
2611         assertFalse(mWifiManager.isDeviceToDeviceRttSupported());
2612         assertFalse(mWifiManager.isDeviceToApRttSupported());
2613         assertFalse(mWifiManager.isPreferredNetworkOffloadSupported());
2614         assertFalse(mWifiManager.isTdlsSupported());
2615         assertFalse(mWifiManager.isOffChannelTdlsSupported());
2616         assertFalse(mWifiManager.isEnhancedPowerReportingSupported());
2617     }
2618 
2619     /**
2620      * Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync}
2621      * throws an exception.
2622      */
2623     @Test(expected = NullPointerException.class)
testGetWifiActivityInfoNullExecutor()2624     public void testGetWifiActivityInfoNullExecutor() throws Exception {
2625         mWifiManager.getWifiActivityEnergyInfoAsync(null, mOnWifiActivityEnergyInfoListener);
2626     }
2627 
2628     /**
2629      * Tests that passing a null listener to {@link WifiManager#getWifiActivityEnergyInfoAsync}
2630      * throws an exception.
2631      */
2632     @Test(expected = NullPointerException.class)
testGetWifiActivityInfoNullListener()2633     public void testGetWifiActivityInfoNullListener() throws Exception {
2634         mWifiManager.getWifiActivityEnergyInfoAsync(mExecutor, null);
2635     }
2636 
2637     /** Tests that the listener runs on the correct Executor. */
2638     @Test
testGetWifiActivityInfoRunsOnCorrectExecutor()2639     public void testGetWifiActivityInfoRunsOnCorrectExecutor() throws Exception {
2640         mWifiManager.getWifiActivityEnergyInfoAsync(mExecutor, mOnWifiActivityEnergyInfoListener);
2641         ArgumentCaptor<IOnWifiActivityEnergyInfoListener> listenerCaptor =
2642                 ArgumentCaptor.forClass(IOnWifiActivityEnergyInfoListener.class);
2643         verify(mWifiService).getWifiActivityEnergyInfoAsync(listenerCaptor.capture());
2644         IOnWifiActivityEnergyInfoListener listener = listenerCaptor.getValue();
2645         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2646         verify(mExecutor).execute(any());
2647 
2648         // ensure that the executor is only triggered once
2649         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2650         verify(mExecutor).execute(any());
2651     }
2652 
2653     /** Tests that the correct listener runs. */
2654     @Test
testGetWifiActivityInfoRunsCorrectListener()2655     public void testGetWifiActivityInfoRunsCorrectListener() throws Exception {
2656         int[] flag = {0};
2657         mWifiManager.getWifiActivityEnergyInfoAsync(
2658                 new SynchronousExecutor(), info -> flag[0]++);
2659         ArgumentCaptor<IOnWifiActivityEnergyInfoListener> listenerCaptor =
2660                 ArgumentCaptor.forClass(IOnWifiActivityEnergyInfoListener.class);
2661         verify(mWifiService).getWifiActivityEnergyInfoAsync(listenerCaptor.capture());
2662         IOnWifiActivityEnergyInfoListener listener = listenerCaptor.getValue();
2663         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2664         assertEquals(1, flag[0]);
2665 
2666         // ensure that the listener is only triggered once
2667         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2668         assertEquals(1, flag[0]);
2669     }
2670 
2671     /**
2672      * Test behavior of {@link WifiManager#getConnectionInfo()}
2673      */
2674     @Test
testGetConnectionInfo()2675     public void testGetConnectionInfo() throws Exception {
2676         WifiInfo wifiInfo = new WifiInfo();
2677         when(mWifiService.getConnectionInfo(anyString(), nullable(String.class))).thenReturn(
2678                 wifiInfo);
2679 
2680         assertEquals(wifiInfo, mWifiManager.getConnectionInfo());
2681     }
2682 
2683     /**
2684      * Test behavior of {@link WifiManager#is24GHzBandSupported()}
2685      */
2686     @Test
testIs24GHzBandSupported()2687     public void testIs24GHzBandSupported() throws Exception {
2688         when(mWifiService.is24GHzBandSupported()).thenReturn(true);
2689         assertTrue(mWifiManager.is24GHzBandSupported());
2690         verify(mWifiService).is24GHzBandSupported();
2691     }
2692 
2693     /**
2694      * Test behavior of {@link WifiManager#is5GHzBandSupported()}
2695      */
2696     @Test
testIs5GHzBandSupported()2697     public void testIs5GHzBandSupported() throws Exception {
2698         when(mWifiService.is5GHzBandSupported()).thenReturn(true);
2699         assertTrue(mWifiManager.is5GHzBandSupported());
2700         verify(mWifiService).is5GHzBandSupported();
2701     }
2702 
2703     /**
2704      * Test behavior of {@link WifiManager#is6GHzBandSupported()}
2705      */
2706     @Test
testIs6GHzBandSupported()2707     public void testIs6GHzBandSupported() throws Exception {
2708         when(mWifiService.is6GHzBandSupported()).thenReturn(true);
2709         assertTrue(mWifiManager.is6GHzBandSupported());
2710         verify(mWifiService).is6GHzBandSupported();
2711     }
2712 
2713     /**
2714      * Test behavior of {@link WifiManager#is60GHzBandSupported()}
2715      */
2716     @Test
testIs60GHzBandSupported()2717     public void testIs60GHzBandSupported() throws Exception {
2718         assumeTrue(SdkLevel.isAtLeastS());
2719 
2720         when(mWifiService.is60GHzBandSupported()).thenReturn(true);
2721         assertTrue(mWifiManager.is60GHzBandSupported());
2722         verify(mWifiService).is60GHzBandSupported();
2723     }
2724 
2725     /**
2726      * Test behavior of {@link WifiManager#isWifiStandardSupported()}
2727      */
2728     @Test
testIsWifiStandardSupported()2729     public void testIsWifiStandardSupported() throws Exception {
2730         int standard = ScanResult.WIFI_STANDARD_11AX;
2731         when(mWifiService.isWifiStandardSupported(standard)).thenReturn(true);
2732         assertTrue(mWifiManager.isWifiStandardSupported(standard));
2733         verify(mWifiService).isWifiStandardSupported(standard);
2734     }
2735 
2736     /**
2737      * Test behavior of {@link WifiManager#getDhcpInfo()}
2738      */
2739     @Test
testGetDhcpInfo()2740     public void testGetDhcpInfo() throws Exception {
2741         DhcpInfo dhcpInfo = new DhcpInfo();
2742 
2743         when(mWifiService.getDhcpInfo(TEST_PACKAGE_NAME)).thenReturn(dhcpInfo);
2744         assertEquals(dhcpInfo, mWifiManager.getDhcpInfo());
2745         verify(mWifiService).getDhcpInfo(TEST_PACKAGE_NAME);
2746     }
2747 
2748     /**
2749      * Test behavior of {@link WifiManager#setWifiEnabled(boolean)}
2750      */
2751     @Test
testSetWifiEnabled()2752     public void testSetWifiEnabled() throws Exception {
2753         when(mWifiService.setWifiEnabled(anyString(), anyBoolean())).thenReturn(true);
2754         assertTrue(mWifiManager.setWifiEnabled(true));
2755         verify(mWifiService).setWifiEnabled(mContext.getOpPackageName(), true);
2756         assertTrue(mWifiManager.setWifiEnabled(false));
2757         verify(mWifiService).setWifiEnabled(mContext.getOpPackageName(), false);
2758     }
2759 
2760     /**
2761      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
2762      */
2763     @Test
testConnectWithListener()2764     public void testConnectWithListener() throws Exception {
2765         ActionListener externalListener = mock(ActionListener.class);
2766         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
2767 
2768         ArgumentCaptor<IActionListener> binderListenerCaptor =
2769                 ArgumentCaptor.forClass(IActionListener.class);
2770         verify(mWifiService).connect(eq(null), eq(TEST_NETWORK_ID), binderListenerCaptor.capture());
2771         assertNotNull(binderListenerCaptor.getValue());
2772 
2773         // Trigger on success.
2774         binderListenerCaptor.getValue().onSuccess();
2775         mLooper.dispatchAll();
2776         verify(externalListener).onSuccess();
2777 
2778         // Trigger on failure.
2779         binderListenerCaptor.getValue().onFailure(BUSY);
2780         mLooper.dispatchAll();
2781         verify(externalListener).onFailure(BUSY);
2782     }
2783 
2784     /**
2785      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
2786      */
2787     @Test
testConnectWithListenerHandleSecurityException()2788     public void testConnectWithListenerHandleSecurityException() throws Exception {
2789         doThrow(new SecurityException()).when(mWifiService)
2790                 .connect(eq(null), anyInt(), any(IActionListener.class));
2791         ActionListener externalListener = mock(ActionListener.class);
2792         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
2793 
2794         mLooper.dispatchAll();
2795         verify(externalListener).onFailure(NOT_AUTHORIZED);
2796     }
2797 
2798     /**
2799      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
2800      */
2801     @Test
testConnectWithListenerHandleRemoteException()2802     public void testConnectWithListenerHandleRemoteException() throws Exception {
2803         doThrow(new RemoteException()).when(mWifiService)
2804                 .connect(eq(null), anyInt(), any(IActionListener.class));
2805         ActionListener externalListener = mock(ActionListener.class);
2806         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
2807 
2808         mLooper.dispatchAll();
2809         verify(externalListener).onFailure(ERROR);
2810     }
2811 
2812     /**
2813      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
2814      */
2815     @Test
testConnectWithoutListener()2816     public void testConnectWithoutListener() throws Exception {
2817         WifiConfiguration configuration = new WifiConfiguration();
2818         mWifiManager.connect(configuration, null);
2819 
2820         verify(mWifiService).connect(configuration, WifiConfiguration.INVALID_NETWORK_ID, null);
2821     }
2822 
2823     /**
2824      * Verify an IllegalArgumentException is thrown if callback is not provided.
2825      */
2826     @Test(expected = IllegalArgumentException.class)
testRegisterScanResultsCallbackWithNullCallback()2827     public void testRegisterScanResultsCallbackWithNullCallback() throws Exception {
2828         mWifiManager.registerScanResultsCallback(mExecutor, null);
2829     }
2830 
2831     /**
2832      * Verify an IllegalArgumentException is thrown if executor is not provided.
2833      */
2834     @Test(expected = IllegalArgumentException.class)
testRegisterCallbackWithNullExecutor()2835     public void testRegisterCallbackWithNullExecutor() throws Exception {
2836         mWifiManager.registerScanResultsCallback(null, mScanResultsCallback);
2837     }
2838 
2839     /**
2840      * Verify client provided callback is being called to the right callback.
2841      */
2842     @Test
testAddScanResultsCallbackAndReceiveEvent()2843     public void testAddScanResultsCallbackAndReceiveEvent() throws Exception {
2844         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
2845                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
2846         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
2847         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
2848         callbackCaptor.getValue().onScanResultsAvailable();
2849         verify(mRunnable).run();
2850     }
2851 
2852     /**
2853      * Verify client provided callback is being called to the right executor.
2854      */
2855     @Test
testRegisterScanResultsCallbackWithTheTargetExecutor()2856     public void testRegisterScanResultsCallbackWithTheTargetExecutor() throws Exception {
2857         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
2858                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
2859         mWifiManager.registerScanResultsCallback(mExecutor, mScanResultsCallback);
2860         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
2861         mWifiManager.registerScanResultsCallback(mAnotherExecutor, mScanResultsCallback);
2862         callbackCaptor.getValue().onScanResultsAvailable();
2863         verify(mExecutor, never()).execute(any(Runnable.class));
2864         verify(mAnotherExecutor).execute(any(Runnable.class));
2865     }
2866 
2867     /**
2868      * Verify client register unregister then register again, to ensure callback still works.
2869      */
2870     @Test
testRegisterUnregisterThenRegisterAgainWithScanResultCallback()2871     public void testRegisterUnregisterThenRegisterAgainWithScanResultCallback() throws Exception {
2872         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
2873                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
2874         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
2875         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
2876         mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
2877         callbackCaptor.getValue().onScanResultsAvailable();
2878         verify(mRunnable, never()).run();
2879         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
2880         callbackCaptor.getValue().onScanResultsAvailable();
2881         verify(mRunnable).run();
2882     }
2883 
2884     /**
2885      * Verify client unregisterScanResultsCallback.
2886      */
2887     @Test
testUnregisterScanResultsCallback()2888     public void testUnregisterScanResultsCallback() throws Exception {
2889         mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
2890         verify(mWifiService).unregisterScanResultsCallback(any());
2891     }
2892 
2893     /**
2894      * Verify client unregisterScanResultsCallback with null callback will cause an exception.
2895      */
2896     @Test(expected = IllegalArgumentException.class)
testUnregisterScanResultsCallbackWithNullCallback()2897     public void testUnregisterScanResultsCallbackWithNullCallback() throws Exception {
2898         mWifiManager.unregisterScanResultsCallback(null);
2899     }
2900 
2901     /**
2902      * Verify an IllegalArgumentException is thrown if executor not provided.
2903      */
2904     @Test(expected = IllegalArgumentException.class)
testAddSuggestionConnectionStatusListenerWithNullExecutor()2905     public void testAddSuggestionConnectionStatusListenerWithNullExecutor() {
2906         mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener);
2907     }
2908 
2909     /**
2910      * Verify an IllegalArgumentException is thrown if listener is not provided.
2911      */
2912     @Test(expected = IllegalArgumentException.class)
testAddSuggestionConnectionStatusListenerWithNullListener()2913     public void testAddSuggestionConnectionStatusListenerWithNullListener() {
2914         mWifiManager.addSuggestionConnectionStatusListener(mExecutor, null);
2915     }
2916 
2917     /**
2918      * Verify client provided listener is being called to the right listener.
2919      */
2920     @Test
testAddSuggestionConnectionStatusListenerAndReceiveEvent()2921     public void testAddSuggestionConnectionStatusListenerAndReceiveEvent() throws Exception {
2922         int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
2923         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
2924                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
2925         Executor executor = new SynchronousExecutor();
2926         mWifiManager.addSuggestionConnectionStatusListener(executor, mSuggestionConnectionListener);
2927         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
2928                 anyString(), nullable(String.class));
2929         callbackCaptor.getValue().onConnectionStatus(mWifiNetworkSuggestion, errorCode);
2930         verify(mSuggestionConnectionListener).onConnectionStatus(any(WifiNetworkSuggestion.class),
2931                 eq(errorCode));
2932     }
2933 
2934     /**
2935      * Verify client provided listener is being called to the right executor.
2936      */
2937     @Test
testAddSuggestionConnectionStatusListenerWithTheTargetExecutor()2938     public void testAddSuggestionConnectionStatusListenerWithTheTargetExecutor() throws Exception {
2939         int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
2940         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
2941                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
2942         mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
2943                 mSuggestionConnectionListener);
2944         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
2945                 anyString(), nullable(String.class));
2946         callbackCaptor.getValue().onConnectionStatus(any(WifiNetworkSuggestion.class), errorCode);
2947         verify(mExecutor).execute(any(Runnable.class));
2948     }
2949 
2950     /**
2951      * Verify an IllegalArgumentException is thrown if listener is not provided.
2952      */
2953     @Test(expected = IllegalArgumentException.class)
testRemoveSuggestionConnectionListenerWithNullListener()2954     public void testRemoveSuggestionConnectionListenerWithNullListener() {
2955         mWifiManager.removeSuggestionConnectionStatusListener(null);
2956     }
2957 
2958     /**
2959      * Verify removeSuggestionConnectionListener.
2960      */
2961     @Test
testRemoveSuggestionConnectionListener()2962     public void testRemoveSuggestionConnectionListener() throws Exception {
2963         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
2964                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
2965         mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
2966                 mSuggestionConnectionListener);
2967         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
2968                 anyString(), nullable(String.class));
2969 
2970         mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener);
2971         verify(mWifiService).unregisterSuggestionConnectionStatusListener(
2972                 eq(callbackCaptor.getValue()), anyString());
2973     }
2974 
2975     /** Test {@link WifiManager#calculateSignalLevel(int)} */
2976     @Test
testCalculateSignalLevel()2977     public void testCalculateSignalLevel() throws Exception {
2978         when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(3);
2979         int actual = mWifiManager.calculateSignalLevel(-60);
2980         verify(mWifiService).calculateSignalLevel(-60);
2981         assertEquals(3, actual);
2982     }
2983 
2984     /** Test {@link WifiManager#getMaxSignalLevel()} */
2985     @Test
testGetMaxSignalLevel()2986     public void testGetMaxSignalLevel() throws Exception {
2987         when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(4);
2988         int actual = mWifiManager.getMaxSignalLevel();
2989         verify(mWifiService).calculateSignalLevel(Integer.MAX_VALUE);
2990         assertEquals(4, actual);
2991     }
2992 
2993     /*
2994      * Test behavior of isWapiSupported
2995      * @throws Exception
2996      */
2997     @Test
testIsWapiSupported()2998     public void testIsWapiSupported() throws Exception {
2999         when(mWifiService.getSupportedFeatures())
3000                 .thenReturn(new Long(WifiManager.WIFI_FEATURE_WAPI));
3001         assertTrue(mWifiManager.isWapiSupported());
3002         when(mWifiService.getSupportedFeatures())
3003                 .thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI));
3004         assertFalse(mWifiManager.isWapiSupported());
3005     }
3006 
3007     /*
3008      * Test that DPP channel list is parsed correctly
3009      */
3010     @Test
testparseDppChannelList()3011     public void testparseDppChannelList() throws Exception {
3012         String channelList = "81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48";
3013         SparseArray<int[]> expectedResult = new SparseArray<>();
3014         expectedResult.append(81, new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
3015         expectedResult.append(115, new int[]{36, 40, 44, 48});
3016 
3017         SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
3018         assertEquals(expectedResult.size(), result.size());
3019 
3020         int index = 0;
3021         int key;
3022 
3023         // Compare the two primitive int arrays
3024         do {
3025             try {
3026                 key = result.keyAt(index);
3027             } catch (java.lang.ArrayIndexOutOfBoundsException e) {
3028                 break;
3029             }
3030             int[] expected = expectedResult.get(key);
3031             int[] output = result.get(key);
3032             assertEquals(expected.length, output.length);
3033             for (int i = 0; i < output.length; i++) {
3034                 assertEquals(expected[i], output[i]);
3035             }
3036             index++;
3037         } while (true);
3038     }
3039 
3040     /*
3041      * Test that DPP channel list parser gracefully fails for invalid input
3042      */
3043     @Test
testparseDppChannelListWithInvalidFormats()3044     public void testparseDppChannelListWithInvalidFormats() throws Exception {
3045         String channelList = "1,2,3,4,5,6,7,8,9,10,11,36,40,44,48";
3046         SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
3047         assertEquals(result.size(), 0);
3048 
3049         channelList = "ajgalskgjalskjg3-09683dh";
3050         result = WifiManager.parseDppChannelList(channelList);
3051         assertEquals(result.size(), 0);
3052 
3053         channelList = "13/abc,46////";
3054         result = WifiManager.parseDppChannelList(channelList);
3055         assertEquals(result.size(), 0);
3056 
3057         channelList = "11/4,5,13/";
3058         result = WifiManager.parseDppChannelList(channelList);
3059         assertEquals(result.size(), 0);
3060 
3061         channelList = "/24,6";
3062         result = WifiManager.parseDppChannelList(channelList);
3063         assertEquals(result.size(), 0);
3064     }
3065 
3066     /**
3067      * Test getWifiConfigsForMatchedNetworkSuggestions for given scanResults.
3068      */
3069     @Test
testGetWifiConfigsForMatchedNetworkSuggestions()3070     public void testGetWifiConfigsForMatchedNetworkSuggestions() throws Exception {
3071         List<WifiConfiguration> testResults = new ArrayList<>();
3072         testResults.add(new WifiConfiguration());
3073 
3074         when(mWifiService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any(List.class)))
3075                 .thenReturn(testResults);
3076         assertEquals(testResults, mWifiManager
3077                 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()));
3078     }
3079 
3080     /**
3081      * Verify the call to setWifiConnectedNetworkScorer goes to WifiServiceImpl.
3082      */
3083     @Test
setWifiConnectedNetworkScorerGoesToWifiServiceImpl()3084     public void setWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception {
3085         mExecutor = new SynchronousExecutor();
3086         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3087         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3088                 any(IWifiConnectedNetworkScorer.Stub.class));
3089     }
3090 
3091     /**
3092      * Verify the call to clearWifiConnectedNetworkScorer goes to WifiServiceImpl.
3093      */
3094     @Test
clearWifiConnectedNetworkScorerGoesToWifiServiceImpl()3095     public void clearWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception {
3096         mExecutor = new SynchronousExecutor();
3097         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3098         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3099                 any(IWifiConnectedNetworkScorer.Stub.class));
3100 
3101         mWifiManager.clearWifiConnectedNetworkScorer();
3102         verify(mWifiService).clearWifiConnectedNetworkScorer();
3103     }
3104 
3105     /**
3106      * Verify that Wi-Fi connected scorer receives score update observer after registeration.
3107      */
3108     @Test
verifyScorerReceiveScoreUpdateObserverAfterRegistration()3109     public void verifyScorerReceiveScoreUpdateObserverAfterRegistration() throws Exception {
3110         mExecutor = new SynchronousExecutor();
3111         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3112         ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> scorerCaptor =
3113                 ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class);
3114         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3115                 scorerCaptor.capture());
3116         scorerCaptor.getValue().onSetScoreUpdateObserver(any());
3117         mLooper.dispatchAll();
3118         verify(mWifiConnectedNetworkScorer).onSetScoreUpdateObserver(any());
3119     }
3120 
3121     /**
3122      * Verify that Wi-Fi connected scorer receives session ID when onStart/onStop methods
3123      * are called.
3124      */
3125     @Test
verifyScorerReceiveSessionIdWhenStartStopIsCalled()3126     public void verifyScorerReceiveSessionIdWhenStartStopIsCalled() throws Exception {
3127         mExecutor = new SynchronousExecutor();
3128         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3129         ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> callbackCaptor =
3130                 ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class);
3131         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3132                 callbackCaptor.capture());
3133         callbackCaptor.getValue().onStart(new WifiConnectedSessionInfo.Builder(10)
3134                 .setUserSelected(true)
3135                 .build());
3136         callbackCaptor.getValue().onStop(10);
3137         mLooper.dispatchAll();
3138         verify(mWifiConnectedNetworkScorer).onStart(
3139                 argThat(sessionInfo -> sessionInfo.getSessionId() == 10
3140                         && sessionInfo.isUserSelected()));
3141         verify(mWifiConnectedNetworkScorer).onStop(10);
3142     }
3143 
3144     /**
3145      * Verify the call to setWifiScoringEnabled goes to WifiServiceImpl.
3146      */
3147     @Test
setWifiScoringEnabledGoesToWifiServiceImpl()3148     public void setWifiScoringEnabledGoesToWifiServiceImpl() throws Exception {
3149         mWifiManager.setWifiScoringEnabled(true);
3150         verify(mWifiService).setWifiScoringEnabled(true);
3151     }
3152 
3153     @Test
testScanThrottle()3154     public void testScanThrottle() throws Exception {
3155         mWifiManager.setScanThrottleEnabled(true);
3156         verify(mWifiService).setScanThrottleEnabled(true);
3157 
3158         when(mWifiService.isScanThrottleEnabled()).thenReturn(false);
3159         assertFalse(mWifiManager.isScanThrottleEnabled());
3160         verify(mWifiService).isScanThrottleEnabled();
3161     }
3162 
3163     @Test
testAutoWakeup()3164     public void testAutoWakeup() throws Exception {
3165         mWifiManager.setAutoWakeupEnabled(true);
3166         verify(mWifiService).setAutoWakeupEnabled(true);
3167 
3168         when(mWifiService.isAutoWakeupEnabled()).thenReturn(false);
3169         assertFalse(mWifiManager.isAutoWakeupEnabled());
3170         verify(mWifiService).isAutoWakeupEnabled();
3171     }
3172 
3173 
3174     @Test
testScanAvailable()3175     public void testScanAvailable() throws Exception {
3176         mWifiManager.setScanAlwaysAvailable(true);
3177         verify(mWifiService).setScanAlwaysAvailable(true, TEST_PACKAGE_NAME);
3178 
3179         when(mWifiService.isScanAlwaysAvailable()).thenReturn(false);
3180         assertFalse(mWifiManager.isScanAlwaysAvailable());
3181         verify(mWifiService).isScanAlwaysAvailable();
3182     }
3183 
3184     @Test
testSetCarrierNetworkOffload()3185     public void testSetCarrierNetworkOffload() throws Exception {
3186         mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, true, false);
3187         verify(mWifiService).setCarrierNetworkOffloadEnabled(TEST_SUB_ID,
3188                 true, false);
3189     }
3190 
3191     @Test
testGetCarrierNetworkOffload()3192     public void testGetCarrierNetworkOffload() throws Exception {
3193         when(mWifiService.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)).thenReturn(true);
3194         assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false));
3195         verify(mWifiService).isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false);
3196     }
3197 
3198 
3199     /**
3200      * Verify an IllegalArgumentException is thrown if listener is not provided.
3201      */
3202     @Test(expected = IllegalArgumentException.class)
testRemoveSuggestionUserApprovalStatusListenerWithNullListener()3203     public void testRemoveSuggestionUserApprovalStatusListenerWithNullListener() {
3204         mWifiManager.removeSuggestionUserApprovalStatusListener(null);
3205     }
3206 
3207 
3208     /**
3209      * Verify removeSuggestionUserApprovalStatusListener.
3210      */
3211     @Test
testRemoveSuggestionUserApprovalStatusListener()3212     public void testRemoveSuggestionUserApprovalStatusListener() throws Exception {
3213         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3214                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3215         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
3216                 mSuggestionUserApprovalStatusListener);
3217         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3218                 anyString());
3219 
3220         mWifiManager.removeSuggestionUserApprovalStatusListener(
3221                 mSuggestionUserApprovalStatusListener);
3222         verify(mWifiService).removeSuggestionUserApprovalStatusListener(
3223                 eq(callbackCaptor.getValue()), anyString());
3224     }
3225 
3226     /**
3227      * Verify an IllegalArgumentException is thrown if executor not provided.
3228      */
3229     @Test(expected = NullPointerException.class)
testAddSuggestionUserApprovalStatusListenerWithNullExecutor()3230     public void testAddSuggestionUserApprovalStatusListenerWithNullExecutor() {
3231         mWifiManager.addSuggestionUserApprovalStatusListener(null,
3232                 mSuggestionUserApprovalStatusListener);
3233     }
3234 
3235     /**
3236      * Verify an IllegalArgumentException is thrown if listener is not provided.
3237      */
3238     @Test(expected = NullPointerException.class)
testAddSuggestionUserApprovalStatusListenerWithNullListener()3239     public void testAddSuggestionUserApprovalStatusListenerWithNullListener() {
3240         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, null);
3241     }
3242 
3243     /**
3244      * Verify client provided listener is being called to the right listener.
3245      */
3246     @Test
testAddSuggestionUserApprovalStatusListenerAndReceiveEvent()3247     public void testAddSuggestionUserApprovalStatusListenerAndReceiveEvent() throws Exception {
3248         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3249                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3250         Executor executor = new SynchronousExecutor();
3251         mWifiManager.addSuggestionUserApprovalStatusListener(executor,
3252                 mSuggestionUserApprovalStatusListener);
3253         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3254                 anyString());
3255         callbackCaptor.getValue().onUserApprovalStatusChange(
3256                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3257         verify(mSuggestionUserApprovalStatusListener).onUserApprovalStatusChange(
3258                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3259     }
3260 
3261     /**
3262      * Verify client provided listener is being called to the right executor.
3263      */
3264     @Test
testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()3265     public void testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()
3266             throws Exception {
3267         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3268                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3269         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
3270                 mSuggestionUserApprovalStatusListener);
3271         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3272                 anyString());
3273         callbackCaptor.getValue().onUserApprovalStatusChange(
3274                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3275         verify(mExecutor).execute(any(Runnable.class));
3276     }
3277 
3278     @Test
testSetEmergencyScanRequestInProgress()3279     public void testSetEmergencyScanRequestInProgress() throws Exception {
3280         mWifiManager.setEmergencyScanRequestInProgress(true);
3281         verify(mWifiService).setEmergencyScanRequestInProgress(true);
3282 
3283         mWifiManager.setEmergencyScanRequestInProgress(false);
3284         verify(mWifiService).setEmergencyScanRequestInProgress(false);
3285     }
3286 
3287     @Test
testRemoveAppState()3288     public void testRemoveAppState() throws Exception {
3289         mWifiManager.removeAppState(TEST_UID, TEST_PACKAGE_NAME);
3290         verify(mWifiService).removeAppState(TEST_UID, TEST_PACKAGE_NAME);
3291     }
3292 
3293     /**
3294      * Test behavior of isPasspointTermsAndConditionsSupported
3295      */
3296     @Test
testIsPasspointTermsAndConditionsSupported()3297     public void testIsPasspointTermsAndConditionsSupported() throws Exception {
3298         when(mWifiService.getSupportedFeatures())
3299                 .thenReturn(new Long(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
3300         assertTrue(mWifiManager.isPasspointTermsAndConditionsSupported());
3301         when(mWifiService.getSupportedFeatures())
3302                 .thenReturn(new Long(~WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
3303         assertFalse(mWifiManager.isPasspointTermsAndConditionsSupported());
3304     }
3305 
3306     /**
3307      * Verify the call to setOverrideCountryCode goes to WifiServiceImpl.
3308      */
3309     @Test
testSetOverrideCountryCode()3310     public void testSetOverrideCountryCode() throws Exception {
3311         assumeTrue(SdkLevel.isAtLeastS());
3312         mWifiManager.setOverrideCountryCode(TEST_COUNTRY_CODE);
3313         verify(mWifiService).setOverrideCountryCode(eq(TEST_COUNTRY_CODE));
3314     }
3315 
3316     /**
3317      * Verify the call to clearOverrideCountryCode goes to WifiServiceImpl.
3318      */
3319     @Test
testClearOverrideCountryCode()3320     public void testClearOverrideCountryCode() throws Exception {
3321         assumeTrue(SdkLevel.isAtLeastS());
3322         mWifiManager.clearOverrideCountryCode();
3323         verify(mWifiService).clearOverrideCountryCode();
3324     }
3325 
3326     /**
3327      * Verify the call to setDefaultCountryCode goes to WifiServiceImpl.
3328      */
3329     @Test
testSetDefaultCountryCode()3330     public void testSetDefaultCountryCode() throws Exception {
3331         assumeTrue(SdkLevel.isAtLeastS());
3332         mWifiManager.setDefaultCountryCode(TEST_COUNTRY_CODE);
3333         verify(mWifiService).setDefaultCountryCode(eq(TEST_COUNTRY_CODE));
3334     }
3335 
3336     /**
3337      * Test behavior of flushPasspointAnqpCache
3338      */
3339     @Test
testFlushPasspointAnqpCache()3340     public void testFlushPasspointAnqpCache() throws Exception {
3341         mWifiManager.flushPasspointAnqpCache();
3342         verify(mWifiService).flushPasspointAnqpCache(anyString());
3343     }
3344 
3345     /**
3346      * Test behavior of isDecoratedIdentitySupported
3347      */
3348     @Test
testIsDecoratedIdentitySupported()3349     public void testIsDecoratedIdentitySupported() throws Exception {
3350         when(mWifiService.getSupportedFeatures())
3351                 .thenReturn(new Long(WIFI_FEATURE_DECORATED_IDENTITY));
3352         assertTrue(mWifiManager.isDecoratedIdentitySupported());
3353         when(mWifiService.getSupportedFeatures())
3354                 .thenReturn(new Long(~WIFI_FEATURE_DECORATED_IDENTITY));
3355         assertFalse(mWifiManager.isDecoratedIdentitySupported());
3356     }
3357 
3358     /**
3359      * Verify call to getAllowedChannels goes to WifiServiceImpl
3360      */
3361     @Test
testGetAllowedChannels()3362     public void testGetAllowedChannels() throws Exception {
3363         assumeTrue(SdkLevel.isAtLeastS());
3364         int band = WifiScanner.WIFI_BAND_24_5_6_GHZ;
3365         int mode = WifiAvailableChannel.OP_MODE_WIFI_AWARE
3366                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO
3367                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI;
3368         mWifiManager.getAllowedChannels(band, mode);
3369         verify(mWifiService).getUsableChannels(eq(band), eq(mode),
3370                 eq(WifiAvailableChannel.FILTER_REGULATORY));
3371     }
3372 
3373     /**
3374      * Verify call to getUsableChannels goes to WifiServiceImpl
3375      */
3376     @Test
testGetUsableChannels()3377     public void testGetUsableChannels() throws Exception {
3378         assumeTrue(SdkLevel.isAtLeastS());
3379         int band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
3380         int mode = WifiAvailableChannel.OP_MODE_WIFI_AWARE
3381                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI;
3382         mWifiManager.getUsableChannels(band, mode);
3383         verify(mWifiService).getUsableChannels(eq(band), eq(mode),
3384                 eq(WifiAvailableChannel.FILTER_CONCURRENCY
3385                     | WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE));
3386     }
3387 }
3388