• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ACTION_REMOVE_SUGGESTION_DISCONNECT;
21 import static android.net.wifi.WifiManager.ACTION_REMOVE_SUGGESTION_LINGER;
22 import static android.net.wifi.WifiManager.ActionListener;
23 import static android.net.wifi.WifiManager.COEX_RESTRICTION_SOFTAP;
24 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_AWARE;
25 import static android.net.wifi.WifiManager.COEX_RESTRICTION_WIFI_DIRECT;
26 import static android.net.wifi.WifiManager.EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE;
27 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
28 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
29 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
30 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
31 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED;
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.VERBOSE_LOGGING_LEVEL_DISABLED;
37 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED;
38 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY;
39 import static android.net.wifi.WifiManager.VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY;
40 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
41 import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;
42 import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
43 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY;
44 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MBB;
45 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET;
46 import static android.net.wifi.WifiManager.WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED;
47 import static android.net.wifi.WifiManager.WIFI_FEATURE_AP_STA;
48 import static android.net.wifi.WifiManager.WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED;
49 import static android.net.wifi.WifiManager.WIFI_FEATURE_DECORATED_IDENTITY;
50 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP;
51 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_AKM;
52 import static android.net.wifi.WifiManager.WIFI_FEATURE_DPP_ENROLLEE_RESPONDER;
53 import static android.net.wifi.WifiManager.WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS;
54 import static android.net.wifi.WifiManager.WIFI_FEATURE_OWE;
55 import static android.net.wifi.WifiManager.WIFI_FEATURE_P2P;
56 import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT;
57 import static android.net.wifi.WifiManager.WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS;
58 import static android.net.wifi.WifiManager.WIFI_FEATURE_SCANNER;
59 import static android.net.wifi.WifiManager.WIFI_FEATURE_T2LM_NEGOTIATION;
60 import static android.net.wifi.WifiManager.WIFI_FEATURE_TRUST_ON_FIRST_USE;
61 import static android.net.wifi.WifiManager.WIFI_FEATURE_WEP;
62 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SAE;
63 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA3_SUITE_B;
64 import static android.net.wifi.WifiManager.WIFI_FEATURE_WPA_PERSONAL;
65 import static android.net.wifi.WifiManager.WpsCallback;
66 
67 import static org.junit.Assert.assertArrayEquals;
68 import static org.junit.Assert.assertEquals;
69 import static org.junit.Assert.assertFalse;
70 import static org.junit.Assert.assertNotNull;
71 import static org.junit.Assert.assertNull;
72 import static org.junit.Assert.assertThrows;
73 import static org.junit.Assert.assertTrue;
74 import static org.junit.Assert.fail;
75 import static org.junit.Assume.assumeTrue;
76 import static org.mockito.ArgumentMatchers.anyBoolean;
77 import static org.mockito.ArgumentMatchers.nullable;
78 import static org.mockito.Mockito.any;
79 import static org.mockito.Mockito.anyInt;
80 import static org.mockito.Mockito.anyList;
81 import static org.mockito.Mockito.anyString;
82 import static org.mockito.Mockito.argThat;
83 import static org.mockito.Mockito.doThrow;
84 import static org.mockito.Mockito.eq;
85 import static org.mockito.Mockito.inOrder;
86 import static org.mockito.Mockito.mock;
87 import static org.mockito.Mockito.never;
88 import static org.mockito.Mockito.reset;
89 import static org.mockito.Mockito.spy;
90 import static org.mockito.Mockito.times;
91 import static org.mockito.Mockito.verify;
92 import static org.mockito.Mockito.verifyNoMoreInteractions;
93 import static org.mockito.Mockito.verifyZeroInteractions;
94 import static org.mockito.Mockito.when;
95 
96 import android.annotation.NonNull;
97 import android.app.ActivityManager;
98 import android.content.AttributionSource;
99 import android.content.Context;
100 import android.content.pm.ApplicationInfo;
101 import android.net.DhcpInfo;
102 import android.net.DhcpOption;
103 import android.net.MacAddress;
104 import android.net.TetheringManager;
105 import android.net.wifi.WifiManager.ActiveCountryCodeChangedCallback;
106 import android.net.wifi.WifiManager.CoexCallback;
107 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
108 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver;
109 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation;
110 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription;
111 import android.net.wifi.WifiManager.NetworkRequestMatchCallback;
112 import android.net.wifi.WifiManager.NetworkRequestUserSelectionCallback;
113 import android.net.wifi.WifiManager.OnWifiUsabilityStatsListener;
114 import android.net.wifi.WifiManager.ScanResultsCallback;
115 import android.net.wifi.WifiManager.SoftApCallback;
116 import android.net.wifi.WifiManager.SubsystemRestartTrackingCallback;
117 import android.net.wifi.WifiManager.SuggestionConnectionStatusListener;
118 import android.net.wifi.WifiManager.SuggestionUserApprovalStatusListener;
119 import android.net.wifi.WifiManager.TrafficStateCallback;
120 import android.net.wifi.WifiManager.WifiConnectedNetworkScorer;
121 import android.net.wifi.WifiUsabilityStatsEntry.ContentionTimeStats;
122 import android.net.wifi.WifiUsabilityStatsEntry.LinkStats;
123 import android.net.wifi.WifiUsabilityStatsEntry.RadioStats;
124 import android.net.wifi.WifiUsabilityStatsEntry.RateStats;
125 import android.net.wifi.twt.TwtRequest;
126 import android.net.wifi.twt.TwtSessionCallback;
127 import android.os.Build;
128 import android.os.Bundle;
129 import android.os.Handler;
130 import android.os.IBinder;
131 import android.os.RemoteException;
132 import android.os.connectivity.WifiActivityEnergyInfo;
133 import android.os.test.TestLooper;
134 import android.util.ArraySet;
135 import android.util.SparseArray;
136 
137 import androidx.test.filters.SmallTest;
138 
139 import com.android.modules.utils.HandlerExecutor;
140 import com.android.modules.utils.build.SdkLevel;
141 
142 import org.junit.Before;
143 import org.junit.Test;
144 import org.mockito.ArgumentCaptor;
145 import org.mockito.InOrder;
146 import org.mockito.Mock;
147 import org.mockito.Mockito;
148 import org.mockito.MockitoAnnotations;
149 
150 import java.util.ArrayList;
151 import java.util.Arrays;
152 import java.util.Collections;
153 import java.util.HashMap;
154 import java.util.List;
155 import java.util.Map;
156 import java.util.Objects;
157 import java.util.Set;
158 import java.util.concurrent.Executor;
159 import java.util.function.BiConsumer;
160 import java.util.function.Consumer;
161 
162 /**
163  * Unit tests for {@link android.net.wifi.WifiManager}.
164  */
165 @SmallTest
166 public class WifiManagerTest {
167 
168     private static final int ERROR_NOT_SET = -1;
169     private static final int ERROR_TEST_REASON = 5;
170     private static final int TEST_UID = 14553;
171     private static final int TEST_NETWORK_ID = 143;
172     private static final String TEST_PACKAGE_NAME = "TestPackage";
173     private static final String TEST_FEATURE_ID = "TestFeature";
174     private static final String TEST_COUNTRY_CODE = "US";
175     private static final String[] TEST_MAC_ADDRESSES = {"da:a1:19:0:0:0"};
176     private static final int TEST_SUB_ID = 3;
177     private static final String[] TEST_AP_INSTANCES = new String[] {"wlan1", "wlan2"};
178     private static final int[] TEST_AP_FREQS = new int[] {2412, 5220};
179     private static final int[] TEST_AP_BWS = new int[] {SoftApInfo.CHANNEL_WIDTH_20MHZ_NOHT,
180             SoftApInfo.CHANNEL_WIDTH_80MHZ};
181     private static final MacAddress[] TEST_AP_BSSIDS = new MacAddress[] {
182             MacAddress.fromString("22:33:44:55:66:77"),
183             MacAddress.fromString("aa:bb:cc:dd:ee:ff")};
184     private static final MacAddress[] TEST_AP_CLIENTS = new MacAddress[] {
185             MacAddress.fromString("22:33:44:aa:aa:77"),
186             MacAddress.fromString("aa:bb:cc:11:11:ff"),
187             MacAddress.fromString("22:bb:cc:11:aa:ff")};
188     private static final String TEST_SSID = "\"Test WiFi Networks\"";
189     private static final byte[] TEST_OUI = new byte[]{0x01, 0x02, 0x03};
190     private static final int TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS = 1000;
191 
192     private static final TetheringManager.TetheringRequest TEST_TETHERING_REQUEST =
193             new TetheringManager.TetheringRequest.Builder(TetheringManager.TETHERING_WIFI).build();
194     private static final String TEST_INTERFACE_NAME = "test-wlan0";
195 
196     @Mock Context mContext;
197     @Mock android.net.wifi.IWifiManager mWifiService;
198     @Mock ApplicationInfo mApplicationInfo;
199     @Mock WifiConfiguration mApConfig;
200     @Mock SoftApCallback mSoftApCallback;
201     @Mock TrafficStateCallback mTrafficStateCallback;
202     @Mock NetworkRequestMatchCallback mNetworkRequestMatchCallback;
203     @Mock OnWifiUsabilityStatsListener mOnWifiUsabilityStatsListener;
204     @Mock OnWifiActivityEnergyInfoListener mOnWifiActivityEnergyInfoListener;
205     @Mock SuggestionConnectionStatusListener mSuggestionConnectionListener;
206     @Mock
207     WifiManager.LocalOnlyConnectionFailureListener mLocalOnlyConnectionFailureListener;
208     @Mock Runnable mRunnable;
209     @Mock Executor mExecutor;
210     @Mock Executor mAnotherExecutor;
211     @Mock ActivityManager mActivityManager;
212     @Mock WifiConnectedNetworkScorer mWifiConnectedNetworkScorer;
213     @Mock SuggestionUserApprovalStatusListener mSuggestionUserApprovalStatusListener;
214     @Mock ActiveCountryCodeChangedCallback mActiveCountryCodeChangedCallback;
215 
216     private Handler mHandler;
217     private TestLooper mLooper;
218     private WifiManager mWifiManager;
219     private WifiNetworkSuggestion mWifiNetworkSuggestion;
220     private ScanResultsCallback mScanResultsCallback;
221     private CoexCallback mCoexCallback;
222     private SubsystemRestartTrackingCallback mRestartCallback;
223     private int mRestartCallbackMethodRun = 0; // 1: restarting, 2: restarted
224     private WifiActivityEnergyInfo mWifiActivityEnergyInfo;
225 
226     private HashMap<String, SoftApInfo> mTestSoftApInfoMap = new HashMap<>();
227     private HashMap<String, List<WifiClient>> mTestWifiClientsMap = new HashMap<>();
228     private SoftApInfo mTestApInfo1 = new SoftApInfo();
229     private SoftApInfo mTestApInfo2 = new SoftApInfo();
230 
231     /**
232      * Util function to check public field which used for softap  in WifiConfiguration
233      * same as the value in SoftApConfiguration.
234      *
235      */
compareWifiAndSoftApConfiguration( SoftApConfiguration softApConfig, WifiConfiguration wifiConfig)236     private boolean compareWifiAndSoftApConfiguration(
237             SoftApConfiguration softApConfig, WifiConfiguration wifiConfig) {
238         // SoftApConfiguration#toWifiConfiguration() creates a config with an unquoted UTF-8 SSID
239         // instead of the double quoted behavior in the javadoc for WifiConfiguration#SSID. Thus,
240         // we need to compare the wifi config SSID directly with the unquoted UTF-8 text.
241         if (!Objects.equals(wifiConfig.SSID, softApConfig.getWifiSsid().getUtf8Text())) {
242             return false;
243         }
244         if (!Objects.equals(wifiConfig.BSSID, softApConfig.getBssid())) {
245             return false;
246         }
247         if (!Objects.equals(wifiConfig.preSharedKey, softApConfig.getPassphrase())) {
248             return false;
249         }
250 
251         if (wifiConfig.hiddenSSID != softApConfig.isHiddenSsid()) {
252             return false;
253         }
254         switch (softApConfig.getSecurityType()) {
255             case SoftApConfiguration.SECURITY_TYPE_OPEN:
256                 if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.NONE) {
257                     return false;
258                 }
259                 break;
260             case SoftApConfiguration.SECURITY_TYPE_WPA2_PSK:
261                 if (wifiConfig.getAuthType() != WifiConfiguration.KeyMgmt.WPA2_PSK) {
262                     return false;
263                 }
264                 break;
265             default:
266                 return false;
267         }
268         return true;
269     }
270 
generatorTestSoftApConfig()271     private SoftApConfiguration generatorTestSoftApConfig() {
272         return new SoftApConfiguration.Builder()
273                 .setSsid("TestSSID")
274                 .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA2_PSK)
275                 .build();
276     }
277 
initTestInfoAndAddToTestMap(int numberOfInfos)278     private void initTestInfoAndAddToTestMap(int numberOfInfos) {
279         if (numberOfInfos > 2) return;
280         for (int i = 0; i < numberOfInfos; i++) {
281             SoftApInfo info = mTestApInfo1;
282             if (i == 1) info = mTestApInfo2;
283             info.setFrequency(TEST_AP_FREQS[i]);
284             info.setBandwidth(TEST_AP_BWS[i]);
285             info.setBssid(TEST_AP_BSSIDS[i]);
286             info.setApInstanceIdentifier(TEST_AP_INSTANCES[i]);
287             mTestSoftApInfoMap.put(TEST_AP_INSTANCES[i], info);
288         }
289     }
290 
initWifiClientAndAddToTestMap(String targetInstance, int numberOfClients, int startIdx)291     private List<WifiClient> initWifiClientAndAddToTestMap(String targetInstance,
292             int numberOfClients, int startIdx) {
293         if (numberOfClients > 3) return null;
294         List<WifiClient> clients = new ArrayList<>();
295         for (int i = startIdx; i < startIdx + numberOfClients; i++) {
296             WifiClient client = new WifiClient(TEST_AP_CLIENTS[i], targetInstance);
297             clients.add(client);
298         }
299         mTestWifiClientsMap.put(targetInstance, clients);
300         return clients;
301     }
302 
303     @Before
setUp()304     public void setUp() throws Exception {
305         MockitoAnnotations.initMocks(this);
306         mLooper = new TestLooper();
307         mHandler = spy(new Handler(mLooper.getLooper()));
308         mApplicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
309         when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
310         when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
311         mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper());
312         verify(mWifiService).getVerboseLoggingLevel();
313         mWifiNetworkSuggestion = new WifiNetworkSuggestion();
314         mScanResultsCallback = new ScanResultsCallback() {
315             @Override
316             public void onScanResultsAvailable() {
317                 mRunnable.run();
318             }
319         };
320         if (SdkLevel.isAtLeastS()) {
321             mCoexCallback = new CoexCallback() {
322                 @Override
323                 public void onCoexUnsafeChannelsChanged(
324                         @NonNull List<CoexUnsafeChannel> unsafeChannels, int restrictions) {
325                     mRunnable.run();
326                 }
327             };
328             AttributionSource attributionSource = mock(AttributionSource.class);
329             when(mContext.getAttributionSource()).thenReturn(attributionSource);
330         }
331         mRestartCallback = new SubsystemRestartTrackingCallback() {
332             @Override
333             public void onSubsystemRestarting() {
334                 mRestartCallbackMethodRun = 1;
335                 mRunnable.run();
336             }
337 
338             @Override
339             public void onSubsystemRestarted() {
340                 mRestartCallbackMethodRun = 2;
341                 mRunnable.run();
342             }
343         };
344         mWifiActivityEnergyInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
345         mTestSoftApInfoMap.clear();
346         mTestWifiClientsMap.clear();
347     }
348 
349     /**
350      * Check the call to setCoexUnsafeChannels calls WifiServiceImpl to setCoexUnsafeChannels with
351      * the provided CoexUnsafeChannels and restrictions bitmask.
352      */
353     @Test
testSetCoexUnsafeChannelsGoesToWifiServiceImpl()354     public void testSetCoexUnsafeChannelsGoesToWifiServiceImpl() throws Exception {
355         assumeTrue(SdkLevel.isAtLeastS());
356         List<CoexUnsafeChannel> unsafeChannels = new ArrayList<>();
357         int restrictions = COEX_RESTRICTION_WIFI_DIRECT | COEX_RESTRICTION_SOFTAP
358                 | COEX_RESTRICTION_WIFI_AWARE;
359 
360         mWifiManager.setCoexUnsafeChannels(unsafeChannels, restrictions);
361 
362         verify(mWifiService).setCoexUnsafeChannels(unsafeChannels, restrictions);
363     }
364 
365     /**
366      * Verify an IllegalArgumentException if passed a null value for unsafeChannels.
367      */
368     @Test
testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels()369     public void testSetCoexUnsafeChannelsThrowsIllegalArgumentExceptionOnNullUnsafeChannels() {
370         assumeTrue(SdkLevel.isAtLeastS());
371         try {
372             mWifiManager.setCoexUnsafeChannels(null, 0);
373             fail("expected IllegalArgumentException");
374         } catch (IllegalArgumentException expected) {
375         }
376     }
377 
378     /**
379      * Verify an IllegalArgumentException is thrown if callback is not provided.
380      */
381     @Test(expected = IllegalArgumentException.class)
testRegisterCoexCallbackWithNullCallback()382     public void testRegisterCoexCallbackWithNullCallback() throws Exception {
383         assumeTrue(SdkLevel.isAtLeastS());
384         mWifiManager.registerCoexCallback(mExecutor, null);
385     }
386 
387     /**
388      * Verify an IllegalArgumentException is thrown if executor is not provided.
389      */
390     @Test(expected = IllegalArgumentException.class)
testRegisterCoexCallbackWithNullExecutor()391     public void testRegisterCoexCallbackWithNullExecutor() throws Exception {
392         assumeTrue(SdkLevel.isAtLeastS());
393         mWifiManager.registerCoexCallback(null, mCoexCallback);
394     }
395 
396     /**
397      * Verify client provided callback is being called to the right callback.
398      */
399     @Test
testAddCoexCallbackAndReceiveEvent()400     public void testAddCoexCallbackAndReceiveEvent() throws Exception {
401         assumeTrue(SdkLevel.isAtLeastS());
402         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
403                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
404         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
405         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
406         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
407         verify(mRunnable).run();
408     }
409 
410     /**
411      * Verify client provided callback is being called to the right executor.
412      */
413     @Test
testRegisterCoexCallbackWithTheTargetExecutor()414     public void testRegisterCoexCallbackWithTheTargetExecutor() throws Exception {
415         assumeTrue(SdkLevel.isAtLeastS());
416         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
417                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
418         mWifiManager.registerCoexCallback(mExecutor, mCoexCallback);
419         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
420         mWifiManager.registerCoexCallback(mAnotherExecutor, mCoexCallback);
421         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
422         verify(mExecutor, never()).execute(any(Runnable.class));
423         verify(mAnotherExecutor).execute(any(Runnable.class));
424     }
425 
426     /**
427      * Verify client register unregister then register again, to ensure callback still works.
428      */
429     @Test
testRegisterUnregisterThenRegisterAgainWithCoexCallback()430     public void testRegisterUnregisterThenRegisterAgainWithCoexCallback() throws Exception {
431         assumeTrue(SdkLevel.isAtLeastS());
432         ArgumentCaptor<ICoexCallback.Stub> callbackCaptor =
433                 ArgumentCaptor.forClass(ICoexCallback.Stub.class);
434         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
435         verify(mWifiService).registerCoexCallback(callbackCaptor.capture());
436         mWifiManager.unregisterCoexCallback(mCoexCallback);
437         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
438         verify(mRunnable, never()).run();
439         mWifiManager.registerCoexCallback(new SynchronousExecutor(), mCoexCallback);
440         callbackCaptor.getValue().onCoexUnsafeChannelsChanged(Collections.emptyList(), 0);
441         verify(mRunnable).run();
442     }
443 
444     /**
445      * Verify client unregisterCoexCallback.
446      */
447     @Test
testUnregisterCoexCallback()448     public void testUnregisterCoexCallback() throws Exception {
449         assumeTrue(SdkLevel.isAtLeastS());
450         mWifiManager.unregisterCoexCallback(mCoexCallback);
451         verify(mWifiService).unregisterCoexCallback(any());
452     }
453 
454     /**
455      * Verify client unregisterCoexCallback with null callback will cause an exception.
456      */
457     @Test(expected = IllegalArgumentException.class)
testUnregisterCoexCallbackWithNullCallback()458     public void testUnregisterCoexCallbackWithNullCallback() throws Exception {
459         assumeTrue(SdkLevel.isAtLeastS());
460         mWifiManager.unregisterCoexCallback(null);
461     }
462 
463     /**
464      * Verify that call is passed to binder.
465      */
466     @Test
testRestartWifiSubsystem()467     public void testRestartWifiSubsystem() throws Exception {
468         assumeTrue(SdkLevel.isAtLeastS());
469         mWifiManager.restartWifiSubsystem();
470         verify(mWifiService).restartWifiSubsystem();
471     }
472 
473     /**
474      * Verify that can register a subsystem restart tracking callback and that calls are passed
475      * through when registered and blocked once unregistered.
476      */
477     @Test
testRegisterSubsystemRestartTrackingCallback()478     public void testRegisterSubsystemRestartTrackingCallback() throws Exception {
479         assumeTrue(SdkLevel.isAtLeastS());
480         mRestartCallbackMethodRun = 0; // none
481         ArgumentCaptor<ISubsystemRestartCallback.Stub> callbackCaptor =
482                 ArgumentCaptor.forClass(ISubsystemRestartCallback.Stub.class);
483         mWifiManager.registerSubsystemRestartTrackingCallback(new SynchronousExecutor(),
484                 mRestartCallback);
485         verify(mWifiService).registerSubsystemRestartCallback(callbackCaptor.capture());
486         mWifiManager.unregisterSubsystemRestartTrackingCallback(mRestartCallback);
487         verify(mWifiService).unregisterSubsystemRestartCallback(callbackCaptor.capture());
488         callbackCaptor.getValue().onSubsystemRestarting();
489         verify(mRunnable, never()).run();
490         mWifiManager.registerSubsystemRestartTrackingCallback(new SynchronousExecutor(),
491                 mRestartCallback);
492         callbackCaptor.getValue().onSubsystemRestarting();
493         assertEquals(mRestartCallbackMethodRun, 1); // restarting
494         callbackCaptor.getValue().onSubsystemRestarted();
495         verify(mRunnable, times(2)).run();
496         assertEquals(mRestartCallbackMethodRun, 2); // restarted
497     }
498 
499     /**
500      * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
501      * WifiConfiguration.  Verify that the return value is propagated to the caller.
502      */
503     @Test
testStartSoftApCallsServiceWithWifiConfig()504     public void testStartSoftApCallsServiceWithWifiConfig() throws Exception {
505         when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(true);
506         assertTrue(mWifiManager.startSoftAp(mApConfig));
507 
508         when(mWifiService.startSoftAp(mApConfig, TEST_PACKAGE_NAME)).thenReturn(false);
509         assertFalse(mWifiManager.startSoftAp(mApConfig));
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
testStartSoftApCallsServiceWithNullConfig()517     public void testStartSoftApCallsServiceWithNullConfig() throws Exception {
518         when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(true);
519         assertTrue(mWifiManager.startSoftAp(null));
520 
521         when(mWifiService.startSoftAp(null, TEST_PACKAGE_NAME)).thenReturn(false);
522         assertFalse(mWifiManager.startSoftAp(null));
523     }
524 
525     /**
526      * Check the call to stopSoftAp calls WifiService to stopSoftAp.
527      */
528     @Test
testStopSoftApCallsService()529     public void testStopSoftApCallsService() throws Exception {
530         when(mWifiService.stopSoftAp()).thenReturn(true);
531         assertTrue(mWifiManager.stopSoftAp());
532 
533         when(mWifiService.stopSoftAp()).thenReturn(false);
534         assertFalse(mWifiManager.stopSoftAp());
535     }
536 
537     /**
538      * Check the call to validateSoftApConfiguration calls WifiService to
539      * validateSoftApConfiguration.
540      */
541     @Test
testValidateSoftApConfigurationCallsService()542     public void testValidateSoftApConfigurationCallsService() throws Exception {
543         SoftApConfiguration apConfig = generatorTestSoftApConfig();
544         when(mWifiService.validateSoftApConfiguration(any())).thenReturn(true);
545         assertTrue(mWifiManager.validateSoftApConfiguration(apConfig));
546 
547         when(mWifiService.validateSoftApConfiguration(any())).thenReturn(false);
548         assertFalse(mWifiManager.validateSoftApConfiguration(apConfig));
549     }
550 
551     /**
552      * Throws  IllegalArgumentException when calling validateSoftApConfiguration with null.
553      */
554     @Test
testValidateSoftApConfigurationWithNullConfiguration()555     public void testValidateSoftApConfigurationWithNullConfiguration() throws Exception {
556         assertThrows(IllegalArgumentException.class,
557                 () -> mWifiManager.validateSoftApConfiguration(null));
558     }
559 
560     /**
561      * Check the call to startSoftAp calls WifiService to startSoftAp with the provided
562      * WifiConfiguration.  Verify that the return value is propagated to the caller.
563      */
564     @Test
testStartTetheredHotspotCallsServiceWithSoftApConfig()565     public void testStartTetheredHotspotCallsServiceWithSoftApConfig() throws Exception {
566         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
567         when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
568                 .thenReturn(true);
569         assertTrue(mWifiManager.startTetheredHotspot(softApConfig));
570 
571         when(mWifiService.startTetheredHotspot(softApConfig, TEST_PACKAGE_NAME))
572                 .thenReturn(false);
573         assertFalse(mWifiManager.startTetheredHotspot(softApConfig));
574     }
575 
576     /**
577      * Check the call to startSoftAp calls WifiService to startSoftAp with a null config.  Verify
578      * that the return value is propagated to the caller.
579      */
580     @Test
testStartTetheredHotspotCallsServiceWithNullConfig()581     public void testStartTetheredHotspotCallsServiceWithNullConfig() throws Exception {
582         when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(true);
583         assertTrue(mWifiManager.startTetheredHotspot(null));
584 
585         when(mWifiService.startTetheredHotspot(null, TEST_PACKAGE_NAME)).thenReturn(false);
586         assertFalse(mWifiManager.startTetheredHotspot(null));
587     }
588 
589     /**
590      * Test creation of a LocalOnlyHotspotReservation and verify that close properly calls
591      * WifiService.stopLocalOnlyHotspot.
592      */
593     @Test
testCreationAndCloseOfLocalOnlyHotspotReservation()594     public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception {
595         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
596         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
597         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
598                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
599         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
600 
601         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
602 
603         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
604         WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
605         assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
606 
607         callback.mRes.close();
608         verify(mWifiService).stopLocalOnlyHotspot();
609     }
610 
611     /**
612      * Verify stopLOHS is called when try-with-resources is used properly.
613      */
614     @Test
testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()615     public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources()
616             throws Exception {
617         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
618         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
619         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
620                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
621         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
622 
623         callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(softApConfig));
624 
625         try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) {
626             assertEquals(softApConfig, res.getSoftApConfiguration());
627             WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
628             assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
629         }
630 
631         verify(mWifiService).stopLocalOnlyHotspot();
632     }
633 
634     /**
635      * Test creation of a LocalOnlyHotspotSubscription.
636      * TODO: when registrations are tracked, verify removal on close.
637      */
638     @Test
testCreationOfLocalOnlyHotspotSubscription()639     public void testCreationOfLocalOnlyHotspotSubscription() throws Exception {
640         try (WifiManager.LocalOnlyHotspotSubscription sub =
641                      mWifiManager.new LocalOnlyHotspotSubscription()) {
642             sub.close();
643         }
644     }
645 
646     public class TestLocalOnlyHotspotCallback extends LocalOnlyHotspotCallback {
647         public boolean mOnStartedCalled = false;
648         public boolean mOnStoppedCalled = false;
649         public int mFailureReason = -1;
650         public LocalOnlyHotspotReservation mRes = null;
651         public long mCallingThreadId = -1;
652 
653         @Override
onStarted(LocalOnlyHotspotReservation r)654         public void onStarted(LocalOnlyHotspotReservation r) {
655             mRes = r;
656             mOnStartedCalled = true;
657             mCallingThreadId = Thread.currentThread().getId();
658         }
659 
660         @Override
onStopped()661         public void onStopped() {
662             mOnStoppedCalled = true;
663             mCallingThreadId = Thread.currentThread().getId();
664         }
665 
666         @Override
onFailed(int reason)667         public void onFailed(int reason) {
668             mFailureReason = reason;
669             mCallingThreadId = Thread.currentThread().getId();
670         }
671     }
672 
673     /**
674      * Verify callback is properly plumbed when called.
675      */
676     @Test
testLocalOnlyHotspotCallback()677     public void testLocalOnlyHotspotCallback() {
678         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
679         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
680         assertFalse(callback.mOnStartedCalled);
681         assertFalse(callback.mOnStoppedCalled);
682         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
683         assertEquals(null, callback.mRes);
684 
685         // test onStarted
686         WifiManager.LocalOnlyHotspotReservation res =
687                 mWifiManager.new LocalOnlyHotspotReservation(softApConfig);
688         callback.onStarted(res);
689         assertEquals(res, callback.mRes);
690         assertTrue(callback.mOnStartedCalled);
691         assertFalse(callback.mOnStoppedCalled);
692         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
693 
694         // test onStopped
695         callback.onStopped();
696         assertEquals(res, callback.mRes);
697         assertTrue(callback.mOnStartedCalled);
698         assertTrue(callback.mOnStoppedCalled);
699         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
700 
701         // test onFailed
702         callback.onFailed(ERROR_TEST_REASON);
703         assertEquals(res, callback.mRes);
704         assertTrue(callback.mOnStartedCalled);
705         assertTrue(callback.mOnStoppedCalled);
706         assertEquals(ERROR_TEST_REASON, callback.mFailureReason);
707     }
708 
709     public class TestLocalOnlyHotspotObserver extends LocalOnlyHotspotObserver {
710         public boolean mOnRegistered = false;
711         public boolean mOnStartedCalled = false;
712         public boolean mOnStoppedCalled = false;
713         public SoftApConfiguration mConfig = null;
714         public LocalOnlyHotspotSubscription mSub = null;
715         public long mCallingThreadId = -1;
716 
717         @Override
onRegistered(LocalOnlyHotspotSubscription sub)718         public void onRegistered(LocalOnlyHotspotSubscription sub) {
719             mOnRegistered = true;
720             mSub = sub;
721             mCallingThreadId = Thread.currentThread().getId();
722         }
723 
724         @Override
onStarted(SoftApConfiguration config)725         public void onStarted(SoftApConfiguration config) {
726             mOnStartedCalled = true;
727             mConfig = config;
728             mCallingThreadId = Thread.currentThread().getId();
729         }
730 
731         @Override
onStopped()732         public void onStopped() {
733             mOnStoppedCalled = true;
734             mCallingThreadId = Thread.currentThread().getId();
735         }
736     }
737 
738     /**
739      * Verify observer is properly plumbed when called.
740      */
741     @Test
testLocalOnlyHotspotObserver()742     public void testLocalOnlyHotspotObserver() {
743         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
744         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
745         assertFalse(observer.mOnRegistered);
746         assertFalse(observer.mOnStartedCalled);
747         assertFalse(observer.mOnStoppedCalled);
748         assertEquals(null, observer.mConfig);
749         assertEquals(null, observer.mSub);
750 
751         WifiManager.LocalOnlyHotspotSubscription sub =
752                 mWifiManager.new LocalOnlyHotspotSubscription();
753         observer.onRegistered(sub);
754         assertTrue(observer.mOnRegistered);
755         assertFalse(observer.mOnStartedCalled);
756         assertFalse(observer.mOnStoppedCalled);
757         assertEquals(null, observer.mConfig);
758         assertEquals(sub, observer.mSub);
759 
760         observer.onStarted(softApConfig);
761         assertTrue(observer.mOnRegistered);
762         assertTrue(observer.mOnStartedCalled);
763         assertFalse(observer.mOnStoppedCalled);
764         assertEquals(softApConfig, observer.mConfig);
765         assertEquals(sub, observer.mSub);
766 
767         observer.onStopped();
768         assertTrue(observer.mOnRegistered);
769         assertTrue(observer.mOnStartedCalled);
770         assertTrue(observer.mOnStoppedCalled);
771         assertEquals(softApConfig, observer.mConfig);
772         assertEquals(sub, observer.mSub);
773     }
774 
775     @Test
testSetSsidsDoNotBlocklist()776     public void testSetSsidsDoNotBlocklist() throws Exception {
777         // test non-empty set
778         List<WifiSsid> expectedSsids = new ArrayList<>();
779         expectedSsids.add(WifiSsid.fromString("\"TEST_SSID\""));
780         mWifiManager.setSsidsAllowlist(new ArraySet<>(expectedSsids));
781         verify(mWifiService).setSsidsAllowlist(any(), eq(expectedSsids));
782 
783         // test empty set
784         mWifiManager.setSsidsAllowlist(Collections.EMPTY_SET);
785         verify(mWifiService).setSsidsAllowlist(any(),
786                 eq(Collections.EMPTY_LIST));
787     }
788 
789     /**
790      * Verify call to startLocalOnlyHotspot goes to WifiServiceImpl.
791      */
792     @Test
testStartLocalOnlyHotspot()793     public void testStartLocalOnlyHotspot() throws Exception {
794         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
795         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
796 
797         verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
798                 anyString(), nullable(String.class), eq(null), any());
799     }
800 
801     /**
802      * Verify a SecurityException is thrown for callers without proper permissions for
803      * startLocalOnlyHotspot.
804      */
805     @Test(expected = SecurityException.class)
testStartLocalOnlyHotspotThrowsSecurityException()806     public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception {
807         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
808         doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
809                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
810                 eq(null), any());
811         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
812     }
813 
814     /**
815      * Verify an IllegalStateException is thrown for callers that already have a pending request for
816      * startLocalOnlyHotspot.
817      */
818     @Test(expected = IllegalStateException.class)
testStartLocalOnlyHotspotThrowsIllegalStateException()819     public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
820         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
821         doThrow(new IllegalStateException()).when(mWifiService).startLocalOnlyHotspot(
822                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
823                 eq(null), any());
824         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
825     }
826 
827     /**
828      * Verify that the handler provided by the caller is used for the callbacks.
829      */
830     @Test
testCorrectLooperIsUsedForHandler()831     public void testCorrectLooperIsUsedForHandler() throws Exception {
832         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
833         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
834                 nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
835         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
836         mLooper.dispatchAll();
837         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
838         verify(mContext, never()).getMainLooper();
839         verify(mContext, never()).getMainExecutor();
840     }
841 
842     /**
843      * Verify that the main looper's thread is used if a handler is not provided by the reqiestomg
844      * application.
845      */
846     @Test
testMainLooperIsUsedWhenHandlerNotProvided()847     public void testMainLooperIsUsedWhenHandlerNotProvided() throws Exception {
848         // record thread from looper.getThread and check ids.
849         TestLooper altLooper = new TestLooper();
850         when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
851         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
852         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
853                 nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
854         mWifiManager.startLocalOnlyHotspot(callback, null);
855         altLooper.dispatchAll();
856         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
857         assertEquals(altLooper.getLooper().getThread().getId(), callback.mCallingThreadId);
858         verify(mContext).getMainExecutor();
859     }
860 
861     /**
862      * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED
863      * message from WifiServiceImpl.
864      */
865     @Test
testOnStartedIsCalledWithReservation()866     public void testOnStartedIsCalledWithReservation() throws Exception {
867         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
868         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
869         TestLooper callbackLooper = new TestLooper();
870         Handler callbackHandler = new Handler(callbackLooper.getLooper());
871         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
872                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
873         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
874                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
875         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
876         callbackLooper.dispatchAll();
877         mLooper.dispatchAll();
878         assertFalse(callback.mOnStartedCalled);
879         assertEquals(null, callback.mRes);
880         // now trigger the callback
881         internalCallback.getValue().onHotspotStarted(softApConfig);
882         mLooper.dispatchAll();
883         callbackLooper.dispatchAll();
884         assertTrue(callback.mOnStartedCalled);
885         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
886         WifiConfiguration wifiConfig = callback.mRes.getWifiConfiguration();
887         assertTrue(compareWifiAndSoftApConfiguration(softApConfig, wifiConfig));
888     }
889 
890     /**
891      * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED
892      * message from WifiServiceImpl when softap enabled with SAE security type.
893      */
894     @Test
testOnStartedIsCalledWithReservationAndSaeSoftApConfig()895     public void testOnStartedIsCalledWithReservationAndSaeSoftApConfig() throws Exception {
896         SoftApConfiguration softApConfig = new SoftApConfiguration.Builder()
897                 .setSsid("TestSSID")
898                 .setPassphrase("TestPassphrase", SoftApConfiguration.SECURITY_TYPE_WPA3_SAE)
899                 .build();
900         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
901         TestLooper callbackLooper = new TestLooper();
902         Handler callbackHandler = new Handler(callbackLooper.getLooper());
903         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
904                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
905         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
906                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
907         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
908         callbackLooper.dispatchAll();
909         mLooper.dispatchAll();
910         assertFalse(callback.mOnStartedCalled);
911         assertEquals(null, callback.mRes);
912         // now trigger the callback
913         internalCallback.getValue().onHotspotStarted(softApConfig);
914         mLooper.dispatchAll();
915         callbackLooper.dispatchAll();
916         assertTrue(callback.mOnStartedCalled);
917         assertEquals(softApConfig, callback.mRes.getSoftApConfiguration());
918         assertEquals(null, callback.mRes.getWifiConfiguration());
919     }
920 
921     /**
922      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_STARTED message with a null
923      * config.
924      */
925     @Test
testOnStartedIsCalledWithNullConfig()926     public void testOnStartedIsCalledWithNullConfig() throws Exception {
927         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
928         TestLooper callbackLooper = new TestLooper();
929         Handler callbackHandler = new Handler(callbackLooper.getLooper());
930         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
931                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
932         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
933                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
934         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
935         callbackLooper.dispatchAll();
936         mLooper.dispatchAll();
937         assertFalse(callback.mOnStartedCalled);
938         assertEquals(null, callback.mRes);
939         // now trigger the callback
940         internalCallback.getValue().onHotspotStarted(null);
941         mLooper.dispatchAll();
942         callbackLooper.dispatchAll();
943         assertFalse(callback.mOnStartedCalled);
944         assertEquals(ERROR_GENERIC, callback.mFailureReason);
945     }
946 
947     /**
948      * Verify onStopped is called if WifiServiceImpl sends a HOTSPOT_STOPPED message.
949      */
950     @Test
testOnStoppedIsCalled()951     public void testOnStoppedIsCalled() throws Exception {
952         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
953         TestLooper callbackLooper = new TestLooper();
954         Handler callbackHandler = new Handler(callbackLooper.getLooper());
955         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
956                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
957         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
958                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
959         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
960         callbackLooper.dispatchAll();
961         mLooper.dispatchAll();
962         assertFalse(callback.mOnStoppedCalled);
963         // now trigger the callback
964         internalCallback.getValue().onHotspotStopped();
965         mLooper.dispatchAll();
966         callbackLooper.dispatchAll();
967         assertTrue(callback.mOnStoppedCalled);
968     }
969 
970     /**
971      * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_FAILED message.
972      */
973     @Test
testOnFailedIsCalled()974     public void testOnFailedIsCalled() throws Exception {
975         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
976         TestLooper callbackLooper = new TestLooper();
977         Handler callbackHandler = new Handler(callbackLooper.getLooper());
978         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
979                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
980         when(mWifiService.startLocalOnlyHotspot(internalCallback.capture(), anyString(),
981                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
982         mWifiManager.startLocalOnlyHotspot(callback, callbackHandler);
983         callbackLooper.dispatchAll();
984         mLooper.dispatchAll();
985         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
986         // now trigger the callback
987         internalCallback.getValue().onHotspotFailed(ERROR_NO_CHANNEL);
988         mLooper.dispatchAll();
989         callbackLooper.dispatchAll();
990         assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
991     }
992 
993     /**
994      * Verify callback triggered from startLocalOnlyHotspot with an incompatible mode failure.
995      */
996     @Test
testLocalOnlyHotspotCallbackFullOnIncompatibleMode()997     public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception {
998         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
999         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1000                 nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
1001         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1002         mLooper.dispatchAll();
1003         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
1004         assertFalse(callback.mOnStartedCalled);
1005         assertFalse(callback.mOnStoppedCalled);
1006         assertEquals(null, callback.mRes);
1007     }
1008 
1009     /**
1010      * Verify callback triggered from startLocalOnlyHotspot with a tethering disallowed failure.
1011      */
1012     @Test
testLocalOnlyHotspotCallbackFullOnTetheringDisallowed()1013     public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception {
1014         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1015         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1016                 nullable(String.class), eq(null), any())).thenReturn(ERROR_TETHERING_DISALLOWED);
1017         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1018         mLooper.dispatchAll();
1019         assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason);
1020         assertFalse(callback.mOnStartedCalled);
1021         assertFalse(callback.mOnStoppedCalled);
1022         assertEquals(null, callback.mRes);
1023     }
1024 
1025     /**
1026      * Verify a SecurityException resulting from an application without necessary permissions will
1027      * bubble up through the call to start LocalOnlyHotspot and will not trigger other callbacks.
1028      */
1029     @Test(expected = SecurityException.class)
testLocalOnlyHotspotCallbackFullOnSecurityException()1030     public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception {
1031         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1032         doThrow(new SecurityException()).when(mWifiService).startLocalOnlyHotspot(
1033                 any(ILocalOnlyHotspotCallback.class), anyString(), nullable(String.class),
1034                 eq(null), any());
1035         try {
1036             mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1037         } catch (SecurityException e) {
1038             assertEquals(ERROR_NOT_SET, callback.mFailureReason);
1039             assertFalse(callback.mOnStartedCalled);
1040             assertFalse(callback.mOnStoppedCalled);
1041             assertEquals(null, callback.mRes);
1042             throw e;
1043         }
1044 
1045     }
1046 
1047     /**
1048      * Verify the handler passed to startLocalOnlyHotspot is correctly used for callbacks when
1049      * SoftApMode fails due to a underlying error.
1050      */
1051     @Test
testLocalOnlyHotspotCallbackFullOnNoChannelError()1052     public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception {
1053         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1054         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1055                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
1056         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1057         mLooper.dispatchAll();
1058         //assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason);
1059         assertFalse(callback.mOnStartedCalled);
1060         assertFalse(callback.mOnStoppedCalled);
1061         assertEquals(null, callback.mRes);
1062     }
1063 
1064     /**
1065      * Verify that the call to cancel a LOHS request does call stopLOHS.
1066      */
1067     @Test
testCancelLocalOnlyHotspotRequestCallsStopOnWifiService()1068     public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception {
1069         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1070         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1071                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
1072         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1073         mWifiManager.cancelLocalOnlyHotspotRequest();
1074         verify(mWifiService).stopLocalOnlyHotspot();
1075     }
1076 
1077     /**
1078      * Verify that we do not crash if cancelLocalOnlyHotspotRequest is called without an existing
1079      * callback stored.
1080      */
1081     @Test
testCancelLocalOnlyHotspotReturnsWithoutExistingRequest()1082     public void testCancelLocalOnlyHotspotReturnsWithoutExistingRequest() {
1083         mWifiManager.cancelLocalOnlyHotspotRequest();
1084     }
1085 
1086     /**
1087      * Verify that the callback is not triggered if the LOHS request was already cancelled.
1088      */
1089     @Test
testCallbackAfterLocalOnlyHotspotWasCancelled()1090     public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception {
1091         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1092         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1093                 nullable(String.class), eq(null), any())).thenReturn(REQUEST_REGISTERED);
1094         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1095         mWifiManager.cancelLocalOnlyHotspotRequest();
1096         verify(mWifiService).stopLocalOnlyHotspot();
1097         mLooper.dispatchAll();
1098         assertEquals(ERROR_NOT_SET, callback.mFailureReason);
1099         assertFalse(callback.mOnStartedCalled);
1100         assertFalse(callback.mOnStoppedCalled);
1101         assertEquals(null, callback.mRes);
1102     }
1103 
1104     /**
1105      * Verify that calling cancel LOHS request does not crash if an error callback was already
1106      * handled.
1107      */
1108     @Test
testCancelAfterLocalOnlyHotspotCallbackTriggered()1109     public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception {
1110         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1111         when(mWifiService.startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class), anyString(),
1112                 nullable(String.class), eq(null), any())).thenReturn(ERROR_INCOMPATIBLE_MODE);
1113         mWifiManager.startLocalOnlyHotspot(callback, mHandler);
1114         mLooper.dispatchAll();
1115         assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason);
1116         assertFalse(callback.mOnStartedCalled);
1117         assertFalse(callback.mOnStoppedCalled);
1118         assertEquals(null, callback.mRes);
1119         mWifiManager.cancelLocalOnlyHotspotRequest();
1120         verify(mWifiService, never()).stopLocalOnlyHotspot();
1121     }
1122 
1123     @Test
testStartLocalOnlyHotspotForwardsCustomConfig()1124     public void testStartLocalOnlyHotspotForwardsCustomConfig() throws Exception {
1125         SoftApConfiguration customConfig = new SoftApConfiguration.Builder()
1126                 .setSsid("customSsid")
1127                 .build();
1128         TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback();
1129         mWifiManager.startLocalOnlyHotspot(customConfig, mExecutor, callback);
1130         verify(mWifiService).startLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class),
1131                 anyString(), nullable(String.class), eq(customConfig), any());
1132     }
1133 
1134     /**
1135      * Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl.
1136      */
1137     @Test
testWatchLocalOnlyHotspot()1138     public void testWatchLocalOnlyHotspot() throws Exception {
1139         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1140 
1141         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1142         verify(mWifiService).startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1143     }
1144 
1145     /**
1146      * Verify a SecurityException is thrown for callers without proper permissions for
1147      * startWatchLocalOnlyHotspot.
1148      */
1149     @Test(expected = SecurityException.class)
testStartWatchLocalOnlyHotspotThrowsSecurityException()1150     public void testStartWatchLocalOnlyHotspotThrowsSecurityException() throws Exception {
1151         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1152         doThrow(new SecurityException()).when(mWifiService)
1153                 .startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1154         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1155     }
1156 
1157     /**
1158      * Verify an IllegalStateException is thrown for callers that already have a pending request for
1159      * watchLocalOnlyHotspot.
1160      */
1161     @Test(expected = IllegalStateException.class)
testStartWatchLocalOnlyHotspotThrowsIllegalStateException()1162     public void testStartWatchLocalOnlyHotspotThrowsIllegalStateException() throws Exception {
1163         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1164         doThrow(new IllegalStateException()).when(mWifiService)
1165                 .startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1166         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1167     }
1168 
1169     /**
1170      * Verify an IllegalArgumentException is thrown if a callback or executor is not provided.
1171      */
1172     @Test
testAddWifiVerboseLoggingStatusChangedListenerIllegalArguments()1173     public void testAddWifiVerboseLoggingStatusChangedListenerIllegalArguments() throws Exception {
1174         try {
1175             mWifiManager.addWifiVerboseLoggingStatusChangedListener(
1176                     new HandlerExecutor(mHandler), null);
1177             fail("expected IllegalArgumentException - null callback");
1178         } catch (IllegalArgumentException expected) {
1179         }
1180         try {
1181             WifiManager.WifiVerboseLoggingStatusChangedListener listener =
1182                     new WifiManager.WifiVerboseLoggingStatusChangedListener() {
1183                         @Override
1184                         public void onWifiVerboseLoggingStatusChanged(boolean enabled) {
1185 
1186                         }
1187                     };
1188             mWifiManager.addWifiVerboseLoggingStatusChangedListener(null, listener);
1189             fail("expected IllegalArgumentException - null executor");
1190         } catch (IllegalArgumentException expected) {
1191         }
1192     }
1193 
1194     /**
1195      * Verify the call to addWifiVerboseLoggingStatusChangedListener and
1196      * removeWifiVerboseLoggingStatusChangedListener goes to WifiServiceImpl.
1197      */
1198     @Test
testWifiVerboseLoggingStatusChangedListenerGoesToWifiServiceImpl()1199     public void testWifiVerboseLoggingStatusChangedListenerGoesToWifiServiceImpl()
1200             throws Exception {
1201         WifiManager.WifiVerboseLoggingStatusChangedListener listener =
1202                 new WifiManager.WifiVerboseLoggingStatusChangedListener() {
1203                     @Override
1204                     public void onWifiVerboseLoggingStatusChanged(boolean enabled) {
1205 
1206                     }
1207                 };
1208         mWifiManager.addWifiVerboseLoggingStatusChangedListener(new HandlerExecutor(mHandler),
1209                 listener);
1210         verify(mWifiService).addWifiVerboseLoggingStatusChangedListener(
1211                 any(IWifiVerboseLoggingStatusChangedListener.Stub.class));
1212         mWifiManager.removeWifiVerboseLoggingStatusChangedListener(listener);
1213         verify(mWifiService).removeWifiVerboseLoggingStatusChangedListener(
1214                 any(IWifiVerboseLoggingStatusChangedListener.Stub.class));
1215     }
1216 
1217     /**
1218      * Verify an IllegalArgumentException is thrown if a callback is not provided.
1219      */
1220     @Test
testRemoveWifiVerboseLoggingStatusChangedListenerIllegalArguments()1221     public void testRemoveWifiVerboseLoggingStatusChangedListenerIllegalArguments()
1222             throws Exception {
1223         try {
1224             mWifiManager.removeWifiVerboseLoggingStatusChangedListener(null);
1225             fail("expected IllegalArgumentException - null callback");
1226         } catch (IllegalArgumentException expected) {
1227         }
1228     }
1229 
1230     /**
1231      * Verify an IllegalArgumentException is thrown if callback is not provided.
1232      */
1233     @Test
registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback()1234     public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
1235         try {
1236             mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), null);
1237             fail("expected IllegalArgumentException");
1238         } catch (IllegalArgumentException expected) {
1239         }
1240     }
1241 
1242     /**
1243      * Verify an IllegalArgumentException is thrown if executor is null.
1244      */
1245     @Test
registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForExecutor()1246     public void registerSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForExecutor() {
1247         try {
1248             mWifiManager.registerSoftApCallback(null, mSoftApCallback);
1249             fail("expected IllegalArgumentException");
1250         } catch (IllegalArgumentException expected) {
1251         }
1252     }
1253 
1254     /**
1255      * Verify an IllegalArgumentException is thrown if callback is not provided.
1256      */
1257     @Test
unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback()1258     public void unregisterSoftApCallbackThrowsIllegalArgumentExceptionOnNullArgumentForCallback() {
1259         try {
1260             mWifiManager.unregisterSoftApCallback(null);
1261             fail("expected IllegalArgumentException");
1262         } catch (IllegalArgumentException expected) {
1263         }
1264     }
1265 
1266     /**
1267      * Verify the call to registerSoftApCallback goes to WifiServiceImpl.
1268      */
1269     @Test
registerSoftApCallbackCallGoesToWifiServiceImpl()1270     public void registerSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
1271         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1272         verify(mWifiService).registerSoftApCallback(any(ISoftApCallback.Stub.class));
1273     }
1274 
1275     /**
1276      * Verify the call to unregisterSoftApCallback goes to WifiServiceImpl.
1277      */
1278     @Test
unregisterSoftApCallbackCallGoesToWifiServiceImpl()1279     public void unregisterSoftApCallbackCallGoesToWifiServiceImpl() throws Exception {
1280         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1281                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1282         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1283         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1284 
1285         mWifiManager.unregisterSoftApCallback(mSoftApCallback);
1286         verify(mWifiService).unregisterSoftApCallback(callbackCaptor.getValue());
1287     }
1288 
1289     /*
1290      * Verify client-provided callback is being called through callback proxy
1291      */
1292     @Test
softApCallbackProxyCallsOnStateChanged()1293     public void softApCallbackProxyCallsOnStateChanged() throws Exception {
1294         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1295                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1296         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1297         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1298 
1299         SoftApState state = new SoftApState(WIFI_AP_STATE_ENABLED, 0,
1300                 TEST_TETHERING_REQUEST, TEST_INTERFACE_NAME);
1301         callbackCaptor.getValue().onStateChanged(state);
1302         mLooper.dispatchAll();
1303         ArgumentCaptor<SoftApState> softApStateCaptor = ArgumentCaptor.forClass(SoftApState.class);
1304         verify(mSoftApCallback).onStateChanged(softApStateCaptor.capture());
1305         assertEquals(state, softApStateCaptor.getValue());
1306     }
1307 
1308     /*
1309      * Verify client-provided callback is being called through callback proxy when registration.
1310      */
1311     @Test
softApCallbackProxyCallsOnRegistrationAndApStartedWithClientsConnected()1312     public void softApCallbackProxyCallsOnRegistrationAndApStartedWithClientsConnected()
1313             throws Exception {
1314         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1315                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1316         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1317         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1318         // Prepare test info and clients
1319         initTestInfoAndAddToTestMap(1);
1320         List<WifiClient> clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1321         // Trigger callback with registration in AP started and clients connected.
1322         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1323                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1324                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1325 
1326         mLooper.dispatchAll();
1327         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1328         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1329         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1330         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1331                         infos.contains(mTestApInfo1)));
1332     }
1333 
1334 
1335     /*
1336      * Verify client-provided callback is being called through callback proxy
1337      */
1338     @Test
softApCallbackProxyCallsOnConnectedClientsChangedEvenIfNoInfoChanged()1339     public void softApCallbackProxyCallsOnConnectedClientsChangedEvenIfNoInfoChanged()
1340             throws Exception {
1341         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1342                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1343         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1344         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1345         List<WifiClient> clientList;
1346         // Verify the register callback in disable state.
1347         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1348                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1349                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1350         mLooper.dispatchAll();
1351         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1352         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1353         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1354         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1355         // After verify, reset mSoftApCallback for nex test
1356         reset(mSoftApCallback);
1357 
1358         // Test first client connected
1359         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1360         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1361                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1362                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1363         mLooper.dispatchAll();
1364         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1365         // and InfoChanged(List<SoftApInfo>)
1366         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1367         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1368         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1369         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1370         // After verify, reset mSoftApCallback for nex test
1371         reset(mSoftApCallback);
1372 
1373         // Test second client connected
1374         mTestWifiClientsMap.clear();
1375         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
1376         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1377                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1378                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1379         mLooper.dispatchAll();
1380         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1381         // and InfoChanged(List<SoftApInfo>)
1382         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1383         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1384         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1385         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1386         // After verify, reset mSoftApCallback for nex test
1387         reset(mSoftApCallback);
1388 
1389         // Test second client disconnect
1390         mTestWifiClientsMap.clear();
1391         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1392         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1393                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1394                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1395         mLooper.dispatchAll();
1396         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1397         // and InfoChanged(List<SoftApInfo>)
1398         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1399         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1400         verify(mSoftApCallback, never()).onConnectedClientsChanged(mTestApInfo1, clientList);
1401         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1402         // After verify, reset mSoftApCallback for nex test
1403         reset(mSoftApCallback);
1404     }
1405 
1406     /*
1407      * Verify client-provided callback is being called through callback proxy
1408      */
1409     @Test
softApCallbackProxyCallsOnConnectedClientsChanged()1410     public void softApCallbackProxyCallsOnConnectedClientsChanged() throws Exception {
1411         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1412                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1413         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1414         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1415         List<WifiClient> clientList;
1416         // Verify the register callback in disable state.
1417         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1418                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1419                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1420         mLooper.dispatchAll();
1421         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1422         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1423         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1424         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1425         // After verify, reset mSoftApCallback for nex test
1426         reset(mSoftApCallback);
1427 
1428         // Single AP mode Test
1429         // Test info update
1430         initTestInfoAndAddToTestMap(1);
1431         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1432                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1433                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1434         mLooper.dispatchAll();
1435         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1436         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1437                         infos.contains(mTestApInfo1)));
1438         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1439         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1440         // After verify, reset mSoftApCallback for nex test
1441         reset(mSoftApCallback);
1442 
1443         // Test first client connected
1444         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1445         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1446                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1447                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1448         mLooper.dispatchAll();
1449         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1450         // and InfoChanged(List<SoftApInfo>)
1451         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1452         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1453         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1454         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1455         // After verify, reset mSoftApCallback for nex test
1456         reset(mSoftApCallback);
1457 
1458         // Test second client connected
1459         mTestWifiClientsMap.clear();
1460         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 2, 0);
1461         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1462                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1463                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1464         mLooper.dispatchAll();
1465         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1466         // and InfoChanged(List<SoftApInfo>)
1467         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1468         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1469         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1470         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1471         // After verify, reset mSoftApCallback for nex test
1472         reset(mSoftApCallback);
1473 
1474         // Test second client disconnect
1475         mTestWifiClientsMap.clear();
1476         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1477         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1478                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1479                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1480         mLooper.dispatchAll();
1481         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1482         // and InfoChanged(List<SoftApInfo>)
1483         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1484         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1485         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1486         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1487         // After verify, reset mSoftApCallback for nex test
1488         reset(mSoftApCallback);
1489 
1490         // Test bridged mode case
1491         mTestSoftApInfoMap.clear();
1492         initTestInfoAndAddToTestMap(2);
1493         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1494                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1495                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1496         mLooper.dispatchAll();
1497         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1498         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1499                   infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
1500                   ));
1501         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1502         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1503         // After verify, reset mSoftApCallback for nex test
1504         reset(mSoftApCallback);
1505 
1506         // Test client connect to second instance
1507         List<WifiClient> clientListOnSecond =
1508                 initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[1], 1, 2); // client3 to wlan2
1509         List<WifiClient> totalList = new ArrayList<>();
1510         totalList.addAll(clientList);
1511         totalList.addAll(clientListOnSecond);
1512         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1513                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1514                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1515         mLooper.dispatchAll();
1516         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1517         // and InfoChanged(List<SoftApInfo>)
1518         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1519         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1520         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo2, clientListOnSecond);
1521         verify(mSoftApCallback).onConnectedClientsChanged(totalList);
1522         // After verify, reset mSoftApCallback for nex test
1523         reset(mSoftApCallback);
1524 
1525         // Test shutdown on second instance
1526         mTestSoftApInfoMap.clear();
1527         mTestWifiClientsMap.clear();
1528         initTestInfoAndAddToTestMap(1);
1529         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1530         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1531                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1532                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1533         mLooper.dispatchAll();
1534         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1535         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1536                         infos.contains(mTestApInfo1)));
1537         // second instance have client connected before, thus it should send empty list
1538         verify(mSoftApCallback).onConnectedClientsChanged(
1539                 mTestApInfo2, new ArrayList<WifiClient>());
1540         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1541         // After verify, reset mSoftApCallback for nex test
1542         reset(mSoftApCallback);
1543 
1544         // Test bridged mode disable when client connected
1545         mTestSoftApInfoMap.clear();
1546         mTestWifiClientsMap.clear();
1547         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1548                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1549                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1550         mLooper.dispatchAll();
1551         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1552         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1553         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1554         verify(mSoftApCallback).onConnectedClientsChanged(
1555                 mTestApInfo1, new ArrayList<WifiClient>());
1556         // After verify, reset mSoftApCallback for nex test
1557         reset(mSoftApCallback);
1558     }
1559 
1560 
1561     /*
1562      * Verify client-provided callback is being called through callback proxy
1563      */
1564     @Test
softApCallbackProxyCallsOnSoftApInfoChanged()1565     public void softApCallbackProxyCallsOnSoftApInfoChanged() throws Exception {
1566         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1567                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1568         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1569         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1570         // Verify the register callback in disable state.
1571         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1572                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1573                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1574         mLooper.dispatchAll();
1575         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1576         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1577         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1578         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1579         // After verify, reset mSoftApCallback for nex test
1580         reset(mSoftApCallback);
1581 
1582         // Single AP mode Test
1583         // Test info update
1584         initTestInfoAndAddToTestMap(1);
1585         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1586                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1587                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1588         mLooper.dispatchAll();
1589         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1590         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1591                         infos.contains(mTestApInfo1)));
1592         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1593         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1594         // After verify, reset mSoftApCallback for nex test
1595         reset(mSoftApCallback);
1596 
1597         // Test info changed
1598         SoftApInfo changedInfo = new SoftApInfo(mTestSoftApInfoMap.get(TEST_AP_INSTANCES[0]));
1599         changedInfo.setFrequency(2422);
1600         mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfo);
1601         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1602                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1603                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1604         mLooper.dispatchAll();
1605         verify(mSoftApCallback).onInfoChanged(changedInfo);
1606         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1607                         infos.contains(changedInfo)));
1608         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1609         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1610 
1611         // Test Stop, all of infos is empty
1612         mTestSoftApInfoMap.clear();
1613         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1614                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1615                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1616         mLooper.dispatchAll();
1617         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1618         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1619         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1620         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1621         // After verify, reset mSoftApCallback for nex test
1622         reset(mSoftApCallback);
1623     }
1624 
1625     /*
1626      * Verify client-provided callback is being called through callback proxy
1627      */
1628     @Test
softApCallbackProxyCallsOnSoftApInfoChangedWhenClientConnected()1629     public void softApCallbackProxyCallsOnSoftApInfoChangedWhenClientConnected() throws Exception {
1630         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1631                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1632         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1633         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1634         List<WifiClient> clientList;
1635         // Verify the register callback in disable state.
1636         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1637                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1638                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
1639         mLooper.dispatchAll();
1640         verify(mSoftApCallback).onConnectedClientsChanged(new ArrayList<WifiClient>());
1641         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1642         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1643         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1644         // After verify, reset mSoftApCallback for nex test
1645         reset(mSoftApCallback);
1646 
1647         // Single AP mode Test
1648         // Test info update
1649         initTestInfoAndAddToTestMap(1);
1650         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1651                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1652                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1653         mLooper.dispatchAll();
1654         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
1655         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1656                         infos.contains(mTestApInfo1)));
1657         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1658         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1659         // After verify, reset mSoftApCallback for nex test
1660         reset(mSoftApCallback);
1661 
1662         clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
1663         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1664                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1665                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1666         mLooper.dispatchAll();
1667         // checked NO any infoChanged, includes InfoChanged(SoftApInfo)
1668         // and InfoChanged(List<SoftApInfo>)
1669         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1670         verify(mSoftApCallback, never()).onInfoChanged(any(List.class));
1671         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
1672         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1673         // After verify, reset mSoftApCallback for nex test
1674         reset(mSoftApCallback);
1675 
1676         // Test info changed when client connected
1677         SoftApInfo changedInfo = new SoftApInfo(mTestSoftApInfoMap.get(TEST_AP_INSTANCES[0]));
1678         changedInfo.setFrequency(2422);
1679         mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfo);
1680         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1681                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1682                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1683         mLooper.dispatchAll();
1684         verify(mSoftApCallback).onInfoChanged(changedInfo);
1685         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1686                         infos.contains(changedInfo)));
1687         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
1688         verify(mSoftApCallback).onConnectedClientsChanged(changedInfo, clientList);
1689         // After verify, reset mSoftApCallback for nex test
1690         reset(mSoftApCallback);
1691 
1692         // Test Stop, all of infos is empty
1693         mTestSoftApInfoMap.clear();
1694         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1695                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1696                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, false);
1697         mLooper.dispatchAll();
1698         verify(mSoftApCallback).onInfoChanged(new SoftApInfo());
1699         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1700         verify(mSoftApCallback).onConnectedClientsChanged(any());
1701         verify(mSoftApCallback).onConnectedClientsChanged(any(), any());
1702     }
1703 
1704     /*
1705      * Verify client-provided callback is being called through callback proxy
1706      */
1707     @Test
softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode()1708     public void softApCallbackProxyCallsOnSoftApInfoChangedInBridgedMode() throws Exception {
1709         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1710                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1711         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1712         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1713 
1714         // Test bridged mode case
1715         initTestInfoAndAddToTestMap(2);
1716         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1717                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1718                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1719         mLooper.dispatchAll();
1720         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1721         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1722                   infos.contains(mTestApInfo1) && infos.contains(mTestApInfo2)
1723                   ));
1724         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1725         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1726         // After verify, reset mSoftApCallback for nex test
1727         reset(mSoftApCallback);
1728 
1729         // Test bridged mode case but an info changed
1730         SoftApInfo changedInfoBridgedMode = new SoftApInfo(mTestSoftApInfoMap.get(
1731                 TEST_AP_INSTANCES[0]));
1732         changedInfoBridgedMode.setFrequency(2422);
1733         mTestSoftApInfoMap.put(TEST_AP_INSTANCES[0], changedInfoBridgedMode);
1734         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1735                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1736                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1737         mLooper.dispatchAll();
1738         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1739         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1740                   infos.contains(changedInfoBridgedMode) && infos.contains(mTestApInfo2)
1741                   ));
1742         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1743         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1744         // After verify, reset mSoftApCallback for nex test
1745         reset(mSoftApCallback);
1746 
1747         // Test bridged mode case but an instance shutdown
1748         mTestSoftApInfoMap.clear();
1749         initTestInfoAndAddToTestMap(1);
1750         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1751                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1752                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1753         mLooper.dispatchAll();
1754         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1755         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
1756                   infos.contains(mTestApInfo1)
1757                   ));
1758         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1759         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1760         // After verify, reset mSoftApCallback for nex test
1761         reset(mSoftApCallback);
1762 
1763         // Test bridged mode disable case
1764         mTestSoftApInfoMap.clear();
1765         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
1766                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
1767                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), true, false);
1768         mLooper.dispatchAll();
1769         verify(mSoftApCallback, never()).onInfoChanged(any(SoftApInfo.class));
1770         verify(mSoftApCallback).onInfoChanged(new ArrayList<SoftApInfo>());
1771         verify(mSoftApCallback, never()).onConnectedClientsChanged(any());
1772         verify(mSoftApCallback, never()).onConnectedClientsChanged(any(), any());
1773         // After verify, reset mSoftApCallback for nex test
1774         reset(mSoftApCallback);
1775     }
1776 
1777     /*
1778      * Verify client-provided callback is being called through callback proxy
1779      */
1780     @Test
softApCallbackProxyCallsOnCapabilityChanged()1781     public void softApCallbackProxyCallsOnCapabilityChanged() throws Exception {
1782         SoftApCapability testSoftApCapability = new SoftApCapability(0);
1783         testSoftApCapability.setMaxSupportedClients(10);
1784         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1785                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1786         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1787         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1788 
1789         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
1790         mLooper.dispatchAll();
1791         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
1792     }
1793 
1794     /*
1795      * Verify client-provided callback is being called through callback proxy
1796      */
1797     @Test
softApCallbackProxyCallsOnBlockedClientConnecting()1798     public void softApCallbackProxyCallsOnBlockedClientConnecting() throws Exception {
1799         WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
1800                 TEST_AP_INSTANCES[0]);
1801         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1802                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1803         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1804         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1805 
1806         callbackCaptor.getValue().onBlockedClientConnecting(testWifiClient,
1807                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
1808         mLooper.dispatchAll();
1809         verify(mSoftApCallback).onBlockedClientConnecting(testWifiClient,
1810                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
1811     }
1812 
1813     /*
1814      * Verify client-provided callback is being called through callback proxy on multiple events
1815      */
1816     @Test
softApCallbackProxyCallsOnMultipleUpdates()1817     public void softApCallbackProxyCallsOnMultipleUpdates() throws Exception {
1818         SoftApCapability testSoftApCapability = new SoftApCapability(0);
1819         testSoftApCapability.setMaxSupportedClients(10);
1820         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1821                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1822         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1823         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1824 
1825         SoftApState state0 = new SoftApState(WIFI_AP_STATE_ENABLING, 0,
1826                 TEST_TETHERING_REQUEST, TEST_INTERFACE_NAME);
1827         callbackCaptor.getValue().onStateChanged(state0);
1828         SoftApState state1 = new SoftApState(WIFI_AP_STATE_FAILED, SAP_START_FAILURE_GENERAL,
1829                 TEST_TETHERING_REQUEST, TEST_INTERFACE_NAME);
1830         callbackCaptor.getValue().onStateChanged(state1);
1831         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
1832 
1833 
1834         mLooper.dispatchAll();
1835         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
1836         ArgumentCaptor<SoftApState> softApStateCaptor =
1837                 ArgumentCaptor.forClass(SoftApState.class);
1838         verify(mSoftApCallback, times(2)).onStateChanged(softApStateCaptor.capture());
1839         assertEquals(state0, softApStateCaptor.getAllValues().get(0));
1840         assertEquals(state1, softApStateCaptor.getAllValues().get(1));
1841     }
1842 
1843     /*
1844      * Verify client-provided callback is being called on the correct thread
1845      */
1846     @Test
softApCallbackIsCalledOnCorrectThread()1847     public void softApCallbackIsCalledOnCorrectThread() throws Exception {
1848         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
1849                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
1850         TestLooper altLooper = new TestLooper();
1851         Handler altHandler = new Handler(altLooper.getLooper());
1852         mWifiManager.registerSoftApCallback(new HandlerExecutor(altHandler), mSoftApCallback);
1853         verify(mWifiService).registerSoftApCallback(callbackCaptor.capture());
1854 
1855         SoftApState state = new SoftApState(WIFI_AP_STATE_ENABLED, 0,
1856                 TEST_TETHERING_REQUEST, TEST_INTERFACE_NAME);
1857         callbackCaptor.getValue().onStateChanged(state);
1858         altLooper.dispatchAll();
1859         ArgumentCaptor<SoftApState> softApStateCaptor =
1860                 ArgumentCaptor.forClass(SoftApState.class);
1861         verify(mSoftApCallback).onStateChanged(softApStateCaptor.capture());
1862         SoftApState softApState = softApStateCaptor.getValue();
1863         assertEquals(WIFI_AP_STATE_ENABLED, softApState.getState());
1864         try {
1865             softApState.getFailureReason();
1866             fail("getFailureReason should throw if not in failure state");
1867         } catch (IllegalStateException e) {
1868             // Pass.
1869         }
1870         assertEquals(TEST_INTERFACE_NAME, softApState.getIface());
1871         assertEquals(TEST_TETHERING_REQUEST, softApState.getTetheringRequest());
1872     }
1873 
1874     /**
1875      * Verify that the handler provided by the caller is used for registering soft AP callback.
1876      */
1877     @Test
testCorrectLooperIsUsedForSoftApCallbackHandler()1878     public void testCorrectLooperIsUsedForSoftApCallbackHandler() throws Exception {
1879         mWifiManager.registerSoftApCallback(new HandlerExecutor(mHandler), mSoftApCallback);
1880         mLooper.dispatchAll();
1881         verify(mWifiService).registerSoftApCallback(any(ISoftApCallback.Stub.class));
1882         verify(mContext, never()).getMainLooper();
1883         verify(mContext, never()).getMainExecutor();
1884     }
1885 
1886     /**
1887      * Verify that the handler provided by the caller is used for the observer.
1888      */
1889     @Test
testCorrectLooperIsUsedForObserverHandler()1890     public void testCorrectLooperIsUsedForObserverHandler() throws Exception {
1891         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1892         mWifiManager.watchLocalOnlyHotspot(observer, mHandler);
1893         mLooper.dispatchAll();
1894         assertTrue(observer.mOnRegistered);
1895         verify(mContext, never()).getMainLooper();
1896         verify(mContext, never()).getMainExecutor();
1897     }
1898 
1899     /**
1900      * Verify that the main looper's thread is used if a handler is not provided by the requesting
1901      * application.
1902      */
1903     @Test
testMainLooperIsUsedWhenHandlerNotProvidedForObserver()1904     public void testMainLooperIsUsedWhenHandlerNotProvidedForObserver() throws Exception {
1905         // record thread from looper.getThread and check ids.
1906         TestLooper altLooper = new TestLooper();
1907         when(mContext.getMainExecutor()).thenReturn(altLooper.getNewExecutor());
1908         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1909         mWifiManager.watchLocalOnlyHotspot(observer, null);
1910         altLooper.dispatchAll();
1911         assertTrue(observer.mOnRegistered);
1912         assertEquals(altLooper.getLooper().getThread().getId(), observer.mCallingThreadId);
1913         verify(mContext).getMainExecutor();
1914     }
1915 
1916     /**
1917      * Verify the LOHS onRegistered observer callback is triggered when WifiManager receives a
1918      * HOTSPOT_OBSERVER_REGISTERED message from WifiServiceImpl.
1919      */
1920     @Test
testOnRegisteredIsCalledWithSubscription()1921     public void testOnRegisteredIsCalledWithSubscription() throws Exception {
1922         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1923         TestLooper observerLooper = new TestLooper();
1924         Handler observerHandler = new Handler(observerLooper.getLooper());
1925         assertFalse(observer.mOnRegistered);
1926         assertEquals(null, observer.mSub);
1927         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1928         verify(mWifiService).startWatchLocalOnlyHotspot(any(ILocalOnlyHotspotCallback.class));
1929         // now trigger the callback
1930         observerLooper.dispatchAll();
1931         mLooper.dispatchAll();
1932         assertTrue(observer.mOnRegistered);
1933         assertNotNull(observer.mSub);
1934     }
1935 
1936     /**
1937      * Verify the LOHS onStarted observer callback is triggered when WifiManager receives a
1938      * HOTSPOT_STARTED message from WifiServiceImpl.
1939      */
1940     @Test
testObserverOnStartedIsCalledWithWifiConfig()1941     public void testObserverOnStartedIsCalledWithWifiConfig() throws Exception {
1942         SoftApConfiguration softApConfig = generatorTestSoftApConfig();
1943         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1944         TestLooper observerLooper = new TestLooper();
1945         Handler observerHandler = new Handler(observerLooper.getLooper());
1946         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1947         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1948                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1949         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1950         observerLooper.dispatchAll();
1951         mLooper.dispatchAll();
1952         assertFalse(observer.mOnStartedCalled);
1953         // now trigger the callback
1954         internalCallback.getValue().onHotspotStarted(softApConfig);
1955         mLooper.dispatchAll();
1956         observerLooper.dispatchAll();
1957         assertTrue(observer.mOnStartedCalled);
1958         assertEquals(softApConfig, observer.mConfig);
1959     }
1960 
1961     /**
1962      * Verify the LOHS onStarted observer callback is triggered not when WifiManager receives a
1963      * HOTSPOT_STARTED message from WifiServiceImpl with a null config.
1964      */
1965     @Test
testObserverOnStartedNotCalledWithNullConfig()1966     public void testObserverOnStartedNotCalledWithNullConfig() throws Exception {
1967         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1968         TestLooper observerLooper = new TestLooper();
1969         Handler observerHandler = new Handler(observerLooper.getLooper());
1970         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1971         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1972                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1973         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1974         observerLooper.dispatchAll();
1975         mLooper.dispatchAll();
1976         assertFalse(observer.mOnStartedCalled);
1977         // now trigger the callback
1978         internalCallback.getValue().onHotspotStarted(null);
1979         mLooper.dispatchAll();
1980         observerLooper.dispatchAll();
1981         assertFalse(observer.mOnStartedCalled);
1982         assertEquals(null, observer.mConfig);
1983     }
1984 
1985 
1986     /**
1987      * Verify the LOHS onStopped observer callback is triggered when WifiManager receives a
1988      * HOTSPOT_STOPPED message from WifiServiceImpl.
1989      */
1990     @Test
testObserverOnStoppedIsCalled()1991     public void testObserverOnStoppedIsCalled() throws Exception {
1992         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
1993         TestLooper observerLooper = new TestLooper();
1994         Handler observerHandler = new Handler(observerLooper.getLooper());
1995         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
1996         ArgumentCaptor<ILocalOnlyHotspotCallback> internalCallback =
1997                 ArgumentCaptor.forClass(ILocalOnlyHotspotCallback.class);
1998         verify(mWifiService).startWatchLocalOnlyHotspot(internalCallback.capture());
1999         observerLooper.dispatchAll();
2000         mLooper.dispatchAll();
2001         assertFalse(observer.mOnStoppedCalled);
2002         // now trigger the callback
2003         internalCallback.getValue().onHotspotStopped();
2004         mLooper.dispatchAll();
2005         observerLooper.dispatchAll();
2006         assertTrue(observer.mOnStoppedCalled);
2007     }
2008 
2009     /**
2010      * Verify WifiServiceImpl is not called if there is not a registered LOHS observer callback.
2011      */
2012     @Test
testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver()2013     public void testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver() throws Exception {
2014         mWifiManager.unregisterLocalOnlyHotspotObserver();
2015         verifyZeroInteractions(mWifiService);
2016     }
2017 
2018     /**
2019      * Verify WifiServiceImpl is called when there is a registered LOHS observer callback.
2020      */
2021     @Test
testUnregisterWifiServiceImplCalledWithRegisteredObserver()2022     public void testUnregisterWifiServiceImplCalledWithRegisteredObserver() throws Exception {
2023         TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver();
2024         TestLooper observerLooper = new TestLooper();
2025         Handler observerHandler = new Handler(observerLooper.getLooper());
2026         mWifiManager.watchLocalOnlyHotspot(observer, observerHandler);
2027         mWifiManager.unregisterLocalOnlyHotspotObserver();
2028         verify(mWifiService).stopWatchLocalOnlyHotspot();
2029     }
2030 
2031     /**
2032      * Test that calls to get the current WPS config token return null and do not have any
2033      * interactions with WifiServiceImpl.
2034      */
2035     @Test
testGetCurrentNetworkWpsNfcConfigurationTokenReturnsNull()2036     public void testGetCurrentNetworkWpsNfcConfigurationTokenReturnsNull() {
2037         assertNull(mWifiManager.getCurrentNetworkWpsNfcConfigurationToken());
2038         verifyNoMoreInteractions(mWifiService);
2039     }
2040 
2041 
2042     class WpsCallbackTester extends WpsCallback {
2043         public boolean mStarted = false;
2044         public boolean mSucceeded = false;
2045         public boolean mFailed = false;
2046         public int mFailureCode = -1;
2047 
2048         @Override
onStarted(String pin)2049         public void onStarted(String pin) {
2050             mStarted = true;
2051         }
2052 
2053         @Override
onSucceeded()2054         public void onSucceeded() {
2055             mSucceeded = true;
2056         }
2057 
2058         @Override
onFailed(int reason)2059         public void onFailed(int reason) {
2060             mFailed = true;
2061             mFailureCode = reason;
2062         }
2063 
2064     }
2065 
2066     /**
2067      * Verify that a call to start WPS immediately returns a failure.
2068      */
2069     @Test
testStartWpsImmediatelyFailsWithCallback()2070     public void testStartWpsImmediatelyFailsWithCallback() {
2071         WpsCallbackTester wpsCallback = new WpsCallbackTester();
2072         mWifiManager.startWps(null, wpsCallback);
2073         assertTrue(wpsCallback.mFailed);
2074         assertEquals(ActionListener.FAILURE_INTERNAL_ERROR, wpsCallback.mFailureCode);
2075         assertFalse(wpsCallback.mStarted);
2076         assertFalse(wpsCallback.mSucceeded);
2077         verifyNoMoreInteractions(mWifiService);
2078     }
2079 
2080     /**
2081      * Verify that a call to start WPS does not go to WifiServiceImpl if we do not have a callback.
2082      */
2083     @Test
testStartWpsDoesNotCallWifiServiceImpl()2084     public void testStartWpsDoesNotCallWifiServiceImpl() {
2085         mWifiManager.startWps(null, null);
2086         verifyNoMoreInteractions(mWifiService);
2087     }
2088 
2089     /**
2090      * Verify that a call to cancel WPS immediately returns a failure.
2091      */
2092     @Test
testCancelWpsImmediatelyFailsWithCallback()2093     public void testCancelWpsImmediatelyFailsWithCallback() {
2094         WpsCallbackTester wpsCallback = new WpsCallbackTester();
2095         mWifiManager.cancelWps(wpsCallback);
2096         assertTrue(wpsCallback.mFailed);
2097         assertEquals(ActionListener.FAILURE_INTERNAL_ERROR, wpsCallback.mFailureCode);
2098         assertFalse(wpsCallback.mStarted);
2099         assertFalse(wpsCallback.mSucceeded);
2100         verifyNoMoreInteractions(mWifiService);
2101     }
2102 
2103     /**
2104      * Verify that a call to cancel WPS does not go to WifiServiceImpl if we do not have a callback.
2105      */
2106     @Test
testCancelWpsDoesNotCallWifiServiceImpl()2107     public void testCancelWpsDoesNotCallWifiServiceImpl() {
2108         mWifiManager.cancelWps(null);
2109         verifyNoMoreInteractions(mWifiService);
2110     }
2111 
2112     /**
2113      * Verify that a successful call properly returns true.
2114      */
2115     @Test
testSetWifiApConfigurationSuccessReturnsTrue()2116     public void testSetWifiApConfigurationSuccessReturnsTrue() throws Exception {
2117         WifiConfiguration apConfig = new WifiConfiguration();
2118 
2119         when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
2120                 .thenReturn(true);
2121         assertTrue(mWifiManager.setWifiApConfiguration(apConfig));
2122     }
2123 
2124     /**
2125      * Verify that a failed call properly returns false.
2126      */
2127     @Test
testSetWifiApConfigurationFailureReturnsFalse()2128     public void testSetWifiApConfigurationFailureReturnsFalse() throws Exception {
2129         WifiConfiguration apConfig = new WifiConfiguration();
2130 
2131         when(mWifiService.setWifiApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
2132                 .thenReturn(false);
2133         assertFalse(mWifiManager.setWifiApConfiguration(apConfig));
2134     }
2135 
2136     /**
2137      * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
2138      */
2139     @Test
testSetWifiApConfigurationRethrowsException()2140     public void testSetWifiApConfigurationRethrowsException() throws Exception {
2141         doThrow(new SecurityException()).when(mWifiService).setWifiApConfiguration(any(), any());
2142 
2143         try {
2144             mWifiManager.setWifiApConfiguration(new WifiConfiguration());
2145             fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
2146         } catch (SecurityException e) { }
2147     }
2148 
2149     /**
2150      * Verify that a successful call properly returns true.
2151      */
2152     @Test
testSetSoftApConfigurationSuccessReturnsTrue()2153     public void testSetSoftApConfigurationSuccessReturnsTrue() throws Exception {
2154         SoftApConfiguration apConfig = generatorTestSoftApConfig();
2155 
2156         when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
2157                 .thenReturn(true);
2158         assertTrue(mWifiManager.setSoftApConfiguration(apConfig));
2159     }
2160 
2161     /**
2162      * Verify that a failed call properly returns false.
2163      */
2164     @Test
testSetSoftApConfigurationFailureReturnsFalse()2165     public void testSetSoftApConfigurationFailureReturnsFalse() throws Exception {
2166         SoftApConfiguration apConfig = generatorTestSoftApConfig();
2167 
2168         when(mWifiService.setSoftApConfiguration(eq(apConfig), eq(TEST_PACKAGE_NAME)))
2169                 .thenReturn(false);
2170         assertFalse(mWifiManager.setSoftApConfiguration(apConfig));
2171     }
2172 
2173     /**
2174      * Verify Exceptions are rethrown when underlying calls to WifiService throw exceptions.
2175      */
2176     @Test
testSetSoftApConfigurationRethrowsException()2177     public void testSetSoftApConfigurationRethrowsException() throws Exception {
2178         doThrow(new SecurityException()).when(mWifiService).setSoftApConfiguration(any(), any());
2179 
2180         try {
2181             mWifiManager.setSoftApConfiguration(generatorTestSoftApConfig());
2182             fail("setWifiApConfiguration should rethrow Exceptions from WifiService");
2183         } catch (SecurityException e) { }
2184     }
2185 
2186     /**
2187      * Check the call to startScan calls WifiService.
2188      */
2189     @Test
testStartScan()2190     public void testStartScan() throws Exception {
2191         when(mWifiService.startScan(eq(TEST_PACKAGE_NAME), nullable(String.class))).thenReturn(
2192                 true);
2193         assertTrue(mWifiManager.startScan());
2194 
2195         when(mWifiService.startScan(eq(TEST_PACKAGE_NAME), nullable(String.class))).thenReturn(
2196                 false);
2197         assertFalse(mWifiManager.startScan());
2198     }
2199 
2200     /**
2201      * Verify main looper is used when handler is not provided.
2202      */
2203     @Test
registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()2204     public void registerTrafficStateCallbackUsesMainLooperOnNullArgumentForHandler()
2205             throws Exception {
2206         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2207                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2208         mWifiManager.registerTrafficStateCallback(
2209                 new HandlerExecutor(new Handler(mLooper.getLooper())), mTrafficStateCallback);
2210         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2211 
2212         assertEquals(0, mLooper.dispatchAll());
2213         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2214         assertEquals(1, mLooper.dispatchAll());
2215         verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2216     }
2217 
2218     /**
2219      * Verify the call to unregisterTrafficStateCallback goes to WifiServiceImpl.
2220      */
2221     @Test
unregisterTrafficStateCallbackCallGoesToWifiServiceImpl()2222     public void unregisterTrafficStateCallbackCallGoesToWifiServiceImpl() throws Exception {
2223         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2224                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2225         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(mHandler),
2226                 mTrafficStateCallback);
2227         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2228 
2229         mWifiManager.unregisterTrafficStateCallback(mTrafficStateCallback);
2230         verify(mWifiService).unregisterTrafficStateCallback(callbackCaptor.getValue());
2231     }
2232 
2233     /*
2234      * Verify client-provided callback is being called through callback proxy on multiple events
2235      */
2236     @Test
trafficStateCallbackProxyCallsOnMultipleUpdates()2237     public void trafficStateCallbackProxyCallsOnMultipleUpdates() throws Exception {
2238         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2239                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2240         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(mHandler),
2241                 mTrafficStateCallback);
2242         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2243 
2244         InOrder inOrder = inOrder(mTrafficStateCallback);
2245 
2246         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_IN);
2247         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2248         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_OUT);
2249 
2250         mLooper.dispatchAll();
2251         inOrder.verify(mTrafficStateCallback).onStateChanged(
2252                 TrafficStateCallback.DATA_ACTIVITY_IN);
2253         inOrder.verify(mTrafficStateCallback).onStateChanged(
2254                 TrafficStateCallback.DATA_ACTIVITY_INOUT);
2255         inOrder.verify(mTrafficStateCallback).onStateChanged(
2256                 TrafficStateCallback.DATA_ACTIVITY_OUT);
2257     }
2258 
2259     /**
2260      * Verify client-provided callback is being called on the correct thread
2261      */
2262     @Test
trafficStateCallbackIsCalledOnCorrectThread()2263     public void trafficStateCallbackIsCalledOnCorrectThread() throws Exception {
2264         ArgumentCaptor<ITrafficStateCallback.Stub> callbackCaptor =
2265                 ArgumentCaptor.forClass(ITrafficStateCallback.Stub.class);
2266         TestLooper altLooper = new TestLooper();
2267         Handler altHandler = new Handler(altLooper.getLooper());
2268         mWifiManager.registerTrafficStateCallback(new HandlerExecutor(altHandler),
2269                 mTrafficStateCallback);
2270         verify(mContext, never()).getMainLooper();
2271         verify(mContext, never()).getMainExecutor();
2272         verify(mWifiService).registerTrafficStateCallback(callbackCaptor.capture());
2273 
2274         assertEquals(0, altLooper.dispatchAll());
2275         callbackCaptor.getValue().onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2276         assertEquals(1, altLooper.dispatchAll());
2277         verify(mTrafficStateCallback).onStateChanged(TrafficStateCallback.DATA_ACTIVITY_INOUT);
2278     }
2279 
2280     /**
2281      * Verify the call to registerNetworkRequestMatchCallback goes to WifiServiceImpl.
2282      */
2283     @Test
registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()2284     public void registerNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()
2285             throws Exception {
2286         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2287                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2288         mWifiManager.registerNetworkRequestMatchCallback(
2289                 new HandlerExecutor(new Handler(mLooper.getLooper())),
2290                 mNetworkRequestMatchCallback);
2291         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2292 
2293         INetworkRequestUserSelectionCallback iUserSelectionCallback =
2294                 mock(INetworkRequestUserSelectionCallback.class);
2295 
2296         assertEquals(0, mLooper.dispatchAll());
2297 
2298         callbackCaptor.getValue().onAbort();
2299         assertEquals(1, mLooper.dispatchAll());
2300         verify(mNetworkRequestMatchCallback).onAbort();
2301 
2302         callbackCaptor.getValue().onMatch(new ArrayList<ScanResult>());
2303         assertEquals(1, mLooper.dispatchAll());
2304         verify(mNetworkRequestMatchCallback).onMatch(anyList());
2305 
2306         callbackCaptor.getValue().onUserSelectionConnectSuccess(new WifiConfiguration());
2307         assertEquals(1, mLooper.dispatchAll());
2308         verify(mNetworkRequestMatchCallback).onUserSelectionConnectSuccess(
2309                 any(WifiConfiguration.class));
2310 
2311         callbackCaptor.getValue().onUserSelectionConnectFailure(new WifiConfiguration());
2312         assertEquals(1, mLooper.dispatchAll());
2313         verify(mNetworkRequestMatchCallback).onUserSelectionConnectFailure(
2314                 any(WifiConfiguration.class));
2315     }
2316 
2317     /**
2318      * Verify the call to unregisterNetworkRequestMatchCallback goes to WifiServiceImpl.
2319      */
2320     @Test
unregisterNetworkRequestMatchCallbackCallGoesToWifiServiceImpl()2321     public void unregisterNetworkRequestMatchCallbackCallGoesToWifiServiceImpl() throws Exception {
2322         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2323                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2324         mWifiManager.registerNetworkRequestMatchCallback(new HandlerExecutor(mHandler),
2325                 mNetworkRequestMatchCallback);
2326         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2327 
2328         mWifiManager.unregisterNetworkRequestMatchCallback(mNetworkRequestMatchCallback);
2329         verify(mWifiService).unregisterNetworkRequestMatchCallback(callbackCaptor.getValue());
2330     }
2331 
2332     /**
2333      * Verify the call to NetworkRequestUserSelectionCallback goes to
2334      * WifiServiceImpl.
2335      */
2336     @Test
networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()2337     public void networkRequestUserSelectionCallbackCallGoesToWifiServiceImpl()
2338             throws Exception {
2339         ArgumentCaptor<INetworkRequestMatchCallback.Stub> callbackCaptor =
2340                 ArgumentCaptor.forClass(INetworkRequestMatchCallback.Stub.class);
2341         mWifiManager.registerNetworkRequestMatchCallback(
2342                 new HandlerExecutor(new Handler(mLooper.getLooper())),
2343                 mNetworkRequestMatchCallback);
2344         verify(mWifiService).registerNetworkRequestMatchCallback(callbackCaptor.capture());
2345 
2346         INetworkRequestUserSelectionCallback iUserSelectionCallback =
2347                 mock(INetworkRequestUserSelectionCallback.class);
2348         ArgumentCaptor<NetworkRequestUserSelectionCallback> userSelectionCallbackCaptor =
2349                 ArgumentCaptor.forClass(NetworkRequestUserSelectionCallback.class);
2350         callbackCaptor.getValue().onUserSelectionCallbackRegistration(
2351                 iUserSelectionCallback);
2352         assertEquals(1, mLooper.dispatchAll());
2353         verify(mNetworkRequestMatchCallback).onUserSelectionCallbackRegistration(
2354                 userSelectionCallbackCaptor.capture());
2355 
2356         WifiConfiguration selected = new WifiConfiguration();
2357         userSelectionCallbackCaptor.getValue().select(selected);
2358         verify(iUserSelectionCallback).select(selected);
2359 
2360         userSelectionCallbackCaptor.getValue().reject();
2361         verify(iUserSelectionCallback).reject();
2362     }
2363 
2364     /**
2365      * Check the call to getAllMatchingWifiConfigs calls getAllMatchingFqdnsForScanResults and
2366      * getWifiConfigsForPasspointProfiles of WifiService in order.
2367      */
2368     @Test
testGetAllMatchingWifiConfigs()2369     public void testGetAllMatchingWifiConfigs() throws Exception {
2370         Map<String, List<ScanResult>> passpointProfiles = new HashMap<>();
2371         passpointProfiles.put("www.test.com_987a69bca26", new ArrayList<>());
2372         when(mWifiService.getAllMatchingPasspointProfilesForScanResults(
2373                 any(List.class))).thenReturn(passpointProfiles);
2374         InOrder inOrder = inOrder(mWifiService);
2375 
2376         mWifiManager.getAllMatchingWifiConfigs(new ArrayList<>());
2377 
2378         inOrder.verify(mWifiService).getAllMatchingPasspointProfilesForScanResults(any(List.class));
2379         inOrder.verify(mWifiService).getWifiConfigsForPasspointProfiles(any(List.class));
2380     }
2381 
2382     /**
2383      * Check the call to getMatchingOsuProviders calls getMatchingOsuProviders of WifiService
2384      * with the provided a list of ScanResult.
2385      */
2386     @Test
testGetMatchingOsuProviders()2387     public void testGetMatchingOsuProviders() throws Exception {
2388         mWifiManager.getMatchingOsuProviders(new ArrayList<>());
2389 
2390         verify(mWifiService).getMatchingOsuProviders(any(List.class));
2391     }
2392 
2393     /**
2394      * Verify calls to {@link WifiManager#addNetworkSuggestions(List)},
2395      * {@link WifiManager#getNetworkSuggestions()} and
2396      * {@link WifiManager#removeNetworkSuggestions(List)}.
2397      */
2398     @Test
addGetRemoveNetworkSuggestions()2399     public void addGetRemoveNetworkSuggestions() throws Exception {
2400         List<WifiNetworkSuggestion> testList = new ArrayList<>();
2401         when(mWifiService.addNetworkSuggestions(any(List.class), anyString(),
2402                 nullable(String.class))).thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS);
2403         when(mWifiService.removeNetworkSuggestions(any(List.class), anyString(), anyInt()))
2404                 .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS);
2405         when(mWifiService.getNetworkSuggestions(anyString()))
2406                 .thenReturn(testList);
2407 
2408         assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS,
2409                 mWifiManager.addNetworkSuggestions(testList));
2410         verify(mWifiService).addNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME),
2411                 nullable(String.class));
2412 
2413         assertEquals(testList, mWifiManager.getNetworkSuggestions());
2414         verify(mWifiService).getNetworkSuggestions(eq(TEST_PACKAGE_NAME));
2415 
2416         assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS,
2417                 mWifiManager.removeNetworkSuggestions(new ArrayList<>()));
2418         verify(mWifiService).removeNetworkSuggestions(anyList(), eq(TEST_PACKAGE_NAME),
2419                 eq(ACTION_REMOVE_SUGGESTION_DISCONNECT));
2420     }
2421 
2422     @Test
testRemoveNetworkSuggestionWithAction()2423     public void testRemoveNetworkSuggestionWithAction() throws Exception {
2424         when(mWifiService.removeNetworkSuggestions(anyList(), anyString(), anyInt()))
2425                 .thenReturn(STATUS_NETWORK_SUGGESTIONS_SUCCESS);
2426         assertEquals(STATUS_NETWORK_SUGGESTIONS_SUCCESS, mWifiManager
2427                 .removeNetworkSuggestions(new ArrayList<>(), ACTION_REMOVE_SUGGESTION_LINGER));
2428         verify(mWifiService).removeNetworkSuggestions(any(List.class),
2429                 eq(TEST_PACKAGE_NAME), eq(ACTION_REMOVE_SUGGESTION_LINGER));
2430     }
2431 
2432     /**
2433      * Verify call to {@link WifiManager#getMaxNumberOfNetworkSuggestionsPerApp()}.
2434      */
2435     @Test
getMaxNumberOfNetworkSuggestionsPerApp()2436     public void getMaxNumberOfNetworkSuggestionsPerApp() {
2437         when(mContext.getSystemService(ActivityManager.class)).thenReturn(mActivityManager);
2438         when(mActivityManager.isLowRamDevice()).thenReturn(true);
2439         assertEquals(256, mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp());
2440 
2441         when(mActivityManager.isLowRamDevice()).thenReturn(false);
2442         assertEquals(1024, mWifiManager.getMaxNumberOfNetworkSuggestionsPerApp());
2443     }
2444 
2445     /**
2446      * Verify getting the factory MAC address.
2447      */
2448     @Test
testGetFactoryMacAddress()2449     public void testGetFactoryMacAddress() throws Exception {
2450         when(mWifiService.getFactoryMacAddresses()).thenReturn(TEST_MAC_ADDRESSES);
2451         assertArrayEquals(TEST_MAC_ADDRESSES, mWifiManager.getFactoryMacAddresses());
2452         verify(mWifiService).getFactoryMacAddresses();
2453     }
2454 
2455     /**
2456      * Verify the call to getCallerConfiguredNetworks goes to WifiServiceImpl.
2457      */
2458     @Test
testGetCallerConfiguredNetworks()2459     public void testGetCallerConfiguredNetworks() throws Exception {
2460         mWifiManager.getCallerConfiguredNetworks();
2461         verify(mWifiService).getConfiguredNetworks(any(), any(), eq(true));
2462     }
2463 
2464     @Test
testGetPrivilegedConfiguredNetworks()2465     public void testGetPrivilegedConfiguredNetworks() throws Exception {
2466         mWifiManager.getPrivilegedConfiguredNetworks();
2467         verify(mWifiService).getPrivilegedConfiguredNetworks(any(), any(), any());
2468     }
2469 
2470     /**
2471      * Verify the call to startRestrictingAutoJoinToSubscriptionId goes to WifiServiceImpl.
2472      */
2473     @Test
testStartRestrictAutoJoinToSubscriptionId()2474     public void testStartRestrictAutoJoinToSubscriptionId() throws Exception {
2475         assumeTrue(SdkLevel.isAtLeastS());
2476         mWifiManager.startRestrictingAutoJoinToSubscriptionId(1);
2477         verify(mWifiService).startRestrictingAutoJoinToSubscriptionId(1);
2478     }
2479 
2480     /**
2481      * Verify the call to stopRestrictingAutoJoinToSubscriptionId goes to WifiServiceImpl.
2482      */
2483     @Test
testStopTemporarilyDisablingAllNonCarrierMergedWifi()2484     public void testStopTemporarilyDisablingAllNonCarrierMergedWifi() throws Exception {
2485         assumeTrue(SdkLevel.isAtLeastS());
2486         mWifiManager.stopRestrictingAutoJoinToSubscriptionId();
2487         verify(mWifiService).stopRestrictingAutoJoinToSubscriptionId();
2488     }
2489 
2490     /**
2491      * Verify the call to addOnWifiUsabilityStatsListener goes to WifiServiceImpl.
2492      */
2493     @Test
addOnWifiUsabilityStatsListenerGoesToWifiServiceImpl()2494     public void addOnWifiUsabilityStatsListenerGoesToWifiServiceImpl() throws Exception {
2495         mExecutor = new SynchronousExecutor();
2496         ArgumentCaptor<IOnWifiUsabilityStatsListener.Stub> callbackCaptor =
2497                 ArgumentCaptor.forClass(IOnWifiUsabilityStatsListener.Stub.class);
2498         mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
2499         verify(mWifiService).addOnWifiUsabilityStatsListener(callbackCaptor.capture());
2500         ContentionTimeStats[] contentionTimeStats = new ContentionTimeStats[4];
2501         contentionTimeStats[0] = new ContentionTimeStats(1, 2, 3, 4);
2502         contentionTimeStats[1] = new ContentionTimeStats(5, 6, 7, 8);
2503         contentionTimeStats[2] = new ContentionTimeStats(9, 10, 11, 12);
2504         contentionTimeStats[3] = new ContentionTimeStats(13, 14, 15, 16);
2505         RateStats[] rateStats = new RateStats[2];
2506         rateStats[0] = new RateStats(1, 3, 5, 7, 9, 11, 13, 15, 17);
2507         rateStats[1] = new RateStats(2, 4, 6, 8, 10, 12, 14, 16, 18);
2508         RadioStats[] radioStats = new RadioStats[2];
2509         radioStats[0] = new RadioStats(0, 10, 11, 12, 13, 14, 15, 16, 17, 18);
2510         radioStats[1] = new RadioStats(1, 20, 21, 22, 23, 24, 25, 26, 27, 28);
2511         SparseArray<LinkStats> linkStats = new SparseArray<>();
2512         linkStats.put(0,
2513                 new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_NOT_IN_USE, 0, -50, 300,
2514                         200,
2515                         188, 2, 2, 100, 300, 100, 100, 200,
2516                         contentionTimeStats, rateStats));
2517         linkStats.put(1,
2518                 new LinkStats(0, WifiUsabilityStatsEntry.LINK_STATE_IN_USE, 0, -40, 860, 600,
2519                         388, 2, 2, 200, 400, 100, 100, 200,
2520                         contentionTimeStats, rateStats));
2521         callbackCaptor.getValue().onWifiUsabilityStats(1, true,
2522                 new WifiUsabilityStatsEntry(System.currentTimeMillis(), -50, 100, 10, 0, 5, 5,
2523                         100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 1, 100, 10,
2524                         100, 27, contentionTimeStats, rateStats, radioStats, 101, true, true, true,
2525                         0, 10, 10, true, linkStats));
2526         verify(mOnWifiUsabilityStatsListener).onWifiUsabilityStats(anyInt(), anyBoolean(),
2527                 any(WifiUsabilityStatsEntry.class));
2528     }
2529 
2530     /**
2531      * Verify the call to removeOnWifiUsabilityStatsListener goes to WifiServiceImpl.
2532      */
2533     @Test
removeOnWifiUsabilityListenerGoesToWifiServiceImpl()2534     public void removeOnWifiUsabilityListenerGoesToWifiServiceImpl() throws Exception {
2535         mExecutor = new SynchronousExecutor();
2536         ArgumentCaptor<IOnWifiUsabilityStatsListener.Stub> callbackCaptor =
2537                 ArgumentCaptor.forClass(IOnWifiUsabilityStatsListener.Stub.class);
2538         mWifiManager.addOnWifiUsabilityStatsListener(mExecutor, mOnWifiUsabilityStatsListener);
2539         verify(mWifiService).addOnWifiUsabilityStatsListener(callbackCaptor.capture());
2540 
2541         mWifiManager.removeOnWifiUsabilityStatsListener(mOnWifiUsabilityStatsListener);
2542         verify(mWifiService).removeOnWifiUsabilityStatsListener(callbackCaptor.getValue());
2543     }
2544 
2545     /**
2546      * Test behavior of isEnhancedOpenSupported
2547      */
2548     @Test
testIsEnhancedOpenSupported()2549     public void testIsEnhancedOpenSupported() throws Exception {
2550         when(mWifiService.getSupportedFeatures())
2551                 .thenReturn(new Long(WIFI_FEATURE_OWE));
2552         assertTrue(mWifiManager.isEnhancedOpenSupported());
2553         when(mWifiService.getSupportedFeatures())
2554                 .thenReturn(new Long(~WIFI_FEATURE_OWE));
2555         assertFalse(mWifiManager.isEnhancedOpenSupported());
2556     }
2557 
2558     /**
2559      * Test behavior of isWpa3SaeSupported
2560      */
2561     @Test
testIsWpa3SaeSupported()2562     public void testIsWpa3SaeSupported() throws Exception {
2563         when(mWifiService.getSupportedFeatures())
2564                 .thenReturn(new Long(WIFI_FEATURE_WPA3_SAE));
2565         assertTrue(mWifiManager.isWpa3SaeSupported());
2566         when(mWifiService.getSupportedFeatures())
2567                 .thenReturn(new Long(~WIFI_FEATURE_WPA3_SAE));
2568         assertFalse(mWifiManager.isWpa3SaeSupported());
2569     }
2570 
2571     /**
2572      * Test behavior of isWpa3SuiteBSupported
2573      */
2574     @Test
testIsWpa3SuiteBSupported()2575     public void testIsWpa3SuiteBSupported() throws Exception {
2576         when(mWifiService.getSupportedFeatures())
2577                 .thenReturn(new Long(WIFI_FEATURE_WPA3_SUITE_B));
2578         assertTrue(mWifiManager.isWpa3SuiteBSupported());
2579         when(mWifiService.getSupportedFeatures())
2580                 .thenReturn(new Long(~WIFI_FEATURE_WPA3_SUITE_B));
2581         assertFalse(mWifiManager.isWpa3SuiteBSupported());
2582     }
2583 
2584     /**
2585      * Test behavior of isEasyConnectSupported
2586      */
2587     @Test
testIsEasyConnectSupported()2588     public void testIsEasyConnectSupported() throws Exception {
2589         when(mWifiService.getSupportedFeatures())
2590                 .thenReturn(new Long(WIFI_FEATURE_DPP));
2591         assertTrue(mWifiManager.isEasyConnectSupported());
2592         when(mWifiService.getSupportedFeatures())
2593                 .thenReturn(new Long(~WIFI_FEATURE_DPP));
2594         assertFalse(mWifiManager.isEasyConnectSupported());
2595     }
2596 
2597     /**
2598      * Test behavior of isEasyConnectDppAkmSupported
2599      */
2600     @Test
testIsEasyConnectDppAkmSupported()2601     public void testIsEasyConnectDppAkmSupported() throws Exception {
2602         when(mWifiService.getSupportedFeatures())
2603                 .thenReturn(new Long(WIFI_FEATURE_DPP_AKM));
2604         assertTrue(mWifiManager.isEasyConnectDppAkmSupported());
2605         when(mWifiService.getSupportedFeatures())
2606                 .thenReturn(new Long(~WIFI_FEATURE_DPP_AKM));
2607         assertFalse(mWifiManager.isEasyConnectDppAkmSupported());
2608     }
2609 
2610     /**
2611      * Test behavior of isEasyConnectEnrolleeResponderModeSupported
2612      */
2613     @Test
testIsEasyConnectEnrolleeResponderModeSupported()2614     public void testIsEasyConnectEnrolleeResponderModeSupported() throws Exception {
2615         assumeTrue(SdkLevel.isAtLeastS());
2616 
2617         when(mWifiService.getSupportedFeatures())
2618                 .thenReturn(new Long(WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
2619         assertTrue(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
2620         when(mWifiService.getSupportedFeatures())
2621                 .thenReturn(new Long(~WIFI_FEATURE_DPP_ENROLLEE_RESPONDER));
2622         assertFalse(mWifiManager.isEasyConnectEnrolleeResponderModeSupported());
2623     }
2624 
2625     /**
2626      * Test behavior of isStaApConcurrencySupported
2627      */
2628     @Test
testIsStaApConcurrencyOpenSupported()2629     public void testIsStaApConcurrencyOpenSupported() throws Exception {
2630         when(mWifiService.getSupportedFeatures())
2631                 .thenReturn(new Long(WIFI_FEATURE_AP_STA));
2632         assertTrue(mWifiManager.isStaApConcurrencySupported());
2633         when(mWifiService.getSupportedFeatures())
2634                 .thenReturn(new Long(~WIFI_FEATURE_AP_STA));
2635         assertFalse(mWifiManager.isStaApConcurrencySupported());
2636     }
2637 
2638     /**
2639      * Test behavior of isStaConcurrencySupported
2640      */
2641     @Test
testIsStaConcurrencySupported()2642     public void testIsStaConcurrencySupported() throws Exception {
2643         when(mWifiService.getSupportedFeatures()).thenReturn(0L);
2644         assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2645         assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2646         assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2647         assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
2648 
2649         when(mWifiService.getSupportedFeatures())
2650                 .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_LOCAL_ONLY));
2651         assertTrue(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2652         assertFalse(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2653         assertFalse(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2654         assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
2655 
2656         when(mWifiService.getSupportedFeatures())
2657                 .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MBB
2658                         | WIFI_FEATURE_ADDITIONAL_STA_RESTRICTED
2659                         | WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
2660         assertFalse(mWifiManager.isStaConcurrencyForLocalOnlyConnectionsSupported());
2661         assertTrue(mWifiManager.isMakeBeforeBreakWifiSwitchingSupported());
2662         assertTrue(mWifiManager.isStaConcurrencyForRestrictedConnectionsSupported());
2663         assertTrue(mWifiManager.isStaConcurrencyForMultiInternetSupported());
2664     }
2665 
2666     /**
2667      * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)}
2668      */
2669     @Test
testAddNetwork()2670     public void testAddNetwork() throws Exception {
2671         WifiConfiguration configuration = new WifiConfiguration();
2672         when(mWifiService.addOrUpdateNetwork(any(), anyString(), any()))
2673                 .thenReturn(TEST_NETWORK_ID);
2674 
2675         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
2676 
2677         assertEquals(mWifiManager.addNetwork(configuration), TEST_NETWORK_ID);
2678         verify(mWifiService).addOrUpdateNetwork(eq(configuration), eq(TEST_PACKAGE_NAME),
2679                 bundleCaptor.capture());
2680         if (SdkLevel.isAtLeastS()) {
2681             assertEquals(mContext.getAttributionSource(),
2682                     bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
2683         } else {
2684             assertNull(bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
2685         }
2686 
2687         // send a null config
2688         assertEquals(mWifiManager.addNetwork(null), -1);
2689     }
2690 
2691     /**
2692      * Test {@link WifiManager#addNetworkPrivileged(WifiConfiguration)} goes to WifiService.
2693      * Also verify that an IllegalArgumentException is thrown if the input is null.
2694      */
2695     @Test
testAddNetworkPrivileged()2696     public void testAddNetworkPrivileged() throws Exception {
2697         WifiConfiguration configuration = new WifiConfiguration();
2698         mWifiManager.addNetworkPrivileged(configuration);
2699         verify(mWifiService).addOrUpdateNetworkPrivileged(configuration,
2700                 mContext.getOpPackageName());
2701 
2702         // send a null config and verify an exception is thrown
2703         try {
2704             mWifiManager.addNetworkPrivileged(null);
2705             fail("configuration is null - IllegalArgumentException is expected.");
2706         } catch (IllegalArgumentException e) {
2707         }
2708     }
2709 
2710     /**
2711      * Test behavior of {@link WifiManager#addNetwork(WifiConfiguration)}
2712      */
2713     @Test
testUpdateNetwork()2714     public void testUpdateNetwork() throws Exception {
2715         WifiConfiguration configuration = new WifiConfiguration();
2716         when(mWifiService.addOrUpdateNetwork(any(), anyString(), any()))
2717                 .thenReturn(TEST_NETWORK_ID);
2718 
2719         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
2720 
2721         configuration.networkId = TEST_NETWORK_ID;
2722         assertEquals(mWifiManager.updateNetwork(configuration), TEST_NETWORK_ID);
2723         verify(mWifiService).addOrUpdateNetwork(eq(configuration), eq(TEST_PACKAGE_NAME),
2724                 bundleCaptor.capture());
2725         if (SdkLevel.isAtLeastS()) {
2726             assertEquals(mContext.getAttributionSource(),
2727                     bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
2728         } else {
2729             assertNull(bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
2730         }
2731 
2732         // config with invalid network ID
2733         configuration.networkId = -1;
2734         assertEquals(mWifiManager.updateNetwork(configuration), -1);
2735 
2736         // send a null config
2737         assertEquals(mWifiManager.updateNetwork(null), -1);
2738     }
2739 
2740     /**
2741      * Test behavior of {@link WifiManager#enableNetwork(int, boolean)}
2742      */
2743     @Test
testEnableNetwork()2744     public void testEnableNetwork() throws Exception {
2745         when(mWifiService.enableNetwork(anyInt(), anyBoolean(), anyString()))
2746                 .thenReturn(true);
2747         assertTrue(mWifiManager.enableNetwork(TEST_NETWORK_ID, true));
2748         verify(mWifiService).enableNetwork(TEST_NETWORK_ID, true, mContext.getOpPackageName());
2749     }
2750 
2751     /**
2752      * Test behavior of {@link WifiManager#disableNetwork(int)}
2753      */
2754     @Test
testDisableNetwork()2755     public void testDisableNetwork() throws Exception {
2756         when(mWifiService.disableNetwork(anyInt(), anyString()))
2757                 .thenReturn(true);
2758         assertTrue(mWifiManager.disableNetwork(TEST_NETWORK_ID));
2759         verify(mWifiService).disableNetwork(TEST_NETWORK_ID, mContext.getOpPackageName());
2760     }
2761 
2762     /**
2763      * Test behavior of {@link WifiManager#allowAutojoin(int, boolean)}
2764      * @throws Exception
2765      */
2766     @Test
testAllowAutojoin()2767     public void testAllowAutojoin() throws Exception {
2768         mWifiManager.allowAutojoin(1, true);
2769         verify(mWifiService).allowAutojoin(1, true);
2770     }
2771 
2772     /**
2773      * Test behavior of {@link WifiManager#allowAutojoinPasspoint(String, boolean)}
2774      * @throws Exception
2775      */
2776     @Test
testAllowAutojoinPasspoint()2777     public void testAllowAutojoinPasspoint() throws Exception {
2778         final String fqdn = "FullyQualifiedDomainName";
2779         mWifiManager.allowAutojoinPasspoint(fqdn, true);
2780         verify(mWifiService).allowAutojoinPasspoint(fqdn, true);
2781     }
2782 
2783     /**
2784      * Test behavior of
2785      * {@link WifiManager#setMacRandomizationSettingPasspointEnabled(String, boolean)}
2786      */
2787     @Test
testSetMacRandomizationSettingPasspointEnabled()2788     public void testSetMacRandomizationSettingPasspointEnabled() throws Exception {
2789         final String fqdn = "FullyQualifiedDomainName";
2790         mWifiManager.setMacRandomizationSettingPasspointEnabled(fqdn, true);
2791         verify(mWifiService).setMacRandomizationSettingPasspointEnabled(fqdn, true);
2792     }
2793 
2794     /**
2795      * Test behavior of
2796      * {@link WifiManager#setMacRandomizationSettingPasspointEnabled(String, boolean)}
2797      */
2798     @Test
testSetPasspointMeteredOverride()2799     public void testSetPasspointMeteredOverride() throws Exception {
2800         final String fqdn = "FullyQualifiedDomainName";
2801         mWifiManager.setPasspointMeteredOverride(fqdn, METERED_OVERRIDE_METERED);
2802         verify(mWifiService).setPasspointMeteredOverride(fqdn, METERED_OVERRIDE_METERED);
2803     }
2804 
2805     /**
2806      * Test behavior of {@link WifiManager#disconnect()}
2807      */
2808     @Test
testDisconnect()2809     public void testDisconnect() throws Exception {
2810         when(mWifiService.disconnect(anyString())).thenReturn(true);
2811         assertTrue(mWifiManager.disconnect());
2812         verify(mWifiService).disconnect(mContext.getOpPackageName());
2813     }
2814 
2815     /**
2816      * Test behavior of {@link WifiManager#reconnect()}
2817      */
2818     @Test
testReconnect()2819     public void testReconnect() throws Exception {
2820         when(mWifiService.reconnect(anyString())).thenReturn(true);
2821         assertTrue(mWifiManager.reconnect());
2822         verify(mWifiService).reconnect(mContext.getOpPackageName());
2823     }
2824 
2825     /**
2826      * Test behavior of {@link WifiManager#reassociate()}
2827      */
2828     @Test
testReassociate()2829     public void testReassociate() throws Exception {
2830         when(mWifiService.reassociate(anyString())).thenReturn(true);
2831         assertTrue(mWifiManager.reassociate());
2832         verify(mWifiService).reassociate(mContext.getOpPackageName());
2833     }
2834 
2835     /**
2836      * Test behavior of {@link WifiManager#getSupportedFeatures()}
2837      */
2838     @Test
testGetSupportedFeatures()2839     public void testGetSupportedFeatures() throws Exception {
2840         long supportedFeatures =
2841                 WIFI_FEATURE_SCANNER
2842                         | WIFI_FEATURE_PASSPOINT
2843                         | WIFI_FEATURE_P2P;
2844         when(mWifiService.getSupportedFeatures())
2845                 .thenReturn(Long.valueOf(supportedFeatures));
2846 
2847         assertTrue(mWifiManager.isWifiScannerSupported());
2848         assertTrue(mWifiManager.isPasspointSupported());
2849         assertTrue(mWifiManager.isP2pSupported());
2850         assertFalse(mWifiManager.isPortableHotspotSupported());
2851         assertFalse(mWifiManager.isDeviceToDeviceRttSupported());
2852         assertFalse(mWifiManager.isDeviceToApRttSupported());
2853         assertFalse(mWifiManager.isPreferredNetworkOffloadSupported());
2854         assertFalse(mWifiManager.isTdlsSupported());
2855         assertFalse(mWifiManager.isOffChannelTdlsSupported());
2856         assertFalse(mWifiManager.isEnhancedPowerReportingSupported());
2857     }
2858 
2859     /**
2860      * Tests that passing a null Executor to {@link WifiManager#getWifiActivityEnergyInfoAsync}
2861      * throws an exception.
2862      */
2863     @Test(expected = NullPointerException.class)
testGetWifiActivityInfoNullExecutor()2864     public void testGetWifiActivityInfoNullExecutor() throws Exception {
2865         mWifiManager.getWifiActivityEnergyInfoAsync(null, mOnWifiActivityEnergyInfoListener);
2866     }
2867 
2868     /**
2869      * Tests that passing a null listener to {@link WifiManager#getWifiActivityEnergyInfoAsync}
2870      * throws an exception.
2871      */
2872     @Test(expected = NullPointerException.class)
testGetWifiActivityInfoNullListener()2873     public void testGetWifiActivityInfoNullListener() throws Exception {
2874         mWifiManager.getWifiActivityEnergyInfoAsync(mExecutor, null);
2875     }
2876 
2877     /** Tests that the listener runs on the correct Executor. */
2878     @Test
testGetWifiActivityInfoRunsOnCorrectExecutor()2879     public void testGetWifiActivityInfoRunsOnCorrectExecutor() throws Exception {
2880         mWifiManager.getWifiActivityEnergyInfoAsync(mExecutor, mOnWifiActivityEnergyInfoListener);
2881         ArgumentCaptor<IOnWifiActivityEnergyInfoListener> listenerCaptor =
2882                 ArgumentCaptor.forClass(IOnWifiActivityEnergyInfoListener.class);
2883         verify(mWifiService).getWifiActivityEnergyInfoAsync(listenerCaptor.capture());
2884         IOnWifiActivityEnergyInfoListener listener = listenerCaptor.getValue();
2885         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2886         verify(mExecutor).execute(any());
2887 
2888         // ensure that the executor is only triggered once
2889         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2890         verify(mExecutor).execute(any());
2891     }
2892 
2893     /** Tests that the correct listener runs. */
2894     @Test
testGetWifiActivityInfoRunsCorrectListener()2895     public void testGetWifiActivityInfoRunsCorrectListener() throws Exception {
2896         int[] flag = {0};
2897         mWifiManager.getWifiActivityEnergyInfoAsync(
2898                 new SynchronousExecutor(), info -> flag[0]++);
2899         ArgumentCaptor<IOnWifiActivityEnergyInfoListener> listenerCaptor =
2900                 ArgumentCaptor.forClass(IOnWifiActivityEnergyInfoListener.class);
2901         verify(mWifiService).getWifiActivityEnergyInfoAsync(listenerCaptor.capture());
2902         IOnWifiActivityEnergyInfoListener listener = listenerCaptor.getValue();
2903         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2904         assertEquals(1, flag[0]);
2905 
2906         // ensure that the listener is only triggered once
2907         listener.onWifiActivityEnergyInfo(mWifiActivityEnergyInfo);
2908         assertEquals(1, flag[0]);
2909     }
2910 
2911     /**
2912      * Test behavior of {@link WifiManager#getConnectionInfo()}
2913      */
2914     @Test
testGetConnectionInfo()2915     public void testGetConnectionInfo() throws Exception {
2916         WifiInfo wifiInfo = new WifiInfo();
2917         when(mWifiService.getConnectionInfo(anyString(), nullable(String.class))).thenReturn(
2918                 wifiInfo);
2919 
2920         assertEquals(wifiInfo, mWifiManager.getConnectionInfo());
2921     }
2922 
2923     /**
2924      * Test behavior of {@link WifiManager#is24GHzBandSupported()}
2925      */
2926     @Test
testIs24GHzBandSupported()2927     public void testIs24GHzBandSupported() throws Exception {
2928         when(mWifiService.is24GHzBandSupported()).thenReturn(true);
2929         assertTrue(mWifiManager.is24GHzBandSupported());
2930         verify(mWifiService).is24GHzBandSupported();
2931     }
2932 
2933     /**
2934      * Test behavior of {@link WifiManager#is5GHzBandSupported()}
2935      */
2936     @Test
testIs5GHzBandSupported()2937     public void testIs5GHzBandSupported() throws Exception {
2938         when(mWifiService.is5GHzBandSupported()).thenReturn(true);
2939         assertTrue(mWifiManager.is5GHzBandSupported());
2940         verify(mWifiService).is5GHzBandSupported();
2941     }
2942 
2943     /**
2944      * Test behavior of {@link WifiManager#is6GHzBandSupported()}
2945      */
2946     @Test
testIs6GHzBandSupported()2947     public void testIs6GHzBandSupported() throws Exception {
2948         when(mWifiService.is6GHzBandSupported()).thenReturn(true);
2949         assertTrue(mWifiManager.is6GHzBandSupported());
2950         verify(mWifiService).is6GHzBandSupported();
2951     }
2952 
2953     /**
2954      * Test behavior of {@link WifiManager#is60GHzBandSupported()}
2955      */
2956     @Test
testIs60GHzBandSupported()2957     public void testIs60GHzBandSupported() throws Exception {
2958         assumeTrue(SdkLevel.isAtLeastS());
2959 
2960         when(mWifiService.is60GHzBandSupported()).thenReturn(true);
2961         assertTrue(mWifiManager.is60GHzBandSupported());
2962         verify(mWifiService).is60GHzBandSupported();
2963     }
2964 
2965     /**
2966      * Test behavior of {@link WifiManager#isWifiStandardSupported()}
2967      */
2968     @Test
testIsWifiStandardSupported()2969     public void testIsWifiStandardSupported() throws Exception {
2970         int standard = ScanResult.WIFI_STANDARD_11AX;
2971         when(mWifiService.isWifiStandardSupported(standard)).thenReturn(true);
2972         assertTrue(mWifiManager.isWifiStandardSupported(standard));
2973         verify(mWifiService).isWifiStandardSupported(standard);
2974     }
2975 
2976     /**
2977      * Test behavior of {@link WifiManager#getDhcpInfo()}
2978      */
2979     @Test
testGetDhcpInfo()2980     public void testGetDhcpInfo() throws Exception {
2981         DhcpInfo dhcpInfo = new DhcpInfo();
2982 
2983         when(mWifiService.getDhcpInfo(TEST_PACKAGE_NAME)).thenReturn(dhcpInfo);
2984         assertEquals(dhcpInfo, mWifiManager.getDhcpInfo());
2985         verify(mWifiService).getDhcpInfo(TEST_PACKAGE_NAME);
2986     }
2987 
2988     /**
2989      * Test behavior of {@link WifiManager#setWifiEnabled(boolean)}
2990      */
2991     @Test
testSetWifiEnabled()2992     public void testSetWifiEnabled() throws Exception {
2993         when(mWifiService.setWifiEnabled(anyString(), anyBoolean())).thenReturn(true);
2994         assertTrue(mWifiManager.setWifiEnabled(true));
2995         verify(mWifiService).setWifiEnabled(mContext.getOpPackageName(), true);
2996         assertTrue(mWifiManager.setWifiEnabled(false));
2997         verify(mWifiService).setWifiEnabled(mContext.getOpPackageName(), false);
2998     }
2999 
3000     /**
3001      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
3002      */
3003     @Test
testConnectWithListener()3004     public void testConnectWithListener() throws Exception {
3005         ActionListener externalListener = mock(ActionListener.class);
3006         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
3007 
3008         ArgumentCaptor<IActionListener> binderListenerCaptor =
3009                 ArgumentCaptor.forClass(IActionListener.class);
3010         verify(mWifiService).connect(eq(null), eq(TEST_NETWORK_ID), binderListenerCaptor.capture(),
3011                 anyString(), any());
3012         assertNotNull(binderListenerCaptor.getValue());
3013 
3014         // Trigger on success.
3015         binderListenerCaptor.getValue().onSuccess();
3016         mLooper.dispatchAll();
3017         verify(externalListener).onSuccess();
3018 
3019         // Trigger on failure.
3020         binderListenerCaptor.getValue().onFailure(WifiManager.ActionListener.FAILURE_BUSY);
3021         mLooper.dispatchAll();
3022         verify(externalListener).onFailure(WifiManager.ActionListener.FAILURE_BUSY);
3023     }
3024 
3025     /**
3026      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
3027      */
3028     @Test
testConnectWithListenerHandleSecurityException()3029     public void testConnectWithListenerHandleSecurityException() throws Exception {
3030         doThrow(new SecurityException()).when(mWifiService)
3031                 .connect(eq(null), anyInt(), any(IActionListener.class), anyString(), any());
3032         ActionListener externalListener = mock(ActionListener.class);
3033         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
3034 
3035         mLooper.dispatchAll();
3036         verify(externalListener).onFailure(ActionListener.FAILURE_NOT_AUTHORIZED);
3037     }
3038 
3039     /**
3040      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
3041      */
3042     @Test
testConnectWithListenerHandleRemoteException()3043     public void testConnectWithListenerHandleRemoteException() throws Exception {
3044         doThrow(new RemoteException()).when(mWifiService)
3045                 .connect(eq(null), anyInt(), any(IActionListener.class), anyString(), any());
3046         ActionListener externalListener = mock(ActionListener.class);
3047         mWifiManager.connect(TEST_NETWORK_ID, externalListener);
3048 
3049         mLooper.dispatchAll();
3050         verify(externalListener).onFailure(ActionListener.FAILURE_INTERNAL_ERROR);
3051     }
3052 
3053     /**
3054      * Test behavior of {@link WifiManager#connect(int, ActionListener)}
3055      */
3056     @Test
testConnectWithoutListener()3057     public void testConnectWithoutListener() throws Exception {
3058         WifiConfiguration configuration = new WifiConfiguration();
3059         mWifiManager.connect(configuration, null);
3060 
3061         verify(mWifiService).connect(eq(configuration), eq(WifiConfiguration.INVALID_NETWORK_ID),
3062                 eq(null), anyString(), any());
3063     }
3064 
3065     /**
3066      * Verify an IllegalArgumentException is thrown if callback is not provided.
3067      */
3068     @Test(expected = IllegalArgumentException.class)
testRegisterScanResultsCallbackWithNullCallback()3069     public void testRegisterScanResultsCallbackWithNullCallback() throws Exception {
3070         mWifiManager.registerScanResultsCallback(mExecutor, null);
3071     }
3072 
3073     /**
3074      * Verify an IllegalArgumentException is thrown if executor is not provided.
3075      */
3076     @Test(expected = IllegalArgumentException.class)
testRegisterCallbackWithNullExecutor()3077     public void testRegisterCallbackWithNullExecutor() throws Exception {
3078         mWifiManager.registerScanResultsCallback(null, mScanResultsCallback);
3079     }
3080 
3081     /**
3082      * Verify client provided callback is being called to the right callback.
3083      */
3084     @Test
testAddScanResultsCallbackAndReceiveEvent()3085     public void testAddScanResultsCallbackAndReceiveEvent() throws Exception {
3086         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
3087                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
3088         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
3089         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
3090         callbackCaptor.getValue().onScanResultsAvailable();
3091         verify(mRunnable).run();
3092     }
3093 
3094     /**
3095      * Verify client provided callback is being called to the right executor.
3096      */
3097     @Test
testRegisterScanResultsCallbackWithTheTargetExecutor()3098     public void testRegisterScanResultsCallbackWithTheTargetExecutor() throws Exception {
3099         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
3100                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
3101         mWifiManager.registerScanResultsCallback(mExecutor, mScanResultsCallback);
3102         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
3103         mWifiManager.registerScanResultsCallback(mAnotherExecutor, mScanResultsCallback);
3104         callbackCaptor.getValue().onScanResultsAvailable();
3105         verify(mExecutor, never()).execute(any(Runnable.class));
3106         verify(mAnotherExecutor).execute(any(Runnable.class));
3107     }
3108 
3109     /**
3110      * Verify client register unregister then register again, to ensure callback still works.
3111      */
3112     @Test
testRegisterUnregisterThenRegisterAgainWithScanResultCallback()3113     public void testRegisterUnregisterThenRegisterAgainWithScanResultCallback() throws Exception {
3114         ArgumentCaptor<IScanResultsCallback.Stub> callbackCaptor =
3115                 ArgumentCaptor.forClass(IScanResultsCallback.Stub.class);
3116         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
3117         verify(mWifiService).registerScanResultsCallback(callbackCaptor.capture());
3118         mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
3119         callbackCaptor.getValue().onScanResultsAvailable();
3120         verify(mRunnable, never()).run();
3121         mWifiManager.registerScanResultsCallback(new SynchronousExecutor(), mScanResultsCallback);
3122         callbackCaptor.getValue().onScanResultsAvailable();
3123         verify(mRunnable).run();
3124     }
3125 
3126     /**
3127      * Verify client unregisterScanResultsCallback.
3128      */
3129     @Test
testUnregisterScanResultsCallback()3130     public void testUnregisterScanResultsCallback() throws Exception {
3131         mWifiManager.unregisterScanResultsCallback(mScanResultsCallback);
3132         verify(mWifiService).unregisterScanResultsCallback(any());
3133     }
3134 
3135     /**
3136      * Verify client unregisterScanResultsCallback with null callback will cause an exception.
3137      */
3138     @Test(expected = IllegalArgumentException.class)
testUnregisterScanResultsCallbackWithNullCallback()3139     public void testUnregisterScanResultsCallbackWithNullCallback() throws Exception {
3140         mWifiManager.unregisterScanResultsCallback(null);
3141     }
3142 
3143     /**
3144      * Verify an IllegalArgumentException is thrown if executor not provided.
3145      */
3146     @Test(expected = IllegalArgumentException.class)
testAddSuggestionConnectionStatusListenerWithNullExecutor()3147     public void testAddSuggestionConnectionStatusListenerWithNullExecutor() {
3148         mWifiManager.addSuggestionConnectionStatusListener(null, mSuggestionConnectionListener);
3149     }
3150 
3151     /**
3152      * Verify an IllegalArgumentException is thrown if listener is not provided.
3153      */
3154     @Test(expected = IllegalArgumentException.class)
testAddSuggestionConnectionStatusListenerWithNullListener()3155     public void testAddSuggestionConnectionStatusListenerWithNullListener() {
3156         mWifiManager.addSuggestionConnectionStatusListener(mExecutor, null);
3157     }
3158 
3159     /**
3160      * Verify client provided listener is being called to the right listener.
3161      */
3162     @Test
testAddSuggestionConnectionStatusListenerAndReceiveEvent()3163     public void testAddSuggestionConnectionStatusListenerAndReceiveEvent() throws Exception {
3164         int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
3165         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
3166                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
3167         Executor executor = new SynchronousExecutor();
3168         mWifiManager.addSuggestionConnectionStatusListener(executor,
3169                 mSuggestionConnectionListener);
3170         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
3171                 anyString(), nullable(String.class));
3172         callbackCaptor.getValue().onConnectionStatus(mWifiNetworkSuggestion, errorCode);
3173         verify(mSuggestionConnectionListener).onConnectionStatus(any(WifiNetworkSuggestion.class),
3174                 eq(errorCode));
3175     }
3176 
3177     /**
3178      * Verify client provided listener is being called to the right executor.
3179      */
3180     @Test
testAddSuggestionConnectionStatusListenerWithTheTargetExecutor()3181     public void testAddSuggestionConnectionStatusListenerWithTheTargetExecutor() throws Exception {
3182         int errorCode = STATUS_SUGGESTION_CONNECTION_FAILURE_AUTHENTICATION;
3183         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
3184                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
3185         mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
3186                 mSuggestionConnectionListener);
3187         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
3188                 anyString(), nullable(String.class));
3189         callbackCaptor.getValue().onConnectionStatus(any(WifiNetworkSuggestion.class), errorCode);
3190         verify(mExecutor).execute(any(Runnable.class));
3191     }
3192 
3193     /**
3194      * Verify an IllegalArgumentException is thrown if listener is not provided.
3195      */
3196     @Test(expected = IllegalArgumentException.class)
testRemoveSuggestionConnectionListenerWithNullListener()3197     public void testRemoveSuggestionConnectionListenerWithNullListener() {
3198         mWifiManager.removeSuggestionConnectionStatusListener(null);
3199     }
3200 
3201     /**
3202      * Verify removeSuggestionConnectionListener.
3203      */
3204     @Test
testRemoveSuggestionConnectionListener()3205     public void testRemoveSuggestionConnectionListener() throws Exception {
3206         ArgumentCaptor<ISuggestionConnectionStatusListener.Stub> callbackCaptor =
3207                 ArgumentCaptor.forClass(ISuggestionConnectionStatusListener.Stub.class);
3208         mWifiManager.addSuggestionConnectionStatusListener(mExecutor,
3209                 mSuggestionConnectionListener);
3210         verify(mWifiService).registerSuggestionConnectionStatusListener(callbackCaptor.capture(),
3211                 anyString(), nullable(String.class));
3212 
3213         mWifiManager.removeSuggestionConnectionStatusListener(mSuggestionConnectionListener);
3214         verify(mWifiService).unregisterSuggestionConnectionStatusListener(
3215                 eq(callbackCaptor.getValue()), anyString());
3216     }
3217 
3218     /** Test {@link WifiManager#calculateSignalLevel(int)} */
3219     @Test
testCalculateSignalLevel()3220     public void testCalculateSignalLevel() throws Exception {
3221         when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(3);
3222         int actual = mWifiManager.calculateSignalLevel(-60);
3223         verify(mWifiService).calculateSignalLevel(-60);
3224         assertEquals(3, actual);
3225     }
3226 
3227     /** Test {@link WifiManager#getMaxSignalLevel()} */
3228     @Test
testGetMaxSignalLevel()3229     public void testGetMaxSignalLevel() throws Exception {
3230         when(mWifiService.calculateSignalLevel(anyInt())).thenReturn(4);
3231         int actual = mWifiManager.getMaxSignalLevel();
3232         verify(mWifiService).calculateSignalLevel(Integer.MAX_VALUE);
3233         assertEquals(4, actual);
3234     }
3235 
3236     /*
3237      * Test behavior of isWapiSupported
3238      * @throws Exception
3239      */
3240     @Test
testIsWapiSupported()3241     public void testIsWapiSupported() throws Exception {
3242         when(mWifiService.getSupportedFeatures())
3243                 .thenReturn(new Long(WifiManager.WIFI_FEATURE_WAPI));
3244         assertTrue(mWifiManager.isWapiSupported());
3245         when(mWifiService.getSupportedFeatures())
3246                 .thenReturn(new Long(~WifiManager.WIFI_FEATURE_WAPI));
3247         assertFalse(mWifiManager.isWapiSupported());
3248     }
3249 
3250     /*
3251      * Test that DPP channel list is parsed correctly
3252      */
3253     @Test
testparseDppChannelList()3254     public void testparseDppChannelList() throws Exception {
3255         String channelList = "81/1,2,3,4,5,6,7,8,9,10,11,115/36,40,44,48";
3256         SparseArray<int[]> expectedResult = new SparseArray<>();
3257         expectedResult.append(81, new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
3258         expectedResult.append(115, new int[]{36, 40, 44, 48});
3259 
3260         SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
3261         assertEquals(expectedResult.size(), result.size());
3262 
3263         int index = 0;
3264         int key;
3265 
3266         // Compare the two primitive int arrays
3267         do {
3268             try {
3269                 key = result.keyAt(index);
3270             } catch (java.lang.ArrayIndexOutOfBoundsException e) {
3271                 break;
3272             }
3273             int[] expected = expectedResult.get(key);
3274             int[] output = result.get(key);
3275             assertEquals(expected.length, output.length);
3276             for (int i = 0; i < output.length; i++) {
3277                 assertEquals(expected[i], output[i]);
3278             }
3279             index++;
3280         } while (true);
3281     }
3282 
3283     /*
3284      * Test that DPP channel list parser gracefully fails for invalid input
3285      */
3286     @Test
testparseDppChannelListWithInvalidFormats()3287     public void testparseDppChannelListWithInvalidFormats() throws Exception {
3288         String channelList = "1,2,3,4,5,6,7,8,9,10,11,36,40,44,48";
3289         SparseArray<int[]> result = WifiManager.parseDppChannelList(channelList);
3290         assertEquals(result.size(), 0);
3291 
3292         channelList = "ajgalskgjalskjg3-09683dh";
3293         result = WifiManager.parseDppChannelList(channelList);
3294         assertEquals(result.size(), 0);
3295 
3296         channelList = "13/abc,46////";
3297         result = WifiManager.parseDppChannelList(channelList);
3298         assertEquals(result.size(), 0);
3299 
3300         channelList = "11/4,5,13/";
3301         result = WifiManager.parseDppChannelList(channelList);
3302         assertEquals(result.size(), 0);
3303 
3304         channelList = "/24,6";
3305         result = WifiManager.parseDppChannelList(channelList);
3306         assertEquals(result.size(), 0);
3307     }
3308 
3309     /**
3310      * Test getWifiConfigsForMatchedNetworkSuggestions for given scanResults.
3311      */
3312     @Test
testGetWifiConfigsForMatchedNetworkSuggestions()3313     public void testGetWifiConfigsForMatchedNetworkSuggestions() throws Exception {
3314         List<WifiConfiguration> testResults = new ArrayList<>();
3315         testResults.add(new WifiConfiguration());
3316 
3317         when(mWifiService.getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(any(List.class)))
3318                 .thenReturn(testResults);
3319         assertEquals(testResults, mWifiManager
3320                 .getWifiConfigForMatchedNetworkSuggestionsSharedWithUser(new ArrayList<>()));
3321     }
3322 
3323     /**
3324      * Verify the call to setWifiConnectedNetworkScorer goes to WifiServiceImpl.
3325      */
3326     @Test
setWifiConnectedNetworkScorerGoesToWifiServiceImpl()3327     public void setWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception {
3328         mExecutor = new SynchronousExecutor();
3329         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3330         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3331                 any(IWifiConnectedNetworkScorer.Stub.class));
3332     }
3333 
3334     /**
3335      * Verify the call to clearWifiConnectedNetworkScorer goes to WifiServiceImpl.
3336      */
3337     @Test
clearWifiConnectedNetworkScorerGoesToWifiServiceImpl()3338     public void clearWifiConnectedNetworkScorerGoesToWifiServiceImpl() throws Exception {
3339         mExecutor = new SynchronousExecutor();
3340         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3341         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3342                 any(IWifiConnectedNetworkScorer.Stub.class));
3343 
3344         mWifiManager.clearWifiConnectedNetworkScorer();
3345         verify(mWifiService).clearWifiConnectedNetworkScorer();
3346     }
3347 
3348     /**
3349      * Verify that Wi-Fi connected scorer receives score update observer after registeration.
3350      */
3351     @Test
verifyScorerReceiveScoreUpdateObserverAfterRegistration()3352     public void verifyScorerReceiveScoreUpdateObserverAfterRegistration() throws Exception {
3353         mExecutor = new SynchronousExecutor();
3354         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3355         ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> scorerCaptor =
3356                 ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class);
3357         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3358                 scorerCaptor.capture());
3359         scorerCaptor.getValue().onSetScoreUpdateObserver(any());
3360         mLooper.dispatchAll();
3361         verify(mWifiConnectedNetworkScorer).onSetScoreUpdateObserver(any());
3362     }
3363 
3364     /**
3365      * Verify that Wi-Fi connected scorer receives session ID when onStart/onStop methods
3366      * are called.
3367      */
3368     @Test
verifyScorerReceiveSessionIdWhenStartStopIsCalled()3369     public void verifyScorerReceiveSessionIdWhenStartStopIsCalled() throws Exception {
3370         mExecutor = new SynchronousExecutor();
3371         mWifiManager.setWifiConnectedNetworkScorer(mExecutor, mWifiConnectedNetworkScorer);
3372         ArgumentCaptor<IWifiConnectedNetworkScorer.Stub> callbackCaptor =
3373                 ArgumentCaptor.forClass(IWifiConnectedNetworkScorer.Stub.class);
3374         verify(mWifiService).setWifiConnectedNetworkScorer(any(IBinder.class),
3375                 callbackCaptor.capture());
3376         callbackCaptor.getValue().onStart(new WifiConnectedSessionInfo.Builder(10)
3377                 .setUserSelected(true)
3378                 .build());
3379         callbackCaptor.getValue().onStop(10);
3380         mLooper.dispatchAll();
3381         verify(mWifiConnectedNetworkScorer).onStart(
3382                 argThat(sessionInfo -> sessionInfo.getSessionId() == 10
3383                         && sessionInfo.isUserSelected()));
3384         verify(mWifiConnectedNetworkScorer).onStop(10);
3385     }
3386 
3387     /**
3388      * Verify the call to setWifiScoringEnabled goes to WifiServiceImpl.
3389      */
3390     @Test
setWifiScoringEnabledGoesToWifiServiceImpl()3391     public void setWifiScoringEnabledGoesToWifiServiceImpl() throws Exception {
3392         mWifiManager.setWifiScoringEnabled(true);
3393         verify(mWifiService).setWifiScoringEnabled(true);
3394     }
3395 
3396     /**
3397      * Verify the call to addCustomDhcpOptions goes to WifiServiceImpl.
3398      */
3399     @Test
addCustomDhcpOptionsGoesToWifiServiceImpl()3400     public void addCustomDhcpOptionsGoesToWifiServiceImpl() throws Exception {
3401         assumeTrue(SdkLevel.isAtLeastT());
3402         mWifiManager.addCustomDhcpOptions(
3403                 WifiSsid.fromString(TEST_SSID), TEST_OUI, new ArrayList<DhcpOption>());
3404         verify(mWifiService).addCustomDhcpOptions(
3405                 WifiSsid.fromString(TEST_SSID), TEST_OUI, new ArrayList<DhcpOption>());
3406     }
3407 
3408     /**
3409      * Verify the call to removeCustomDhcpOptions goes to WifiServiceImpl.
3410      */
3411     @Test
removeCustomDhcpOptionsGoesToWifiServiceImpl()3412     public void removeCustomDhcpOptionsGoesToWifiServiceImpl() throws Exception {
3413         assumeTrue(SdkLevel.isAtLeastT());
3414         mWifiManager.removeCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), TEST_OUI);
3415         verify(mWifiService).removeCustomDhcpOptions(WifiSsid.fromString(TEST_SSID), TEST_OUI);
3416     }
3417 
3418     @Test
testScanThrottle()3419     public void testScanThrottle() throws Exception {
3420         mWifiManager.setScanThrottleEnabled(true);
3421         verify(mWifiService).setScanThrottleEnabled(true);
3422 
3423         when(mWifiService.isScanThrottleEnabled()).thenReturn(false);
3424         assertFalse(mWifiManager.isScanThrottleEnabled());
3425         verify(mWifiService).isScanThrottleEnabled();
3426     }
3427 
3428     @Test
testAutoWakeup()3429     public void testAutoWakeup() throws Exception {
3430         mWifiManager.setAutoWakeupEnabled(true);
3431         verify(mWifiService).setAutoWakeupEnabled(true);
3432 
3433         when(mWifiService.isAutoWakeupEnabled()).thenReturn(false);
3434         assertFalse(mWifiManager.isAutoWakeupEnabled());
3435         verify(mWifiService).isAutoWakeupEnabled();
3436     }
3437 
3438 
3439     @Test
testScanAvailable()3440     public void testScanAvailable() throws Exception {
3441         mWifiManager.setScanAlwaysAvailable(true);
3442         verify(mWifiService).setScanAlwaysAvailable(true, TEST_PACKAGE_NAME);
3443 
3444         when(mWifiService.isScanAlwaysAvailable()).thenReturn(false);
3445         assertFalse(mWifiManager.isScanAlwaysAvailable());
3446         verify(mWifiService).isScanAlwaysAvailable();
3447     }
3448 
3449     @Test
testSetCarrierNetworkOffload()3450     public void testSetCarrierNetworkOffload() throws Exception {
3451         mWifiManager.setCarrierNetworkOffloadEnabled(TEST_SUB_ID, true, false);
3452         verify(mWifiService).setCarrierNetworkOffloadEnabled(TEST_SUB_ID,
3453                 true, false);
3454     }
3455 
3456     @Test
testGetCarrierNetworkOffload()3457     public void testGetCarrierNetworkOffload() throws Exception {
3458         when(mWifiService.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false)).thenReturn(true);
3459         assertTrue(mWifiManager.isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false));
3460         verify(mWifiService).isCarrierNetworkOffloadEnabled(TEST_SUB_ID, false);
3461     }
3462 
3463 
3464     /**
3465      * Verify an IllegalArgumentException is thrown if listener is not provided.
3466      */
3467     @Test(expected = IllegalArgumentException.class)
testRemoveSuggestionUserApprovalStatusListenerWithNullListener()3468     public void testRemoveSuggestionUserApprovalStatusListenerWithNullListener() {
3469         mWifiManager.removeSuggestionUserApprovalStatusListener(null);
3470     }
3471 
3472 
3473     /**
3474      * Verify removeSuggestionUserApprovalStatusListener.
3475      */
3476     @Test
testRemoveSuggestionUserApprovalStatusListener()3477     public void testRemoveSuggestionUserApprovalStatusListener() throws Exception {
3478         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3479                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3480         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
3481                 mSuggestionUserApprovalStatusListener);
3482         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3483                 anyString());
3484 
3485         mWifiManager.removeSuggestionUserApprovalStatusListener(
3486                 mSuggestionUserApprovalStatusListener);
3487         verify(mWifiService).removeSuggestionUserApprovalStatusListener(
3488                 eq(callbackCaptor.getValue()), anyString());
3489     }
3490 
3491     /**
3492      * Verify an IllegalArgumentException is thrown if executor not provided.
3493      */
3494     @Test(expected = NullPointerException.class)
testAddSuggestionUserApprovalStatusListenerWithNullExecutor()3495     public void testAddSuggestionUserApprovalStatusListenerWithNullExecutor() {
3496         mWifiManager.addSuggestionUserApprovalStatusListener(null,
3497                 mSuggestionUserApprovalStatusListener);
3498     }
3499 
3500     /**
3501      * Verify an IllegalArgumentException is thrown if listener is not provided.
3502      */
3503     @Test(expected = NullPointerException.class)
testAddSuggestionUserApprovalStatusListenerWithNullListener()3504     public void testAddSuggestionUserApprovalStatusListenerWithNullListener() {
3505         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor, null);
3506     }
3507 
3508     /**
3509      * Verify client provided listener is being called to the right listener.
3510      */
3511     @Test
testAddSuggestionUserApprovalStatusListenerAndReceiveEvent()3512     public void testAddSuggestionUserApprovalStatusListenerAndReceiveEvent() throws Exception {
3513         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3514                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3515         Executor executor = new SynchronousExecutor();
3516         mWifiManager.addSuggestionUserApprovalStatusListener(executor,
3517                 mSuggestionUserApprovalStatusListener);
3518         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3519                 anyString());
3520         callbackCaptor.getValue().onUserApprovalStatusChange(
3521                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3522         verify(mSuggestionUserApprovalStatusListener).onUserApprovalStatusChange(
3523                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3524     }
3525 
3526     /**
3527      * Verify client provided listener is being called to the right executor.
3528      */
3529     @Test
testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()3530     public void testAddSuggestionUserApprovalStatusListenerWithTheTargetExecutor()
3531             throws Exception {
3532         ArgumentCaptor<ISuggestionUserApprovalStatusListener.Stub> callbackCaptor =
3533                 ArgumentCaptor.forClass(ISuggestionUserApprovalStatusListener.Stub.class);
3534         mWifiManager.addSuggestionUserApprovalStatusListener(mExecutor,
3535                 mSuggestionUserApprovalStatusListener);
3536         verify(mWifiService).addSuggestionUserApprovalStatusListener(callbackCaptor.capture(),
3537                 anyString());
3538         callbackCaptor.getValue().onUserApprovalStatusChange(
3539                 WifiManager.STATUS_SUGGESTION_APPROVAL_APPROVED_BY_USER);
3540         verify(mExecutor).execute(any(Runnable.class));
3541     }
3542 
3543     @Test
testSetExternalPnoScanRequestNullFrequencies()3544     public void testSetExternalPnoScanRequestNullFrequencies() throws Exception {
3545         mWifiManager.setExternalPnoScanRequest(Collections.EMPTY_LIST, null,
3546                 mock(Executor.class), mock(WifiManager.PnoScanResultsCallback.class));
3547         // null frequencies should get converted to empty array
3548         verify(mWifiService).setExternalPnoScanRequest(any(), any(), eq(Collections.EMPTY_LIST),
3549                 eq(new int[0]), any(), any());
3550     }
3551 
3552     @Test
testSetEmergencyScanRequestInProgress()3553     public void testSetEmergencyScanRequestInProgress() throws Exception {
3554         mWifiManager.setEmergencyScanRequestInProgress(true);
3555         verify(mWifiService).setEmergencyScanRequestInProgress(true);
3556 
3557         mWifiManager.setEmergencyScanRequestInProgress(false);
3558         verify(mWifiService).setEmergencyScanRequestInProgress(false);
3559     }
3560 
3561     @Test
testRemoveAppState()3562     public void testRemoveAppState() throws Exception {
3563         mWifiManager.removeAppState(TEST_UID, TEST_PACKAGE_NAME);
3564         verify(mWifiService).removeAppState(TEST_UID, TEST_PACKAGE_NAME);
3565     }
3566 
3567     /**
3568      * Test behavior of isPasspointTermsAndConditionsSupported
3569      */
3570     @Test
testIsPasspointTermsAndConditionsSupported()3571     public void testIsPasspointTermsAndConditionsSupported() throws Exception {
3572         when(mWifiService.getSupportedFeatures())
3573                 .thenReturn(new Long(WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
3574         assertTrue(mWifiManager.isPasspointTermsAndConditionsSupported());
3575         when(mWifiService.getSupportedFeatures())
3576                 .thenReturn(new Long(~WIFI_FEATURE_PASSPOINT_TERMS_AND_CONDITIONS));
3577         assertFalse(mWifiManager.isPasspointTermsAndConditionsSupported());
3578     }
3579 
3580     /**
3581      * Verify the call to setOverrideCountryCode goes to WifiServiceImpl.
3582      */
3583     @Test
testSetOverrideCountryCode()3584     public void testSetOverrideCountryCode() throws Exception {
3585         assumeTrue(SdkLevel.isAtLeastS());
3586         mWifiManager.setOverrideCountryCode(TEST_COUNTRY_CODE);
3587         verify(mWifiService).setOverrideCountryCode(eq(TEST_COUNTRY_CODE));
3588     }
3589 
3590     /**
3591      * Verify the call to clearOverrideCountryCode goes to WifiServiceImpl.
3592      */
3593     @Test
testClearOverrideCountryCode()3594     public void testClearOverrideCountryCode() throws Exception {
3595         assumeTrue(SdkLevel.isAtLeastS());
3596         mWifiManager.clearOverrideCountryCode();
3597         verify(mWifiService).clearOverrideCountryCode();
3598     }
3599 
3600     /**
3601      * Verify the call to setDefaultCountryCode goes to WifiServiceImpl.
3602      */
3603     @Test
testSetDefaultCountryCode()3604     public void testSetDefaultCountryCode() throws Exception {
3605         assumeTrue(SdkLevel.isAtLeastS());
3606         mWifiManager.setDefaultCountryCode(TEST_COUNTRY_CODE);
3607         verify(mWifiService).setDefaultCountryCode(eq(TEST_COUNTRY_CODE));
3608     }
3609 
3610     /**
3611      * Test behavior of flushPasspointAnqpCache
3612      */
3613     @Test
testFlushPasspointAnqpCache()3614     public void testFlushPasspointAnqpCache() throws Exception {
3615         mWifiManager.flushPasspointAnqpCache();
3616         verify(mWifiService).flushPasspointAnqpCache(anyString());
3617     }
3618 
3619     @Test
testSetPnoScanState()3620     public void testSetPnoScanState() throws Exception {
3621         mWifiManager.setPnoScanState(WifiManager.PNO_SCAN_STATE_DISABLED_UNTIL_WIFI_TOGGLE);
3622         verify(mWifiService).setPnoScanEnabled(false, true, TEST_PACKAGE_NAME);
3623 
3624         mWifiManager.setPnoScanState(WifiManager.PNO_SCAN_STATE_DISABLED_UNTIL_REBOOT);
3625         verify(mWifiService).setPnoScanEnabled(false, false, TEST_PACKAGE_NAME);
3626 
3627         mWifiManager.setPnoScanState(WifiManager.PNO_SCAN_STATE_ENABLED);
3628         verify(mWifiService).setPnoScanEnabled(eq(true), anyBoolean(), any());
3629 
3630         assertThrows(IllegalArgumentException.class, () -> mWifiManager.setPnoScanState(999));
3631     }
3632 
3633 
3634 
3635     /**
3636      * Test behavior of isDecoratedIdentitySupported
3637      */
3638     @Test
testIsDecoratedIdentitySupported()3639     public void testIsDecoratedIdentitySupported() throws Exception {
3640         when(mWifiService.getSupportedFeatures())
3641                 .thenReturn(new Long(WIFI_FEATURE_DECORATED_IDENTITY));
3642         assertTrue(mWifiManager.isDecoratedIdentitySupported());
3643         when(mWifiService.getSupportedFeatures())
3644                 .thenReturn(new Long(~WIFI_FEATURE_DECORATED_IDENTITY));
3645         assertFalse(mWifiManager.isDecoratedIdentitySupported());
3646     }
3647 
3648     /**
3649      * Test behavior of isTrustOnFirstUseSupported.
3650      */
3651     @Test
testIsTrustOnFirstUseSupported()3652     public void testIsTrustOnFirstUseSupported() throws Exception {
3653         when(mWifiService.getSupportedFeatures())
3654                 .thenReturn(new Long(WIFI_FEATURE_TRUST_ON_FIRST_USE));
3655         assertTrue(mWifiManager.isTrustOnFirstUseSupported());
3656         when(mWifiService.getSupportedFeatures())
3657                 .thenReturn(new Long(~WIFI_FEATURE_TRUST_ON_FIRST_USE));
3658         assertFalse(mWifiManager.isTrustOnFirstUseSupported());
3659     }
3660 
3661     /**
3662      * Verify call to getAllowedChannels goes to WifiServiceImpl
3663      */
3664     @Test
testGetAllowedChannels()3665     public void testGetAllowedChannels() throws Exception {
3666         assumeTrue(SdkLevel.isAtLeastS());
3667         int band = WifiScanner.WIFI_BAND_24_5_6_GHZ;
3668         int mode = WifiAvailableChannel.OP_MODE_WIFI_AWARE
3669                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_GO
3670                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI;
3671         mWifiManager.getAllowedChannels(band, mode);
3672         verify(mWifiService).getUsableChannels(eq(band), eq(mode),
3673                 eq(WifiAvailableChannel.FILTER_REGULATORY), eq(TEST_PACKAGE_NAME), any());
3674     }
3675 
3676     /**
3677      * Verify call to getUsableChannels goes to WifiServiceImpl
3678      */
3679     @Test
testGetUsableChannels()3680     public void testGetUsableChannels() throws Exception {
3681         assumeTrue(SdkLevel.isAtLeastS());
3682         int band = WifiScanner.WIFI_BAND_BOTH_WITH_DFS;
3683         int mode = WifiAvailableChannel.OP_MODE_WIFI_AWARE
3684                 | WifiAvailableChannel.OP_MODE_WIFI_DIRECT_CLI;
3685         mWifiManager.getUsableChannels(band, mode);
3686         verify(mWifiService).getUsableChannels(eq(band), eq(mode),
3687                 eq(WifiAvailableChannel.FILTER_CONCURRENCY
3688                     | WifiAvailableChannel.FILTER_CELLULAR_COEXISTENCE),
3689                 eq(TEST_PACKAGE_NAME), any());
3690     }
3691 
3692     /**
3693      * Verify an IllegalArgumentException is thrown if callback is not provided.
3694      */
3695     @Test
testRegisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullCallback()3696     public void testRegisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullCallback() {
3697         assumeTrue(SdkLevel.isAtLeastT());
3698         try {
3699             mWifiManager.registerActiveCountryCodeChangedCallback(
3700                     new HandlerExecutor(mHandler), null);
3701             fail("expected IllegalArgumentException");
3702         } catch (IllegalArgumentException expected) {
3703         }
3704     }
3705 
3706     /**
3707      * Verify an IllegalArgumentException is thrown if executor is null.
3708      */
3709     @Test
testRegisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullExecutor()3710     public void testRegisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullExecutor() {
3711         assumeTrue(SdkLevel.isAtLeastT());
3712         try {
3713             mWifiManager.registerActiveCountryCodeChangedCallback(null,
3714                     mActiveCountryCodeChangedCallback);
3715             fail("expected IllegalArgumentException");
3716         } catch (IllegalArgumentException expected) {
3717         }
3718     }
3719 
3720     /**
3721      * Verify an IllegalArgumentException is thrown if callback is not provided.
3722      */
3723     @Test
testUnregisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullCallback()3724     public void testUnregisterActiveCountryCodeChangedCallbackThrowsExceptionOnNullCallback() {
3725         assumeTrue(SdkLevel.isAtLeastT());
3726         try {
3727             mWifiManager.unregisterActiveCountryCodeChangedCallback(null);
3728             fail("expected IllegalArgumentException");
3729         } catch (IllegalArgumentException expected) {
3730         }
3731     }
3732 
3733     /**
3734      * Verify the call to registerActiveCountryCodeChangedCallback goes to WifiServiceImpl.
3735      */
3736     @Test
testRegisterActiveCountryCodeChangedCallbackCallGoesToWifiServiceImpl()3737     public void testRegisterActiveCountryCodeChangedCallbackCallGoesToWifiServiceImpl()
3738             throws Exception {
3739         assumeTrue(SdkLevel.isAtLeastT());
3740         mWifiManager.registerActiveCountryCodeChangedCallback(new HandlerExecutor(mHandler),
3741                 mActiveCountryCodeChangedCallback);
3742         verify(mWifiService).registerDriverCountryCodeChangedListener(
3743                 any(IOnWifiDriverCountryCodeChangedListener.Stub.class), anyString(),
3744                 any() /* getAttributionTag(), nullable */);
3745     }
3746 
3747     /**
3748      * Verify the call to unregisterActiveCountryCodeChangedCallback goes to WifiServiceImpl.
3749      */
3750     @Test
testUnregisterActiveCountryCodeChangedCallbackCallGoesToWifiServiceImpl()3751     public void testUnregisterActiveCountryCodeChangedCallbackCallGoesToWifiServiceImpl()
3752             throws Exception {
3753         assumeTrue(SdkLevel.isAtLeastT());
3754         ArgumentCaptor<IOnWifiDriverCountryCodeChangedListener.Stub> listenerCaptor =
3755                 ArgumentCaptor.forClass(IOnWifiDriverCountryCodeChangedListener.Stub.class);
3756         mWifiManager.registerActiveCountryCodeChangedCallback(new HandlerExecutor(mHandler),
3757                 mActiveCountryCodeChangedCallback);
3758         verify(mWifiService).registerDriverCountryCodeChangedListener(listenerCaptor.capture(),
3759                  anyString(), any() /* getAttributionTag(), nullable */);
3760 
3761         mWifiManager.unregisterActiveCountryCodeChangedCallback(
3762                 mActiveCountryCodeChangedCallback);
3763         verify(mWifiService).unregisterDriverCountryCodeChangedListener(listenerCaptor.getValue());
3764     }
3765 
3766     /*
3767      * Verify client-provided callback is being called through callback proxy
3768      */
3769     @Test
testDriverCountryCodeChangedCallbackProxyCallsOnActiveCountryCodeChanged()3770     public void testDriverCountryCodeChangedCallbackProxyCallsOnActiveCountryCodeChanged()
3771             throws Exception {
3772         assumeTrue(SdkLevel.isAtLeastT());
3773         ArgumentCaptor<IOnWifiDriverCountryCodeChangedListener.Stub> listenerCaptor =
3774                 ArgumentCaptor.forClass(IOnWifiDriverCountryCodeChangedListener.Stub.class);
3775         mWifiManager.registerActiveCountryCodeChangedCallback(new HandlerExecutor(mHandler),
3776                 mActiveCountryCodeChangedCallback);
3777         verify(mWifiService).registerDriverCountryCodeChangedListener(listenerCaptor.capture(),
3778                  anyString(), any() /* getAttributionTag(), nullable */);
3779 
3780         listenerCaptor.getValue().onDriverCountryCodeChanged(TEST_COUNTRY_CODE);
3781         mLooper.dispatchAll();
3782         verify(mActiveCountryCodeChangedCallback).onActiveCountryCodeChanged(TEST_COUNTRY_CODE);
3783     }
3784 
3785     /*
3786      * Verify client-provided callback is being called through callback proxy
3787      */
3788     @Test
testDriverCountryCodeChangedCallbackProxyCallsOnCountryCodeInactiveWhenNull()3789     public void testDriverCountryCodeChangedCallbackProxyCallsOnCountryCodeInactiveWhenNull()
3790             throws Exception {
3791         assumeTrue(SdkLevel.isAtLeastT());
3792         ArgumentCaptor<IOnWifiDriverCountryCodeChangedListener.Stub> listenerCaptor =
3793                 ArgumentCaptor.forClass(IOnWifiDriverCountryCodeChangedListener.Stub.class);
3794         mWifiManager.registerActiveCountryCodeChangedCallback(new HandlerExecutor(mHandler),
3795                 mActiveCountryCodeChangedCallback);
3796         verify(mWifiService).registerDriverCountryCodeChangedListener(listenerCaptor.capture(),
3797                  anyString(), any() /* getAttributionTag(), nullable */);
3798 
3799         listenerCaptor.getValue().onDriverCountryCodeChanged(null);
3800         mLooper.dispatchAll();
3801         verify(mActiveCountryCodeChangedCallback).onCountryCodeInactive();
3802     }
3803 
3804     /**
3805      * Verify an IllegalArgumentException is thrown if callback is not provided.
3806      */
3807     @Test
registerLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullCallback()3808     public void registerLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullCallback() {
3809         assumeTrue(SdkLevel.isAtLeastT());
3810         try {
3811             mWifiManager.registerLocalOnlyHotspotSoftApCallback(
3812                     new HandlerExecutor(mHandler), null);
3813             fail("expected IllegalArgumentException");
3814         } catch (IllegalArgumentException expected) {
3815         }
3816     }
3817 
3818     /**
3819      * Verify an IllegalArgumentException is thrown if executor is null.
3820      */
3821     @Test
registerLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullExecutor()3822     public void registerLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullExecutor() {
3823         assumeTrue(SdkLevel.isAtLeastT());
3824         try {
3825             mWifiManager.registerLocalOnlyHotspotSoftApCallback(null, mSoftApCallback);
3826             fail("expected IllegalArgumentException");
3827         } catch (IllegalArgumentException expected) {
3828         }
3829     }
3830 
3831     /**
3832      * Verify an IllegalArgumentException is thrown if callback is not provided.
3833      */
3834     @Test
unregisterLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullCallback()3835     public void unregisterLohsSoftApCallbackThrowsIllegalArgumentExceptionOnNullCallback() {
3836         assumeTrue(SdkLevel.isAtLeastT());
3837         try {
3838             mWifiManager.unregisterLocalOnlyHotspotSoftApCallback(null);
3839             fail("expected IllegalArgumentException");
3840         } catch (IllegalArgumentException expected) {
3841         }
3842     }
3843 
3844     /**
3845      * Verify the call to registerLocalOnlyHotspotSoftApCallback goes to WifiServiceImpl.
3846      */
3847     @Test
registerLocalOnlyHotspotSoftApCallbackCallGoesToWifiServiceImpl()3848     public void registerLocalOnlyHotspotSoftApCallbackCallGoesToWifiServiceImpl()
3849             throws Exception {
3850         assumeTrue(SdkLevel.isAtLeastT());
3851         mWifiManager.registerLocalOnlyHotspotSoftApCallback(new HandlerExecutor(mHandler),
3852                 mSoftApCallback);
3853         verify(mWifiService).registerLocalOnlyHotspotSoftApCallback(
3854                 any(ISoftApCallback.Stub.class), any(Bundle.class));
3855     }
3856 
3857     /**
3858      * Verify the call to unregisterLocalOnlyHotspotSoftApCallback goes to WifiServiceImpl.
3859      */
3860     @Test
unregisterLocalOnlyHotspotSoftApCallbackCallGoesToWifiServiceImpl()3861     public void unregisterLocalOnlyHotspotSoftApCallbackCallGoesToWifiServiceImpl()
3862             throws Exception {
3863         assumeTrue(SdkLevel.isAtLeastT());
3864         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
3865                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
3866         mWifiManager.registerLocalOnlyHotspotSoftApCallback(new HandlerExecutor(mHandler),
3867                 mSoftApCallback);
3868         verify(mWifiService).registerLocalOnlyHotspotSoftApCallback(callbackCaptor.capture(),
3869                 any(Bundle.class));
3870 
3871         mWifiManager.unregisterLocalOnlyHotspotSoftApCallback(mSoftApCallback);
3872         verify(mWifiService).unregisterLocalOnlyHotspotSoftApCallback(eq(callbackCaptor.getValue()),
3873                 any(Bundle.class));
3874     }
3875 
3876     /**
3877      * Verify lohs client-provided callback is being called through callback proxy.
3878      */
3879     @Test
softApCallbackProxyCallsCallbackForLohsRegister()3880     public void softApCallbackProxyCallsCallbackForLohsRegister() throws Exception {
3881         assumeTrue(SdkLevel.isAtLeastT());
3882         WifiClient testWifiClient = new WifiClient(MacAddress.fromString("22:33:44:55:66:77"),
3883                 TEST_AP_INSTANCES[0]);
3884         SoftApCapability testSoftApCapability = new SoftApCapability(0);
3885         // Prepare test info and clients
3886         initTestInfoAndAddToTestMap(1);
3887         List<WifiClient> clientList = initWifiClientAndAddToTestMap(TEST_AP_INSTANCES[0], 1, 0);
3888 
3889         ArgumentCaptor<ISoftApCallback.Stub> callbackCaptor =
3890                 ArgumentCaptor.forClass(ISoftApCallback.Stub.class);
3891         mWifiManager.registerLocalOnlyHotspotSoftApCallback(
3892                 new HandlerExecutor(mHandler), mSoftApCallback);
3893         verify(mWifiService).registerLocalOnlyHotspotSoftApCallback(callbackCaptor.capture(),
3894                 any(Bundle.class));
3895 
3896         SoftApState state = new SoftApState(WIFI_AP_STATE_ENABLED, 0,
3897                 TEST_TETHERING_REQUEST, TEST_INTERFACE_NAME);
3898         callbackCaptor.getValue().onStateChanged(state);
3899         callbackCaptor.getValue().onConnectedClientsOrInfoChanged(
3900                 (Map<String, SoftApInfo>) mTestSoftApInfoMap.clone(),
3901                 (Map<String, List<WifiClient>>) mTestWifiClientsMap.clone(), false, true);
3902         callbackCaptor.getValue().onCapabilityChanged(testSoftApCapability);
3903         callbackCaptor.getValue().onBlockedClientConnecting(testWifiClient,
3904                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
3905 
3906         mLooper.dispatchAll();
3907         ArgumentCaptor<SoftApState> softApStateCaptor =
3908                 ArgumentCaptor.forClass(SoftApState.class);
3909         verify(mSoftApCallback).onStateChanged(softApStateCaptor.capture());
3910         assertEquals(state, softApStateCaptor.getValue());
3911 
3912         verify(mSoftApCallback).onConnectedClientsChanged(clientList);
3913         verify(mSoftApCallback).onConnectedClientsChanged(mTestApInfo1, clientList);
3914         verify(mSoftApCallback).onInfoChanged(mTestApInfo1);
3915         verify(mSoftApCallback).onInfoChanged(Mockito.argThat((List<SoftApInfo> infos) ->
3916                         infos.contains(mTestApInfo1)));
3917 
3918         verify(mSoftApCallback).onCapabilityChanged(testSoftApCapability);
3919 
3920         verify(mSoftApCallback).onBlockedClientConnecting(testWifiClient,
3921                 WifiManager.SAP_CLIENT_BLOCK_REASON_CODE_NO_MORE_STAS);
3922     }
3923 
3924     /*
3925      * Verify call to {@link WifiManager#isStaConcurrencyForMultiInternetSupported}.
3926      */
3927     @Test
testIsStaConcurrencyForMultiInternetSupported()3928     public void testIsStaConcurrencyForMultiInternetSupported() throws Exception {
3929         when(mWifiService.getSupportedFeatures())
3930                 .thenReturn(new Long(WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
3931         assertTrue(mWifiManager.isStaConcurrencyForMultiInternetSupported());
3932         when(mWifiService.getSupportedFeatures())
3933                 .thenReturn(new Long(~WIFI_FEATURE_ADDITIONAL_STA_MULTI_INTERNET));
3934         assertFalse(mWifiManager.isStaConcurrencyForMultiInternetSupported());
3935     }
3936 
3937     /*
3938      * Verify call to {@link WifiManager#getStaConcurrencyForMultiInternetMode()}.
3939      */
3940     @Test
testGetStaConcurrencyForMultiInternetMode()3941     public void testGetStaConcurrencyForMultiInternetMode() throws Exception {
3942         final int mode = mWifiManager.getStaConcurrencyForMultiInternetMode();
3943         verify(mWifiService).getStaConcurrencyForMultiInternetMode();
3944         assertEquals(WifiManager.WIFI_MULTI_INTERNET_MODE_DISABLED, mode);
3945     }
3946 
3947     /*
3948      * Verify call to {@link WifiManager#setStaConcurrencyForMultiInternetMode()}.
3949      */
3950     @Test
testSetStaConcurrencyForMultiInternetMode()3951     public void testSetStaConcurrencyForMultiInternetMode() throws Exception {
3952         mWifiManager.setStaConcurrencyForMultiInternetMode(
3953                 WifiManager.WIFI_MULTI_INTERNET_MODE_DBS_AP);
3954         verify(mWifiService).setStaConcurrencyForMultiInternetMode(
3955                 WifiManager.WIFI_MULTI_INTERNET_MODE_DBS_AP);
3956     }
3957 
3958     /*
3959      * Verify call to {@link WifiManager#isDualBandSimultaneousSupported}.
3960      */
3961     @Test
testIsDualBandSimultaneousSupported()3962     public void testIsDualBandSimultaneousSupported() throws Exception {
3963         when(mWifiService.getSupportedFeatures())
3964                 .thenReturn(new Long(WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS));
3965         assertTrue(mWifiManager.isDualBandSimultaneousSupported());
3966         when(mWifiService.getSupportedFeatures())
3967                 .thenReturn(new Long(~WIFI_FEATURE_DUAL_BAND_SIMULTANEOUS));
3968         assertFalse(mWifiManager.isDualBandSimultaneousSupported());
3969     }
3970     /*
3971      * Verify call to {@link WifiManager#isTidToLinkMappingSupported()}
3972      */
3973     @Test
testIsTidToLinkMappingSupported()3974     public void testIsTidToLinkMappingSupported() throws Exception {
3975         when(mWifiService.getSupportedFeatures()).thenReturn(WIFI_FEATURE_T2LM_NEGOTIATION);
3976         assertTrue(mWifiManager.isTidToLinkMappingNegotiationSupported());
3977         when(mWifiService.getSupportedFeatures()).thenReturn(~WIFI_FEATURE_T2LM_NEGOTIATION);
3978         assertFalse(mWifiManager.isTidToLinkMappingNegotiationSupported());
3979     }
3980 
3981     /**
3982      * Verify call to
3983      * {@link WifiManager#reportCreateInterfaceImpact(int, boolean, Executor, BiConsumer)}.
3984      */
3985     @Test
testIsItPossibleToCreateInterface()3986     public void testIsItPossibleToCreateInterface() throws Exception {
3987         assumeTrue(SdkLevel.isAtLeastT());
3988 
3989         final int interfaceToCreate = WifiManager.WIFI_INTERFACE_TYPE_DIRECT;
3990         final boolean requireNewInterface = false;
3991         final boolean canCreate = true;
3992         final String packageName1 = "TestPackage1";
3993         final String packageName2 = "TestPackage2";
3994         final int[] interfaces =
3995                 {WifiManager.WIFI_INTERFACE_TYPE_AP, WifiManager.WIFI_INTERFACE_TYPE_AWARE};
3996         final String[] packagesForInterfaces =
3997                 {TEST_PACKAGE_NAME, packageName1 + "," + packageName2};
3998         final Set<WifiManager.InterfaceCreationImpact> interfacePairs = Set.of(
3999                 new WifiManager.InterfaceCreationImpact(interfaces[0],
4000                         new ArraySet<>(new String[]{TEST_PACKAGE_NAME})),
4001                 new WifiManager.InterfaceCreationImpact(interfaces[1],
4002                         new ArraySet<>(new String[]{packageName1, packageName2})));
4003         when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
4004         BiConsumer<Boolean, Set<WifiManager.InterfaceCreationImpact>> resultCallback = mock(
4005                 BiConsumer.class);
4006         ArgumentCaptor<IInterfaceCreationInfoCallback.Stub> cbCaptor = ArgumentCaptor.forClass(
4007                 IInterfaceCreationInfoCallback.Stub.class);
4008         ArgumentCaptor<Set<WifiManager.InterfaceCreationImpact>> resultCaptor =
4009                 ArgumentCaptor.forClass(Set.class);
4010 
4011         mWifiManager.reportCreateInterfaceImpact(interfaceToCreate, requireNewInterface,
4012                 new SynchronousExecutor(), resultCallback);
4013         verify(mWifiService).reportCreateInterfaceImpact(eq(TEST_PACKAGE_NAME),
4014                 eq(interfaceToCreate), eq(requireNewInterface), cbCaptor.capture());
4015         cbCaptor.getValue().onResults(canCreate, interfaces, packagesForInterfaces);
4016         verify(resultCallback).accept(eq(canCreate), resultCaptor.capture());
4017         assertEquals(interfacePairs, resultCaptor.getValue());
4018     }
4019 
4020     /**
4021      * Verify call to getChannelData goes to WifiServiceImpl
4022      */
4023     @Test
testChannelData()4024     public void testChannelData() throws Exception {
4025         assumeTrue(SdkLevel.isAtLeastT());
4026         Consumer<List<Bundle>> resultsCallback = mock(Consumer.class);
4027         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4028         mWifiManager.getChannelData(executor, resultsCallback);
4029         verify(mWifiService).getChannelData(any(IListListener.Stub.class), eq(TEST_PACKAGE_NAME),
4030                 any(Bundle.class));
4031     }
4032 
4033     /**
4034      * Verify call to {@link WifiManager#addQosPolicies(List, Executor, Consumer)}.
4035      */
4036     @Test
testAddQosPolicies()4037     public void testAddQosPolicies() throws Exception {
4038         assumeTrue(SdkLevel.isAtLeastU());
4039 
4040         final int policyId = 2;
4041         final int direction = QosPolicyParams.DIRECTION_DOWNLINK;
4042         final int userPriority = QosPolicyParams.USER_PRIORITY_VIDEO_LOW;
4043         final int ipVersion = QosPolicyParams.IP_VERSION_4;
4044         QosPolicyParams policyParams = new QosPolicyParams.Builder(policyId, direction)
4045                 .setUserPriority(userPriority)
4046                 .setIpVersion(ipVersion)
4047                 .build();
4048         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4049         Consumer<List<Integer>> resultsCallback = mock(Consumer.class);
4050 
4051         mWifiManager.addQosPolicies(Arrays.asList(policyParams), executor, resultsCallback);
4052         verify(mWifiService).addQosPolicies(any(), any(), eq(TEST_PACKAGE_NAME),
4053                 any(IListListener.Stub.class));
4054     }
4055 
4056     /**
4057      * Verify call to {@link WifiManager#removeQosPolicies(int[])}
4058      */
4059     @Test
testRemoveQosPolicies()4060     public void testRemoveQosPolicies() throws Exception {
4061         assumeTrue(SdkLevel.isAtLeastU());
4062         final int[] policyIdList = new int[]{127, 128};
4063         mWifiManager.removeQosPolicies(policyIdList);
4064         verify(mWifiService).removeQosPolicies(any(), eq(TEST_PACKAGE_NAME));
4065     }
4066 
4067     @Test
testAddRemoveLocaOnlyConnectionListener()4068     public void testAddRemoveLocaOnlyConnectionListener() throws RemoteException {
4069         assertThrows(IllegalArgumentException.class, () -> mWifiManager
4070                 .addLocalOnlyConnectionFailureListener(null, mLocalOnlyConnectionFailureListener));
4071         assertThrows(IllegalArgumentException.class, () -> mWifiManager
4072                 .addLocalOnlyConnectionFailureListener(mExecutor, null));
4073         mWifiManager.addLocalOnlyConnectionFailureListener(mExecutor,
4074                 mLocalOnlyConnectionFailureListener);
4075         verify(mWifiService).addLocalOnlyConnectionStatusListener(any(), eq(TEST_PACKAGE_NAME),
4076                 nullable(String.class));
4077         mWifiManager.removeLocalOnlyConnectionFailureListener(mLocalOnlyConnectionFailureListener);
4078         verify(mWifiService).removeLocalOnlyConnectionStatusListener(any(), eq(TEST_PACKAGE_NAME));
4079     }
4080 
4081     /**
4082      * Verify if the call for set / get link layer stats polling interval goes to WifiServiceImpl
4083      */
4084     @Test
testSetAndGetLinkLayerStatsPollingInterval()4085     public void testSetAndGetLinkLayerStatsPollingInterval() throws Exception {
4086         assumeTrue(SdkLevel.isAtLeastT());
4087         mWifiManager.setLinkLayerStatsPollingInterval(TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS);
4088         verify(mWifiService).setLinkLayerStatsPollingInterval(
4089                 eq(TEST_LINK_LAYER_STATS_POLLING_INTERVAL_MS));
4090 
4091         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4092         Consumer<Integer> resultsCallback = mock(Consumer.class);
4093         mWifiManager.getLinkLayerStatsPollingInterval(executor, resultsCallback);
4094         verify(mWifiService).getLinkLayerStatsPollingInterval(any(IIntegerListener.class));
4095 
4096         // null executor
4097         assertThrows(NullPointerException.class,
4098                 () -> mWifiManager.getLinkLayerStatsPollingInterval(null, resultsCallback));
4099         // null resultsCallback
4100         assertThrows(NullPointerException.class,
4101                 () -> mWifiManager.getLinkLayerStatsPollingInterval(executor, null));
4102     }
4103 
4104     /**
4105      * Verify {@link WifiManager#setMloMode(int)} and {@link WifiManager#getMloMode()}.
4106      */
4107     @Test
testMloMode()4108     public void testMloMode() throws RemoteException {
4109         Consumer<Boolean> resultsSetCallback = mock(Consumer.class);
4110         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4111         // Out of range values.
4112         assertThrows(IllegalArgumentException.class,
4113                 () -> mWifiManager.setMloMode(-1, executor, resultsSetCallback));
4114         assertThrows(IllegalArgumentException.class,
4115                 () -> mWifiManager.setMloMode(1000, executor, resultsSetCallback));
4116         // Null executor/callback exception.
4117         assertThrows("null executor should trigger exception", NullPointerException.class,
4118                 () -> mWifiManager.setMloMode(WifiManager.MLO_MODE_DEFAULT, null,
4119                         resultsSetCallback));
4120         assertThrows("null listener should trigger exception", NullPointerException.class,
4121                 () -> mWifiManager.setMloMode(WifiManager.MLO_MODE_DEFAULT, executor, null));
4122         // Set and verify.
4123         mWifiManager.setMloMode(WifiManager.MLO_MODE_LOW_POWER, executor, resultsSetCallback);
4124         verify(mWifiService).setMloMode(eq(WifiManager.MLO_MODE_LOW_POWER),
4125                 any(IBooleanListener.Stub.class));
4126         // Get and verify.
4127         Consumer<Integer> resultsGetCallback = mock(Consumer.class);
4128         mWifiManager.getMloMode(executor, resultsGetCallback);
4129         verify(mWifiService).getMloMode(any(IIntegerListener.Stub.class));
4130     }
4131 
4132     @Test
testVerboseLogging()4133     public void testVerboseLogging() throws RemoteException {
4134         mWifiManager.setVerboseLoggingEnabled(true);
4135         verify(mWifiService).enableVerboseLogging(VERBOSE_LOGGING_LEVEL_ENABLED);
4136         mWifiManager.setVerboseLoggingEnabled(false);
4137         verify(mWifiService).enableVerboseLogging(VERBOSE_LOGGING_LEVEL_DISABLED);
4138         when(mWifiService.getVerboseLoggingLevel()).thenReturn(VERBOSE_LOGGING_LEVEL_ENABLED);
4139         assertTrue(mWifiManager.isVerboseLoggingEnabled());
4140         when(mWifiService.getVerboseLoggingLevel())
4141                 .thenReturn(VERBOSE_LOGGING_LEVEL_ENABLED_SHOW_KEY);
4142         assertTrue(mWifiManager.isVerboseLoggingEnabled());
4143         when(mWifiService.getVerboseLoggingLevel())
4144                 .thenReturn(VERBOSE_LOGGING_LEVEL_WIFI_AWARE_ENABLED_ONLY);
4145         assertFalse(mWifiManager.isVerboseLoggingEnabled());
4146         when(mWifiService.getVerboseLoggingLevel()).thenReturn(VERBOSE_LOGGING_LEVEL_DISABLED);
4147         assertFalse(mWifiManager.isVerboseLoggingEnabled());
4148     }
4149 
4150     /**
4151      * Test behavior of isWepSupported
4152      */
4153     @Test
testIsWepSupported()4154     public void testIsWepSupported() throws Exception {
4155         when(mWifiService.getSupportedFeatures())
4156                 .thenReturn(new Long(WIFI_FEATURE_WEP));
4157         assertTrue(mWifiManager.isWepSupported());
4158         when(mWifiService.getSupportedFeatures())
4159                 .thenReturn(new Long(~WIFI_FEATURE_WEP));
4160         assertFalse(mWifiManager.isWepSupported());
4161     }
4162 
4163     /**
4164      * Test behavior of isWpaPersonalSupported
4165      */
4166     @Test
testIsWpaPersonalSupported()4167     public void testIsWpaPersonalSupported() throws Exception {
4168         when(mWifiService.getSupportedFeatures())
4169                 .thenReturn(new Long(WIFI_FEATURE_WPA_PERSONAL));
4170         assertTrue(mWifiManager.isWpaPersonalSupported());
4171         when(mWifiService.getSupportedFeatures())
4172                 .thenReturn(new Long(~WIFI_FEATURE_WPA_PERSONAL));
4173         assertFalse(mWifiManager.isWpaPersonalSupported());
4174     }
4175 
4176     @Test
testSetWepAllowed()4177     public void testSetWepAllowed() throws Exception {
4178         mWifiManager.setWepAllowed(true);
4179         verify(mWifiService).setWepAllowed(true);
4180         mWifiManager.setWepAllowed(false);
4181         verify(mWifiService).setWepAllowed(false);
4182     }
4183 
4184     @Test
testQueryWepAllowed()4185     public void testQueryWepAllowed() throws Exception {
4186         Consumer<Boolean> resultsSetCallback = mock(Consumer.class);
4187         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4188         // Null executor/callback exception.
4189         assertThrows("null executor should trigger exception", NullPointerException.class,
4190                 () -> mWifiManager.queryWepAllowed(null, resultsSetCallback));
4191         assertThrows("null listener should trigger exception", NullPointerException.class,
4192                 () -> mWifiManager.queryWepAllowed(executor, null));
4193         // Set and verify.
4194         mWifiManager.queryWepAllowed(executor, resultsSetCallback);
4195         verify(mWifiService).queryWepAllowed(
4196                 any(IBooleanListener.Stub.class));
4197     }
4198 
4199     /**
4200      * Verify {@link WifiManager#setPerSsidRoamingMode(WifiSsid, int)}.
4201      */
4202     @Test
testSetPerSsidRoamingMode()4203     public void testSetPerSsidRoamingMode() throws RemoteException {
4204         assumeTrue(SdkLevel.isAtLeastV());
4205         // Invalid input throws exception.
4206         assertThrows(IllegalArgumentException.class,
4207                 () -> mWifiManager.setPerSsidRoamingMode(WifiSsid.fromString(TEST_SSID), -1));
4208         assertThrows(IllegalArgumentException.class,
4209                 () -> mWifiManager.setPerSsidRoamingMode(WifiSsid.fromString(TEST_SSID), 3));
4210         assertThrows(NullPointerException.class,
4211                 () -> mWifiManager.setPerSsidRoamingMode(null, WifiManager.ROAMING_MODE_NORMAL));
4212         // Set and verify.
4213         mWifiManager.setPerSsidRoamingMode(WifiSsid.fromString(TEST_SSID),
4214                 WifiManager.ROAMING_MODE_NORMAL);
4215         verify(mWifiService).setPerSsidRoamingMode(WifiSsid.fromString(TEST_SSID),
4216                 WifiManager.ROAMING_MODE_NORMAL, TEST_PACKAGE_NAME);
4217     }
4218 
4219     /**
4220      * Verify {@link WifiManager#removePerSsidRoamingMode(WifiSsid)}.
4221      */
4222     @Test
testRemovePerSsidRoamingMode()4223     public void testRemovePerSsidRoamingMode() throws RemoteException {
4224         assumeTrue(SdkLevel.isAtLeastV());
4225         // Invalid input throws exception.
4226         assertThrows(NullPointerException.class,
4227                 () -> mWifiManager.removePerSsidRoamingMode(null));
4228         // Remove and verify.
4229         mWifiManager.removePerSsidRoamingMode(WifiSsid.fromString(TEST_SSID));
4230         verify(mWifiService).removePerSsidRoamingMode(WifiSsid.fromString(TEST_SSID),
4231                 TEST_PACKAGE_NAME);
4232     }
4233 
4234     /**
4235      * Verify {@link WifiManager#getPerSsidRoamingModes()}.
4236      */
4237     @Test
testGetPerSsidRoamingModes()4238     public void testGetPerSsidRoamingModes() throws RemoteException {
4239         assumeTrue(SdkLevel.isAtLeastV());
4240         Consumer<Map<String, Integer>> resultsSetCallback = mock(Consumer.class);
4241         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4242         // Null executor/callback exception.
4243         assertThrows("null executor should trigger exception", NullPointerException.class,
4244                 () -> mWifiManager.getPerSsidRoamingModes(null,
4245                         resultsSetCallback));
4246         assertThrows("null executor should trigger exception", NullPointerException.class,
4247                 () -> mWifiManager.getPerSsidRoamingModes(executor,
4248                         null));
4249         // Get and verify.
4250         mWifiManager.getPerSsidRoamingModes(executor, resultsSetCallback);
4251         verify(mWifiService).getPerSsidRoamingModes(eq(TEST_PACKAGE_NAME),
4252                 any(IMapListener.Stub.class));
4253     }
4254 
4255     @Test
testGetTwtCapabilities()4256     public void testGetTwtCapabilities() throws Exception {
4257         assumeTrue(SdkLevel.isAtLeastV());
4258         Consumer<Bundle> resultCallback = mock(Consumer.class);
4259         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4260         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
4261         // Null check
4262         assertThrows("null executor should trigger exception", NullPointerException.class,
4263                 () -> mWifiManager.getTwtCapabilities(executor, null));
4264         assertThrows("null executor should trigger exception", NullPointerException.class,
4265                 () -> mWifiManager.getTwtCapabilities(null, resultCallback));
4266         // Get and verify
4267         mWifiManager.getTwtCapabilities(executor, resultCallback);
4268         verify(mWifiService).getTwtCapabilities(any(ITwtCapabilitiesListener.Stub.class),
4269                 bundleCaptor.capture());
4270         verify(mContext.getAttributionSource()).equals(
4271                 bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
4272     }
4273 
4274     @Test
testSetupTwtSession()4275     public void testSetupTwtSession() throws Exception {
4276         assumeTrue(SdkLevel.isAtLeastV());
4277         TwtSessionCallback resultCallback = mock(TwtSessionCallback.class);
4278         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4279         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
4280         TwtRequest twtRequest = mock(TwtRequest.class);
4281         // Null check
4282         assertThrows("null executor should trigger exception", NullPointerException.class,
4283                 () -> mWifiManager.setupTwtSession(null, executor, resultCallback));
4284         assertThrows("null executor should trigger exception", NullPointerException.class,
4285                 () -> mWifiManager.setupTwtSession(twtRequest, null, resultCallback));
4286         assertThrows("null executor should trigger exception", NullPointerException.class,
4287                 () -> mWifiManager.setupTwtSession(twtRequest, executor, null));
4288         // Call twtSessionSetup and verify
4289         mWifiManager.setupTwtSession(twtRequest, executor, resultCallback);
4290         verify(mWifiService).setupTwtSession(any(TwtRequest.class), any(ITwtCallback.class),
4291                 bundleCaptor.capture());
4292         verify(mContext.getAttributionSource()).equals(
4293                 bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
4294     }
4295 
4296     @Test
testGetStatsTwtSession()4297     public void testGetStatsTwtSession() throws Exception {
4298         assumeTrue(SdkLevel.isAtLeastV());
4299         Consumer<Bundle> resultCallback = mock(Consumer.class);
4300         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4301         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
4302         // Null check
4303         assertThrows("null executor should trigger exception", NullPointerException.class,
4304                 () -> mWifiManager.getStatsTwtSession(0, null, resultCallback));
4305         assertThrows("null executor should trigger exception", NullPointerException.class,
4306                 () -> mWifiManager.getStatsTwtSession(0, executor, null));
4307         // Call twtSessionGetStats and verify
4308         mWifiManager.getStatsTwtSession(2, executor, resultCallback);
4309         verify(mWifiService).getStatsTwtSession(eq(2), any(ITwtStatsListener.class),
4310                 bundleCaptor.capture());
4311         verify(mContext.getAttributionSource()).equals(
4312                 bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
4313     }
4314 
4315     @Test
testTeardownTwtSession()4316     public void testTeardownTwtSession() throws Exception {
4317         assumeTrue(SdkLevel.isAtLeastV());
4318         ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
4319         // Call twtSessionTeardown and verify
4320         mWifiManager.teardownTwtSession(10);
4321         verify(mWifiService).teardownTwtSession(eq(10), bundleCaptor.capture());
4322         verify(mContext.getAttributionSource()).equals(
4323                 bundleCaptor.getValue().getParcelable(EXTRA_PARAM_KEY_ATTRIBUTION_SOURCE));
4324     }
4325 
4326     /**
4327      * Test behavior of isD2dSupportedWhenInfraStaDisabled.
4328      */
4329     @Test
testIsD2dSupportedWhenInfraStaDisabled()4330     public void testIsD2dSupportedWhenInfraStaDisabled() throws Exception {
4331         when(mWifiService.getSupportedFeatures())
4332                 .thenReturn(new Long(WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED));
4333         assertTrue(mWifiManager.isD2dSupportedWhenInfraStaDisabled());
4334         when(mWifiService.getSupportedFeatures())
4335                 .thenReturn(new Long(~WIFI_FEATURE_D2D_WHEN_INFRA_STA_DISABLED));
4336         assertFalse(mWifiManager.isD2dSupportedWhenInfraStaDisabled());
4337     }
4338 
4339     @Test
testSetD2dAllowedInfraStaDisabled()4340     public void testSetD2dAllowedInfraStaDisabled() throws Exception {
4341         mWifiManager.setD2dAllowedWhenInfraStaDisabled(true);
4342         verify(mWifiService).setD2dAllowedWhenInfraStaDisabled(true);
4343         mWifiManager.setD2dAllowedWhenInfraStaDisabled(false);
4344         verify(mWifiService).setD2dAllowedWhenInfraStaDisabled(false);
4345     }
4346 
4347     @Test
testQueryD2dAllowedInfraStaDisabled()4348     public void testQueryD2dAllowedInfraStaDisabled() throws Exception {
4349         Consumer<Boolean> resultsSetCallback = mock(Consumer.class);
4350         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4351         // Null executor/callback exception.
4352         assertThrows("null executor should trigger exception", NullPointerException.class,
4353                 () -> mWifiManager.queryD2dAllowedWhenInfraStaDisabled(null, resultsSetCallback));
4354         assertThrows("null listener should trigger exception", NullPointerException.class,
4355                 () -> mWifiManager.queryD2dAllowedWhenInfraStaDisabled(executor, null));
4356         // Set and verify.
4357         mWifiManager.queryD2dAllowedWhenInfraStaDisabled(executor, resultsSetCallback);
4358         verify(mWifiService).queryD2dAllowedWhenInfraStaDisabled(
4359                 any(IBooleanListener.Stub.class));
4360     }
4361 
4362     @Test
testRetrieveRestoreWifiBackupData()4363     public void testRetrieveRestoreWifiBackupData() throws Exception {
4364         assumeTrue(SdkLevel.isAtLeastV());
4365         Consumer<byte[]> resultsSetCallback = mock(Consumer.class);
4366         SynchronousExecutor executor = mock(SynchronousExecutor.class);
4367         byte[] testByteArray = new byte[0];
4368         // Null executor/callback exception.
4369         assertThrows("null executor should trigger exception", NullPointerException.class,
4370                 () -> mWifiManager.retrieveWifiBackupData(null, resultsSetCallback));
4371         assertThrows("null listener should trigger exception", NullPointerException.class,
4372                 () -> mWifiManager.retrieveWifiBackupData(executor, null));
4373         // Call and verify.
4374         mWifiManager.retrieveWifiBackupData(executor, resultsSetCallback);
4375         verify(mWifiService).retrieveWifiBackupData(
4376                 any(IByteArrayListener.Stub.class));
4377         mWifiManager.restoreWifiBackupData(testByteArray);
4378         verify(mWifiService).restoreWifiBackupData(eq(testByteArray));
4379     }
4380 
4381 
4382     @Test
testIsPreferredNetworkOffloadSupported()4383     public void testIsPreferredNetworkOffloadSupported() throws Exception {
4384         mWifiManager.isPreferredNetworkOffloadSupported();
4385         verify(mWifiService).isPnoSupported();
4386     }
4387 }
4388