• 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 com.android.server.wifi;
18 
19 import static org.junit.Assert.assertArrayEquals;
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertNotNull;
23 import static org.junit.Assert.assertNull;
24 import static org.junit.Assert.assertTrue;
25 import static org.mockito.ArgumentMatchers.anyInt;
26 import static org.mockito.ArgumentMatchers.eq;
27 import static org.mockito.Matchers.argThat;
28 import static org.mockito.Mockito.any;
29 import static org.mockito.Mockito.anyLong;
30 import static org.mockito.Mockito.anyString;
31 import static org.mockito.Mockito.doNothing;
32 import static org.mockito.Mockito.doThrow;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.reset;
36 import static org.mockito.Mockito.times;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.verifyNoMoreInteractions;
39 import static org.mockito.Mockito.when;
40 
41 import android.app.AlarmManager;
42 import android.net.wifi.IApInterface;
43 import android.net.wifi.IApInterfaceEventCallback;
44 import android.net.wifi.IClientInterface;
45 import android.net.wifi.IPnoScanEvent;
46 import android.net.wifi.IScanEvent;
47 import android.net.wifi.ISendMgmtFrameEvent;
48 import android.net.wifi.IWifiScannerImpl;
49 import android.net.wifi.IWificond;
50 import android.net.wifi.ScanResult;
51 import android.net.wifi.WifiConfiguration;
52 import android.net.wifi.WifiEnterpriseConfig;
53 import android.net.wifi.WifiScanner;
54 import android.os.Handler;
55 import android.os.IBinder;
56 import android.os.RemoteException;
57 import android.os.test.TestLooper;
58 
59 import androidx.test.filters.SmallTest;
60 
61 import com.android.server.wifi.WifiNative.SendMgmtFrameCallback;
62 import com.android.server.wifi.util.NativeUtil;
63 import com.android.server.wifi.wificond.ChannelSettings;
64 import com.android.server.wifi.wificond.HiddenNetwork;
65 import com.android.server.wifi.wificond.NativeScanResult;
66 import com.android.server.wifi.wificond.PnoSettings;
67 import com.android.server.wifi.wificond.RadioChainInfo;
68 import com.android.server.wifi.wificond.SingleScanSettings;
69 
70 import org.junit.Before;
71 import org.junit.Test;
72 import org.mockito.AdditionalMatchers;
73 import org.mockito.ArgumentCaptor;
74 import org.mockito.ArgumentMatcher;
75 import org.mockito.Mock;
76 import org.mockito.MockitoAnnotations;
77 
78 import java.io.ByteArrayOutputStream;
79 import java.nio.charset.StandardCharsets;
80 import java.util.ArrayList;
81 import java.util.Arrays;
82 import java.util.BitSet;
83 import java.util.HashSet;
84 import java.util.List;
85 import java.util.Set;
86 
87 /**
88  * Unit tests for {@link com.android.server.wifi.WificondControl}.
89  */
90 @SmallTest
91 public class WificondControlTest {
92     @Mock private WifiInjector mWifiInjector;
93     @Mock private WifiMonitor mWifiMonitor;
94     @Mock private WifiMetrics mWifiMetrics;
95     @Mock private IWificond mWificond;
96     @Mock private IBinder mWifiCondBinder;
97     @Mock private IClientInterface mClientInterface;
98     @Mock private IWifiScannerImpl mWifiScannerImpl;
99     @Mock private CarrierNetworkConfig mCarrierNetworkConfig;
100     @Mock private IApInterface mApInterface;
101     @Mock private WifiNative.SoftApListener mSoftApListener;
102     @Mock private AlarmManager mAlarmManager;
103     @Mock private Clock mClock;
104     @Mock private SendMgmtFrameCallback mSendMgmtFrameCallback;
105     private TestLooper mLooper;
106     private WificondControl mWificondControl;
107     private static final String TEST_INTERFACE_NAME = "test_wlan_if";
108     private static final String TEST_INTERFACE_NAME1 = "test_wlan_if1";
109     private static final String TEST_INVALID_INTERFACE_NAME = "asdf";
110     private static final byte[] TEST_SSID =
111             new byte[] {'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
112     private static final byte[] TEST_PSK =
113             new byte[] {'T', 'e', 's', 't'};
114     private static final byte[] TEST_BSSID =
115             new byte[] {(byte) 0x12, (byte) 0xef, (byte) 0xa1,
116                         (byte) 0x2c, (byte) 0x97, (byte) 0x8b};
117     // This the IE buffer which is consistent with TEST_SSID.
118     private static final byte[] TEST_INFO_ELEMENT_SSID =
119             new byte[] {
120                     // Element ID for SSID.
121                     (byte) 0x00,
122                     // Length of the SSID: 0x0b or 11.
123                     (byte) 0x0b,
124                     // This is string "GoogleGuest"
125                     'G', 'o', 'o', 'g', 'l', 'e', 'G', 'u', 'e', 's', 't'};
126     // RSN IE data indicating EAP key management.
127     private static final byte[] TEST_INFO_ELEMENT_RSN =
128             new byte[] {
129                     // Element ID for RSN.
130                     (byte) 0x30,
131                     // Length of the element data.
132                     (byte) 0x18,
133                     (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02,
134                     (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x04,
135                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x02, (byte) 0x01, (byte) 0x00,
136                     (byte) 0x00, (byte) 0x0F, (byte) 0xAC, (byte) 0x01, (byte) 0x00, (byte) 0x00 };
137 
138     private static final int TEST_FREQUENCY = 2456;
139     private static final int TEST_SIGNAL_MBM = -4500;
140     private static final long TEST_TSF = 34455441;
141     private static final BitSet TEST_CAPABILITY = new BitSet(16) {{ set(2); set(5); }};
142     private static final boolean TEST_ASSOCIATED = true;
143     private static final NativeScanResult MOCK_NATIVE_SCAN_RESULT =
144             new NativeScanResult() {{
145                 ssid = TEST_SSID;
146                 bssid = TEST_BSSID;
147                 infoElement = TEST_INFO_ELEMENT_SSID;
148                 frequency = TEST_FREQUENCY;
149                 signalMbm = TEST_SIGNAL_MBM;
150                 capability = TEST_CAPABILITY;
151                 associated = TEST_ASSOCIATED;
152                 radioChainInfos = new ArrayList<>();
153             }};
154     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_1 =
155             new RadioChainInfo() {{
156                 chainId = 1;
157                 level = -89;
158             }};
159     private static final RadioChainInfo MOCK_NATIVE_RADIO_CHAIN_INFO_2 =
160             new RadioChainInfo() {{
161                 chainId = 0;
162                 level = -78;
163             }};
164     private static final Set<Integer> SCAN_FREQ_SET =
165             new HashSet<Integer>() {{
166                 add(2410);
167                 add(2450);
168                 add(5050);
169                 add(5200);
170             }};
171     private static final String TEST_QUOTED_SSID_1 = "\"testSsid1\"";
172     private static final String TEST_QUOTED_SSID_2 = "\"testSsid2\"";
173     private static final int[] TEST_FREQUENCIES_1 = {};
174     private static final int[] TEST_FREQUENCIES_2 = {2500, 5124};
175 
176     private static final List<String> SCAN_HIDDEN_NETWORK_SSID_LIST =
177             new ArrayList<String>() {{
178                 add(TEST_QUOTED_SSID_1);
179                 add(TEST_QUOTED_SSID_2);
180             }};
181 
182 
183     private static final WifiNative.PnoSettings TEST_PNO_SETTINGS =
184             new WifiNative.PnoSettings() {{
185                 isConnected = false;
186                 periodInMs = 6000;
187                 networkList = new WifiNative.PnoNetwork[2];
188                 networkList[0] = new WifiNative.PnoNetwork();
189                 networkList[1] = new WifiNative.PnoNetwork();
190                 networkList[0].ssid = TEST_QUOTED_SSID_1;
191                 networkList[0].flags = WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN;
192                 networkList[0].frequencies = TEST_FREQUENCIES_1;
193                 networkList[1].ssid = TEST_QUOTED_SSID_2;
194                 networkList[1].flags = 0;
195                 networkList[1].frequencies = TEST_FREQUENCIES_2;
196             }};
197 
198     private static final int TEST_MCS_RATE = 5;
199     private static final int TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS = 100;
200     private static final byte[] TEST_PROBE_FRAME = {
201             0x40, 0x00, 0x3c, 0x00, (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b,
202             0x33, 0x72, (byte) 0xf4, (byte) 0xf5, (byte) 0xe8, 0x51, (byte) 0x9e, 0x09,
203             (byte) 0xa8, (byte) 0xbd, 0x27, 0x5b, 0x33, 0x72, (byte) 0xb0, 0x66,
204             0x00, 0x00
205     };
206 
207     @Before
setUp()208     public void setUp() throws Exception {
209         // Setup mocks for successful WificondControl operation. Failure case mocks should be
210         // created in specific tests
211         MockitoAnnotations.initMocks(this);
212         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
213         when(mWificond.asBinder()).thenReturn(mWifiCondBinder);
214         when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl);
215         when(mWificond.createClientInterface(any())).thenReturn(mClientInterface);
216         when(mWificond.createApInterface(any())).thenReturn(mApInterface);
217         when(mWificond.tearDownClientInterface(any())).thenReturn(true);
218         when(mWificond.tearDownApInterface(any())).thenReturn(true);
219         when(mClientInterface.getWifiScannerImpl()).thenReturn(mWifiScannerImpl);
220         when(mClientInterface.getInterfaceName()).thenReturn(TEST_INTERFACE_NAME);
221         when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
222         mLooper = new TestLooper();
223         mWificondControl = new WificondControl(mWifiInjector, mWifiMonitor, mCarrierNetworkConfig,
224                 mAlarmManager, mLooper.getLooper(), mClock);
225         assertEquals(mClientInterface, mWificondControl.setupInterfaceForClientMode(
226                 TEST_INTERFACE_NAME));
227         verify(mWifiInjector).makeWificond();
228         verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
229     }
230 
231     /**
232      * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) calls Wificond.
233      */
234     @Test
testSetupInterfaceForClientMode()235     public void testSetupInterfaceForClientMode() throws Exception {
236         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
237         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
238         verify(mWificond).createClientInterface(TEST_INTERFACE_NAME);
239     }
240 
241     /**
242      * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) calls subscribeScanEvents().
243      */
244     @Test
testSetupInterfaceForClientModeCallsScanEventSubscripiton()245     public void testSetupInterfaceForClientModeCallsScanEventSubscripiton() throws Exception {
246         verify(mWifiScannerImpl).subscribeScanEvents(any(IScanEvent.class));
247     }
248 
249     /**
250      * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) returns null when wificond is
251      * not started.
252      */
253     @Test
testSetupInterfaceForClientModeErrorWhenWificondIsNotStarted()254     public void testSetupInterfaceForClientModeErrorWhenWificondIsNotStarted() throws Exception {
255         // Invoke wificond death handler to clear the handle.
256         mWificondControl.binderDied();
257         mLooper.dispatchAll();
258         when(mWifiInjector.makeWificond()).thenReturn(null);
259         IClientInterface returnedClientInterface =
260                 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
261         assertEquals(null, returnedClientInterface);
262         verify(mWifiInjector, times(2)).makeWificond();
263     }
264 
265     /**
266      * Verifies that setupInterfaceForClientMode(TEST_INTERFACE_NAME) returns null when wificond
267      * failed to setup client interface.
268      */
269     @Test
testSetupInterfaceForClientModeErrorWhenWificondFailedToSetupInterface()270     public void testSetupInterfaceForClientModeErrorWhenWificondFailedToSetupInterface()
271             throws Exception {
272         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
273         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(null);
274 
275         IClientInterface returnedClientInterface =
276                 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
277         assertEquals(null, returnedClientInterface);
278     }
279 
280     /**
281      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
282      */
283     @Test
testTeardownClientInterface()284     public void testTeardownClientInterface() throws Exception {
285         when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(true);
286 
287         assertTrue(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME));
288         verify(mWifiScannerImpl).unsubscribeScanEvents();
289         verify(mWifiScannerImpl).unsubscribePnoScanEvents();
290         verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME);
291     }
292 
293     /**
294      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
295      */
296     @Test
testTeardownClientInterfaceOnInvalidIface()297     public void testTeardownClientInterfaceOnInvalidIface() throws Exception {
298         when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME1)).thenReturn(true);
299 
300         assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME1));
301         verify(mWifiScannerImpl, never()).unsubscribeScanEvents();
302         verify(mWifiScannerImpl, never()).unsubscribePnoScanEvents();
303         verify(mWificond, never()).tearDownClientInterface(any());
304     }
305 
306     /**
307      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
308      */
309     @Test
testTeardownClientInterfaceFailDueToExceptionScannerUnsubscribe()310     public void testTeardownClientInterfaceFailDueToExceptionScannerUnsubscribe() throws Exception {
311         when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(true);
312         doThrow(new RemoteException()).when(mWifiScannerImpl).unsubscribeScanEvents();
313 
314         assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME));
315         verify(mWifiScannerImpl).unsubscribeScanEvents();
316         verify(mWifiScannerImpl, never()).unsubscribePnoScanEvents();
317         verify(mWificond, never()).tearDownClientInterface(TEST_INTERFACE_NAME);
318     }
319     /**
320      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
321      */
322     @Test
testTeardownClientInterfaceErrorWhenWificondFailed()323     public void testTeardownClientInterfaceErrorWhenWificondFailed() throws Exception {
324         when(mWificond.tearDownClientInterface(TEST_INTERFACE_NAME)).thenReturn(false);
325 
326         assertFalse(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME));
327         verify(mWifiScannerImpl).unsubscribeScanEvents();
328         verify(mWifiScannerImpl).unsubscribePnoScanEvents();
329         verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME);
330     }
331 
332     /**
333      * Verifies that the client handles are cleared after teardown.
334      */
335     @Test
testTeardownClientInterfaceClearsHandles()336     public void testTeardownClientInterfaceClearsHandles() throws Exception {
337         testTeardownClientInterface();
338 
339         assertNull(mWificondControl.signalPoll(TEST_INTERFACE_NAME));
340         verify(mClientInterface, never()).signalPoll();
341 
342         assertFalse(mWificondControl.scan(
343                 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_LATENCY,
344                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
345         verify(mWifiScannerImpl, never()).scan(any());
346     }
347 
348     /**
349      * Verifies that setupInterfaceForSoftApMode(TEST_INTERFACE_NAME) calls wificond.
350      */
351     @Test
testSetupInterfaceForSoftApMode()352     public void testSetupInterfaceForSoftApMode() throws Exception {
353         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
354         when(mWificond.createApInterface(TEST_INTERFACE_NAME)).thenReturn(mApInterface);
355 
356         IApInterface returnedApInterface =
357                 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME);
358         assertEquals(mApInterface, returnedApInterface);
359         verify(mWifiInjector).makeWificond();
360         verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
361         verify(mWificond).createApInterface(TEST_INTERFACE_NAME);
362     }
363 
364     /**
365      * Verifies that setupInterfaceForSoftAp() returns null when wificond is not started.
366      */
367     @Test
testSetupInterfaceForSoftApModeErrorWhenWificondIsNotStarted()368     public void testSetupInterfaceForSoftApModeErrorWhenWificondIsNotStarted() throws Exception {
369         // Invoke wificond death handler to clear the handle.
370         mWificondControl.binderDied();
371         mLooper.dispatchAll();
372         when(mWifiInjector.makeWificond()).thenReturn(null);
373 
374         IApInterface returnedApInterface =
375                 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME);
376 
377         assertEquals(null, returnedApInterface);
378         verify(mWifiInjector, times(2)).makeWificond();
379     }
380 
381     /**
382      * Verifies that setupInterfaceForSoftApMode(TEST_INTERFACE_NAME) returns null when wificond
383      * failed to setup AP interface.
384      */
385     @Test
testSetupInterfaceForSoftApModeErrorWhenWificondFailedToSetupInterface()386     public void testSetupInterfaceForSoftApModeErrorWhenWificondFailedToSetupInterface()
387             throws Exception {
388         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
389         when(mWificond.createApInterface(TEST_INTERFACE_NAME)).thenReturn(null);
390 
391         IApInterface returnedApInterface =
392                 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME);
393         assertEquals(null, returnedApInterface);
394     }
395 
396     /**
397      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
398      */
399     @Test
testTeardownSoftApInterface()400     public void testTeardownSoftApInterface() throws Exception {
401         testSetupInterfaceForSoftApMode();
402         when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME)).thenReturn(true);
403 
404         assertTrue(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME));
405         verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME);
406     }
407 
408     /**
409      * Verifies that tearDownSoftapInterface(TEST_INTERFACE_NAME) calls Wificond.
410      */
411     @Test
testTeardownSoftApInterfaceOnInvalidIface()412     public void testTeardownSoftApInterfaceOnInvalidIface() throws Exception {
413         testSetupInterfaceForSoftApMode();
414         when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME1)).thenReturn(true);
415 
416         assertFalse(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME1));
417         verify(mWificond, never()).tearDownApInterface(any());
418     }
419 
420     /**
421      * Verifies that tearDownClientInterface(TEST_INTERFACE_NAME) calls Wificond.
422      */
423     @Test
testTeardownSoftApInterfaceErrorWhenWificondFailed()424     public void testTeardownSoftApInterfaceErrorWhenWificondFailed() throws Exception {
425         testSetupInterfaceForSoftApMode();
426         when(mWificond.tearDownApInterface(TEST_INTERFACE_NAME)).thenReturn(false);
427 
428         assertFalse(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME));
429         verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME);
430     }
431 
432     /**
433      * Verifies that the SoftAp handles are cleared after teardown.
434      */
435     @Test
testTeardownSoftApInterfaceClearsHandles()436     public void testTeardownSoftApInterfaceClearsHandles() throws Exception {
437         testTeardownSoftApInterface();
438 
439         assertFalse(mWificondControl.registerApListener(
440                 TEST_INTERFACE_NAME, mSoftApListener));
441         verify(mApInterface, never()).registerCallback(any());
442     }
443 
444     /**
445      * Verifies that we can setup concurrent interfaces.
446      */
447     @Test
testSetupMulitpleInterfaces()448     public void testSetupMulitpleInterfaces() throws Exception {
449         when(mWificond.createApInterface(TEST_INTERFACE_NAME1)).thenReturn(mApInterface);
450 
451         IApInterface returnedApInterface =
452                 mWificondControl.setupInterfaceForSoftApMode(TEST_INTERFACE_NAME1);
453         assertEquals(mApInterface, returnedApInterface);
454         verify(mWifiInjector).makeWificond();
455         verify(mWifiCondBinder).linkToDeath(any(IBinder.DeathRecipient.class), anyInt());
456 
457         verify(mWificond).createClientInterface(TEST_INTERFACE_NAME);
458         verify(mWificond).createApInterface(TEST_INTERFACE_NAME1);
459     }
460 
461     /**
462      * Verifies that we can setup concurrent interfaces.
463      */
464     @Test
testTeardownMulitpleInterfaces()465     public void testTeardownMulitpleInterfaces() throws Exception {
466         testSetupMulitpleInterfaces();
467         assertTrue(mWificondControl.tearDownClientInterface(TEST_INTERFACE_NAME));
468         assertTrue(mWificondControl.tearDownSoftApInterface(TEST_INTERFACE_NAME1));
469 
470         verify(mWificond).tearDownClientInterface(TEST_INTERFACE_NAME);
471         verify(mWificond).tearDownApInterface(TEST_INTERFACE_NAME1);
472     }
473 
474     /**
475      * Verifies that tearDownInterfaces() calls wificond.
476      */
477     @Test
testTearDownInterfaces()478     public void testTearDownInterfaces() throws Exception {
479         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
480         assertTrue(mWificondControl.tearDownInterfaces());
481         verify(mWificond).tearDownInterfaces();
482     }
483 
484     /**
485      * Verifies that tearDownInterfaces() calls unsubscribeScanEvents() when there was
486      * a configured client interface.
487      */
488     @Test
testTearDownInterfacesRemovesScanEventSubscription()489     public void testTearDownInterfacesRemovesScanEventSubscription() throws Exception {
490         assertTrue(mWificondControl.tearDownInterfaces());
491         verify(mWifiScannerImpl).unsubscribeScanEvents();
492     }
493 
494 
495     /**
496      * Verifies that tearDownInterfaces() returns false when wificond is not started.
497      */
498     @Test
testTearDownInterfacesErrorWhenWificondIsNotStarterd()499     public void testTearDownInterfacesErrorWhenWificondIsNotStarterd() throws Exception {
500         // Invoke wificond death handler to clear the handle.
501         mWificondControl.binderDied();
502         mLooper.dispatchAll();
503         when(mWifiInjector.makeWificond()).thenReturn(null);
504         assertFalse(mWificondControl.tearDownInterfaces());
505     }
506 
507     /**
508      * Verifies that signalPoll() calls wificond.
509      */
510     @Test
testSignalPoll()511     public void testSignalPoll() throws Exception {
512         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
513         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
514 
515         mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
516         mWificondControl.signalPoll(TEST_INTERFACE_NAME);
517         verify(mClientInterface).signalPoll();
518     }
519 
520     /**
521      * Verifies that signalPoll() returns null when there is no configured client interface.
522      */
523     @Test
testSignalPollErrorWhenNoClientInterfaceConfigured()524     public void testSignalPollErrorWhenNoClientInterfaceConfigured() throws Exception {
525         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
526         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
527 
528         // Configure client interface.
529         IClientInterface returnedClientInterface =
530                 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
531         assertEquals(mClientInterface, returnedClientInterface);
532 
533         // Tear down interfaces.
534         assertTrue(mWificondControl.tearDownInterfaces());
535 
536         // Signal poll should fail.
537         assertEquals(null, mWificondControl.signalPoll(TEST_INTERFACE_NAME));
538     }
539 
540     /**
541      * Verifies that getTxPacketCounters() calls wificond.
542      */
543     @Test
testGetTxPacketCounters()544     public void testGetTxPacketCounters() throws Exception {
545         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
546         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
547 
548         mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
549         mWificondControl.getTxPacketCounters(TEST_INTERFACE_NAME);
550         verify(mClientInterface).getPacketCounters();
551     }
552 
553     /**
554      * Verifies that getTxPacketCounters() returns null when there is no configured client
555      * interface.
556      */
557     @Test
testGetTxPacketCountersErrorWhenNoClientInterfaceConfigured()558     public void testGetTxPacketCountersErrorWhenNoClientInterfaceConfigured() throws Exception {
559         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
560         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
561 
562         // Configure client interface.
563         IClientInterface returnedClientInterface =
564                 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
565         assertEquals(mClientInterface, returnedClientInterface);
566 
567         // Tear down interfaces.
568         assertTrue(mWificondControl.tearDownInterfaces());
569 
570         // Signal poll should fail.
571         assertEquals(null, mWificondControl.getTxPacketCounters(TEST_INTERFACE_NAME));
572     }
573 
574     /**
575      * Verifies that getScanResults() returns null when there is no configured client
576      * interface.
577      */
578     @Test
testGetScanResultsErrorWhenNoClientInterfaceConfigured()579     public void testGetScanResultsErrorWhenNoClientInterfaceConfigured() throws Exception {
580         when(mWifiInjector.makeWificond()).thenReturn(mWificond);
581         when(mWificond.createClientInterface(TEST_INTERFACE_NAME)).thenReturn(mClientInterface);
582 
583         // Configure client interface.
584         IClientInterface returnedClientInterface =
585                 mWificondControl.setupInterfaceForClientMode(TEST_INTERFACE_NAME);
586         assertEquals(mClientInterface, returnedClientInterface);
587 
588         // Tear down interfaces.
589         assertTrue(mWificondControl.tearDownInterfaces());
590 
591         // getScanResults should fail.
592         assertEquals(0,
593                 mWificondControl.getScanResults(TEST_INTERFACE_NAME,
594                         WificondControl.SCAN_TYPE_SINGLE_SCAN).size());
595     }
596 
597     /**
598      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
599      */
600     @Test
testGetScanResults()601     public void testGetScanResults() throws Exception {
602         assertNotNull(mWifiScannerImpl);
603 
604         // Mock the returned array of NativeScanResult.
605         NativeScanResult[] mockScanResults = {MOCK_NATIVE_SCAN_RESULT};
606         when(mWifiScannerImpl.getScanResults()).thenReturn(mockScanResults);
607 
608         ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults(
609                 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN);
610         // The test IEs {@link #TEST_INFO_ELEMENT} doesn't contained RSN IE, which means non-EAP
611         // AP. So verify carrier network is not checked, since EAP is currently required for a
612         // carrier network.
613         verify(mCarrierNetworkConfig, never()).isCarrierNetwork(anyString());
614         assertEquals(mockScanResults.length, returnedScanResults.size());
615         // Since NativeScanResult is organized differently from ScanResult, this only checks
616         // a few fields.
617         for (int i = 0; i < mockScanResults.length; i++) {
618             assertArrayEquals(mockScanResults[i].ssid,
619                               returnedScanResults.get(i).getScanResult().SSID.getBytes());
620             assertEquals(mockScanResults[i].frequency,
621                          returnedScanResults.get(i).getScanResult().frequency);
622             assertEquals(mockScanResults[i].tsf,
623                          returnedScanResults.get(i).getScanResult().timestamp);
624         }
625     }
626 
627     /**
628      * Verifies that scan result's carrier network info {@link ScanResult#isCarrierAp} and
629      * {@link ScanResult#getCarrierApEapType} is set appropriated based on the carrier network
630      * config.
631      *
632      * @throws Exception
633      */
634     @Test
testGetScanResultsForCarrierAp()635     public void testGetScanResultsForCarrierAp() throws Exception {
636         assertNotNull(mWifiScannerImpl);
637 
638         // Include RSN IE to indicate EAP key management.
639         ByteArrayOutputStream out = new ByteArrayOutputStream();
640         out.write(TEST_INFO_ELEMENT_SSID);
641         out.write(TEST_INFO_ELEMENT_RSN);
642         NativeScanResult nativeScanResult = new NativeScanResult(MOCK_NATIVE_SCAN_RESULT);
643         nativeScanResult.infoElement = out.toByteArray();
644         when(mWifiScannerImpl.getScanResults()).thenReturn(
645                 new NativeScanResult[] {nativeScanResult});
646 
647         // AP associated with a carrier network.
648         int eapType = WifiEnterpriseConfig.Eap.SIM;
649         String carrierName = "Test Carrier";
650         when(mCarrierNetworkConfig.isCarrierNetwork(new String(nativeScanResult.ssid)))
651                 .thenReturn(true);
652         when(mCarrierNetworkConfig.getNetworkEapType(new String(nativeScanResult.ssid)))
653                 .thenReturn(eapType);
654         when(mCarrierNetworkConfig.getCarrierName(new String(nativeScanResult.ssid)))
655                 .thenReturn(carrierName);
656         ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults(
657                 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN);
658         assertEquals(1, returnedScanResults.size());
659         // Verify returned scan result.
660         ScanResult scanResult = returnedScanResults.get(0).getScanResult();
661         assertArrayEquals(nativeScanResult.ssid, scanResult.SSID.getBytes());
662         assertTrue(scanResult.isCarrierAp);
663         assertEquals(eapType, scanResult.carrierApEapType);
664         assertEquals(carrierName, scanResult.carrierName);
665         reset(mCarrierNetworkConfig);
666 
667         // AP not associated with a carrier network.
668         when(mCarrierNetworkConfig.isCarrierNetwork(new String(nativeScanResult.ssid)))
669                 .thenReturn(false);
670         returnedScanResults = mWificondControl.getScanResults(
671                 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN);
672         assertEquals(1, returnedScanResults.size());
673         // Verify returned scan result.
674         scanResult = returnedScanResults.get(0).getScanResult();
675         assertArrayEquals(nativeScanResult.ssid, scanResult.SSID.getBytes());
676         assertFalse(scanResult.isCarrierAp);
677         assertEquals(ScanResult.UNSPECIFIED, scanResult.carrierApEapType);
678         assertEquals(null, scanResult.carrierName);
679     }
680 
681     /**
682      * Verifies that getScanResults() can parse NativeScanResult from wificond correctly,
683      * when there is radio chain info.
684      */
685     @Test
testGetScanResultsWithRadioChainInfo()686     public void testGetScanResultsWithRadioChainInfo() throws Exception {
687         assertNotNull(mWifiScannerImpl);
688 
689         // Mock the returned array of NativeScanResult.
690         NativeScanResult nativeScanResult = new NativeScanResult(MOCK_NATIVE_SCAN_RESULT);
691         // Add radio chain info
692         ArrayList<RadioChainInfo> nativeRadioChainInfos = new ArrayList<RadioChainInfo>() {{
693                 add(MOCK_NATIVE_RADIO_CHAIN_INFO_1);
694                 add(MOCK_NATIVE_RADIO_CHAIN_INFO_2);
695             }};
696         nativeScanResult.radioChainInfos = nativeRadioChainInfos;
697         NativeScanResult[] mockScanResults = { nativeScanResult };
698 
699         when(mWifiScannerImpl.getScanResults()).thenReturn(mockScanResults);
700 
701         ArrayList<ScanDetail> returnedScanResults = mWificondControl.getScanResults(
702                 TEST_INTERFACE_NAME, WificondControl.SCAN_TYPE_SINGLE_SCAN);
703         // The test IEs {@link #TEST_INFO_ELEMENT} doesn't contained RSN IE, which means non-EAP
704         // AP. So verify carrier network is not checked, since EAP is currently required for a
705         // carrier network.
706         verify(mCarrierNetworkConfig, never()).isCarrierNetwork(anyString());
707         assertEquals(mockScanResults.length, returnedScanResults.size());
708         // Since NativeScanResult is organized differently from ScanResult, this only checks
709         // a few fields.
710         for (int i = 0; i < mockScanResults.length; i++) {
711             assertArrayEquals(mockScanResults[i].ssid,
712                     returnedScanResults.get(i).getScanResult().SSID.getBytes());
713             assertEquals(mockScanResults[i].frequency,
714                     returnedScanResults.get(i).getScanResult().frequency);
715             assertEquals(mockScanResults[i].tsf,
716                     returnedScanResults.get(i).getScanResult().timestamp);
717             assertRadioChainInfosEqual(nativeRadioChainInfos,
718                     returnedScanResults.get(i).getScanResult().radioChainInfos);
719         }
720     }
721 
722     /**
723      * Verifies that Scan() can convert input parameters to SingleScanSettings correctly.
724      */
725     @Test
testScan()726     public void testScan() throws Exception {
727         when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true);
728         assertTrue(mWificondControl.scan(
729                 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_POWER,
730                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
731         verify(mWifiScannerImpl).scan(argThat(new ScanMatcher(
732                 IWifiScannerImpl.SCAN_TYPE_LOW_POWER,
733                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)));
734     }
735 
736     /**
737      * Verifies that Scan() removes duplicates hiddenSsids passed in from input.
738      */
739     @Test
testScanWithDuplicateHiddenSsids()740     public void testScanWithDuplicateHiddenSsids() throws Exception {
741         when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true);
742         // Create a list of hiddenSsid that has a duplicate element
743         List<String> hiddenSsidWithDup = new ArrayList<>(SCAN_HIDDEN_NETWORK_SSID_LIST);
744         hiddenSsidWithDup.add(SCAN_HIDDEN_NETWORK_SSID_LIST.get(0));
745         assertEquals(hiddenSsidWithDup.get(0),
746                 hiddenSsidWithDup.get(hiddenSsidWithDup.size() - 1));
747         // Pass the List with duplicate elements into scan()
748         assertTrue(mWificondControl.scan(
749                 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_POWER,
750                 SCAN_FREQ_SET, hiddenSsidWithDup));
751         // But the argument passed down should have the duplicate removed.
752         verify(mWifiScannerImpl).scan(argThat(new ScanMatcher(
753                 IWifiScannerImpl.SCAN_TYPE_LOW_POWER,
754                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST)));
755     }
756 
757     /**
758      * Verifies that Scan() can handle null input parameters correctly.
759      */
760     @Test
testScanNullParameters()761     public void testScanNullParameters() throws Exception {
762         when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(true);
763         assertTrue(mWificondControl.scan(
764                 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_HIGH_ACCURACY, null, null));
765         verify(mWifiScannerImpl).scan(argThat(new ScanMatcher(
766                 IWifiScannerImpl.SCAN_TYPE_HIGH_ACCURACY, null, null)));
767     }
768 
769     /**
770      * Verifies that Scan() can handle wificond scan failure.
771      */
772     @Test
testScanFailure()773     public void testScanFailure() throws Exception {
774         when(mWifiScannerImpl.scan(any(SingleScanSettings.class))).thenReturn(false);
775         assertFalse(mWificondControl.scan(
776                 TEST_INTERFACE_NAME, WifiNative.SCAN_TYPE_LOW_LATENCY,
777                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
778         verify(mWifiScannerImpl).scan(any(SingleScanSettings.class));
779     }
780 
781     /**
782      * Verifies that Scan() can handle invalid type.
783      */
784     @Test
testScanFailureDueToInvalidType()785     public void testScanFailureDueToInvalidType() throws Exception {
786         assertFalse(mWificondControl.scan(
787                 TEST_INTERFACE_NAME, 100,
788                 SCAN_FREQ_SET, SCAN_HIDDEN_NETWORK_SSID_LIST));
789         verify(mWifiScannerImpl, never()).scan(any(SingleScanSettings.class));
790     }
791 
792     /**
793      * Verifies that startPnoScan() can convert input parameters to PnoSettings correctly.
794      */
795     @Test
testStartPnoScan()796     public void testStartPnoScan() throws Exception {
797         when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(true);
798         assertTrue(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS));
799         verify(mWifiScannerImpl).startPnoScan(argThat(new PnoScanMatcher(TEST_PNO_SETTINGS)));
800     }
801 
802     /**
803      * Verifies that stopPnoScan() calls underlying wificond.
804      */
805     @Test
testStopPnoScan()806     public void testStopPnoScan() throws Exception {
807         when(mWifiScannerImpl.stopPnoScan()).thenReturn(true);
808         assertTrue(mWificondControl.stopPnoScan(TEST_INTERFACE_NAME));
809         verify(mWifiScannerImpl).stopPnoScan();
810     }
811 
812     /**
813      * Verifies that stopPnoScan() can handle wificond failure.
814      */
815     @Test
testStopPnoScanFailure()816     public void testStopPnoScanFailure() throws Exception {
817 
818         when(mWifiScannerImpl.stopPnoScan()).thenReturn(false);
819         assertFalse(mWificondControl.stopPnoScan(TEST_INTERFACE_NAME));
820         verify(mWifiScannerImpl).stopPnoScan();
821     }
822 
823     /**
824      * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon scan
825      * reuslt event.
826      */
827     @Test
testScanResultEvent()828     public void testScanResultEvent() throws Exception {
829         ArgumentCaptor<IScanEvent> messageCaptor = ArgumentCaptor.forClass(IScanEvent.class);
830         verify(mWifiScannerImpl).subscribeScanEvents(messageCaptor.capture());
831         IScanEvent scanEvent = messageCaptor.getValue();
832         assertNotNull(scanEvent);
833         scanEvent.OnScanResultReady();
834 
835         verify(mWifiMonitor).broadcastScanResultEvent(any(String.class));
836     }
837 
838     /**
839      * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon scan
840      * failed event.
841      */
842     @Test
testScanFailedEvent()843     public void testScanFailedEvent() throws Exception {
844 
845         ArgumentCaptor<IScanEvent> messageCaptor = ArgumentCaptor.forClass(IScanEvent.class);
846         verify(mWifiScannerImpl).subscribeScanEvents(messageCaptor.capture());
847         IScanEvent scanEvent = messageCaptor.getValue();
848         assertNotNull(scanEvent);
849         scanEvent.OnScanFailed();
850 
851         verify(mWifiMonitor).broadcastScanFailedEvent(any(String.class));
852     }
853 
854     /**
855      * Verifies that WificondControl can invoke WifiMonitor broadcast methods upon pno scan
856      * result event.
857      */
858     @Test
testPnoScanResultEvent()859     public void testPnoScanResultEvent() throws Exception {
860         ArgumentCaptor<IPnoScanEvent> messageCaptor = ArgumentCaptor.forClass(IPnoScanEvent.class);
861         verify(mWifiScannerImpl).subscribePnoScanEvents(messageCaptor.capture());
862         IPnoScanEvent pnoScanEvent = messageCaptor.getValue();
863         assertNotNull(pnoScanEvent);
864         pnoScanEvent.OnPnoNetworkFound();
865         verify(mWifiMonitor).broadcastPnoScanResultEvent(any(String.class));
866     }
867 
868     /**
869      * Verifies that WificondControl can invoke WifiMetrics pno scan count methods upon pno event.
870      */
871     @Test
testPnoScanEventsForMetrics()872     public void testPnoScanEventsForMetrics() throws Exception {
873         ArgumentCaptor<IPnoScanEvent> messageCaptor = ArgumentCaptor.forClass(IPnoScanEvent.class);
874         verify(mWifiScannerImpl).subscribePnoScanEvents(messageCaptor.capture());
875         IPnoScanEvent pnoScanEvent = messageCaptor.getValue();
876         assertNotNull(pnoScanEvent);
877 
878         pnoScanEvent.OnPnoNetworkFound();
879         verify(mWifiMetrics).incrementPnoFoundNetworkEventCount();
880 
881         pnoScanEvent.OnPnoScanFailed();
882         verify(mWifiMetrics).incrementPnoScanFailedCount();
883 
884         pnoScanEvent.OnPnoScanOverOffloadStarted();
885         verify(mWifiMetrics).incrementPnoScanStartedOverOffloadCount();
886 
887         pnoScanEvent.OnPnoScanOverOffloadFailed(0);
888         verify(mWifiMetrics).incrementPnoScanFailedOverOffloadCount();
889     }
890 
891     /**
892      * Verifies that startPnoScan() can invoke WifiMetrics pno scan count methods correctly.
893      */
894     @Test
testStartPnoScanForMetrics()895     public void testStartPnoScanForMetrics() throws Exception {
896         when(mWifiScannerImpl.startPnoScan(any(PnoSettings.class))).thenReturn(false);
897         assertFalse(mWificondControl.startPnoScan(TEST_INTERFACE_NAME, TEST_PNO_SETTINGS));
898         verify(mWifiMetrics).incrementPnoScanStartAttempCount();
899         verify(mWifiMetrics).incrementPnoScanFailedCount();
900     }
901 
902     /**
903      * Verifies that abortScan() calls underlying wificond.
904      */
905     @Test
testAbortScan()906     public void testAbortScan() throws Exception {
907         mWificondControl.abortScan(TEST_INTERFACE_NAME);
908         verify(mWifiScannerImpl).abortScan();
909     }
910 
911     /**
912      * Ensures that the Ap interface callbacks are forwarded to the
913      * SoftApListener used for starting soft AP.
914      */
915     @Test
testSoftApListenerInvocation()916     public void testSoftApListenerInvocation() throws Exception {
917         testSetupInterfaceForSoftApMode();
918 
919         WifiConfiguration config = new WifiConfiguration();
920         config.SSID = new String(TEST_SSID, StandardCharsets.UTF_8);
921 
922         when(mApInterface.registerCallback(any())).thenReturn(true);
923 
924         final ArgumentCaptor<IApInterfaceEventCallback> apInterfaceCallbackCaptor =
925                 ArgumentCaptor.forClass(IApInterfaceEventCallback.class);
926 
927         assertTrue(mWificondControl.registerApListener(
928                 TEST_INTERFACE_NAME, mSoftApListener));
929         verify(mApInterface).registerCallback(apInterfaceCallbackCaptor.capture());
930 
931         int numStations = 5;
932         apInterfaceCallbackCaptor.getValue().onNumAssociatedStationsChanged(numStations);
933         verify(mSoftApListener).onNumAssociatedStationsChanged(eq(numStations));
934 
935         int channelFrequency = 2437;
936         int channelBandwidth = IApInterfaceEventCallback.BANDWIDTH_20;
937         apInterfaceCallbackCaptor.getValue().onSoftApChannelSwitched(channelFrequency,
938                 channelBandwidth);
939         verify(mSoftApListener).onSoftApChannelSwitched(eq(channelFrequency), eq(channelBandwidth));
940     }
941 
942     /**
943      * Verifies registration and invocation of wificond death handler.
944      */
945     @Test
testRegisterDeathHandler()946     public void testRegisterDeathHandler() throws Exception {
947         WifiNative.WificondDeathEventHandler handler =
948                 mock(WifiNative.WificondDeathEventHandler.class);
949         assertTrue(mWificondControl.initialize(handler));
950         verify(mWificond).tearDownInterfaces();
951         mWificondControl.binderDied();
952         mLooper.dispatchAll();
953         verify(handler).onDeath();
954     }
955 
956     /**
957      * Verifies handling of wificond death and ensures that all internal state is cleared and
958      * handlers are invoked.
959      */
960     @Test
testDeathHandling()961     public void testDeathHandling() throws Exception {
962         WifiNative.WificondDeathEventHandler handler =
963                 mock(WifiNative.WificondDeathEventHandler.class);
964         assertTrue(mWificondControl.initialize(handler));
965 
966         testSetupInterfaceForClientMode();
967 
968         mWificondControl.binderDied();
969         mLooper.dispatchAll();
970         verify(handler).onDeath();
971 
972         // The handles should be cleared after death.
973         assertNull(mWificondControl.getChannelsForBand(WifiScanner.WIFI_BAND_5_GHZ));
974         verify(mWificond, never()).getAvailable5gNonDFSChannels();
975     }
976 
977     /**
978      * sendMgmtFrame() should fail if a null callback is passed in.
979      */
980     @Test
testSendMgmtFrameNullCallback()981     public void testSendMgmtFrameNullCallback() throws Exception {
982         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, null, TEST_MCS_RATE);
983 
984         verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
985     }
986 
987     /**
988      * sendMgmtFrame() should fail if a null frame is passed in.
989      */
990     @Test
testSendMgmtFrameNullFrame()991     public void testSendMgmtFrameNullFrame() throws Exception {
992         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, null,
993                 mSendMgmtFrameCallback, TEST_MCS_RATE);
994 
995         verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
996         verify(mSendMgmtFrameCallback).onFailure(anyInt());
997     }
998 
999     /**
1000      * sendMgmtFrame() should fail if an interface name that does not exist is passed in.
1001      */
1002     @Test
testSendMgmtFrameInvalidInterfaceName()1003     public void testSendMgmtFrameInvalidInterfaceName() throws Exception {
1004         mWificondControl.sendMgmtFrame(TEST_INVALID_INTERFACE_NAME, TEST_PROBE_FRAME,
1005                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1006 
1007         verify(mClientInterface, never()).SendMgmtFrame(any(), any(), anyInt());
1008         verify(mSendMgmtFrameCallback).onFailure(anyInt());
1009     }
1010 
1011     /**
1012      * sendMgmtFrame() should fail if it is called a second time before the first call completed.
1013      */
1014     @Test
testSendMgmtFrameCalledTwiceBeforeFinished()1015     public void testSendMgmtFrameCalledTwiceBeforeFinished() throws Exception {
1016         SendMgmtFrameCallback cb1 = mock(SendMgmtFrameCallback.class);
1017         SendMgmtFrameCallback cb2 = mock(SendMgmtFrameCallback.class);
1018 
1019         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb1, TEST_MCS_RATE);
1020         verify(cb1, never()).onFailure(anyInt());
1021         verify(mClientInterface, times(1))
1022                 .SendMgmtFrame(AdditionalMatchers.aryEq(TEST_PROBE_FRAME),
1023                         any(), eq(TEST_MCS_RATE));
1024 
1025         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb2, TEST_MCS_RATE);
1026         verify(cb2).onFailure(WifiNative.SEND_MGMT_FRAME_ERROR_ALREADY_STARTED);
1027         // verify SendMgmtFrame() still was only called once i.e. not called again
1028         verify(mClientInterface, times(1))
1029                 .SendMgmtFrame(any(), any(), anyInt());
1030     }
1031 
1032     /**
1033      * Tests that when a RemoteException is triggered on AIDL call, onFailure() is called only once.
1034      */
1035     @Test
testSendMgmtFrameThrowsException()1036     public void testSendMgmtFrameThrowsException() throws Exception {
1037         SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class);
1038 
1039         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1040                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1041 
1042         doThrow(new RemoteException()).when(mClientInterface)
1043                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1044 
1045         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1046                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1047         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1048         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1049                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1050 
1051         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
1052                 cb, TEST_MCS_RATE);
1053         mLooper.dispatchAll();
1054 
1055         verify(cb).onFailure(anyInt());
1056         verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue()));
1057 
1058         sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1059         mLooper.dispatchAll();
1060 
1061         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1062         mLooper.dispatchAll();
1063 
1064         verifyNoMoreInteractions(cb);
1065     }
1066 
1067     /**
1068      * Tests that the onAck() callback is triggered correctly.
1069      */
1070     @Test
testSendMgmtFrameSuccess()1071     public void testSendMgmtFrameSuccess() throws Exception {
1072         SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class);
1073 
1074         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1075                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1076         doNothing().when(mClientInterface)
1077                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1078         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1079                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1080         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1081         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1082                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1083         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
1084 
1085         sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS);
1086         mLooper.dispatchAll();
1087         verify(cb).onAck(eq(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS));
1088         verify(cb, never()).onFailure(anyInt());
1089         verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue()));
1090 
1091         // verify that even if timeout is triggered afterwards, SendMgmtFrameCallback is not
1092         // triggered again
1093         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1094         mLooper.dispatchAll();
1095         verify(cb, times(1)).onAck(anyInt());
1096         verify(cb, never()).onFailure(anyInt());
1097     }
1098 
1099     /**
1100      * Tests that the onFailure() callback is triggered correctly.
1101      */
1102     @Test
testSendMgmtFrameFailure()1103     public void testSendMgmtFrameFailure() throws Exception {
1104         SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class);
1105 
1106         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1107                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1108         doNothing().when(mClientInterface)
1109                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1110         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1111                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1112         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1113         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1114                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1115         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
1116 
1117         sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1118         mLooper.dispatchAll();
1119         verify(cb, never()).onAck(anyInt());
1120         verify(cb).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN));
1121         verify(mAlarmManager).cancel(eq(alarmListenerCaptor.getValue()));
1122 
1123         // verify that even if timeout is triggered afterwards, SendMgmtFrameCallback is not
1124         // triggered again
1125         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1126         mLooper.dispatchAll();
1127         verify(cb, never()).onAck(anyInt());
1128         verify(cb, times(1)).onFailure(anyInt());
1129     }
1130 
1131     /**
1132      * Tests that the onTimeout() callback is triggered correctly.
1133      */
1134     @Test
testSendMgmtFrameTimeout()1135     public void testSendMgmtFrameTimeout() throws Exception {
1136         SendMgmtFrameCallback cb = mock(SendMgmtFrameCallback.class);
1137 
1138         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1139                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1140         doNothing().when(mClientInterface)
1141                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1142         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1143                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1144         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1145         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1146                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1147         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME, cb, TEST_MCS_RATE);
1148 
1149         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1150         mLooper.dispatchAll();
1151         verify(cb, never()).onAck(anyInt());
1152         verify(cb).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT));
1153 
1154         // verify that even if onAck() callback is triggered after timeout,
1155         // SendMgmtFrameCallback is not triggered again
1156         sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS);
1157         mLooper.dispatchAll();
1158         verify(cb, never()).onAck(anyInt());
1159         verify(cb, times(1)).onFailure(anyInt());
1160     }
1161 
1162     /**
1163      * Tests every possible test outcome followed by every other test outcome to ensure that the
1164      * internal state is reset correctly between calls.
1165      * i.e. (success, success), (success, failure), (success, timeout),
1166      * (failure, failure), (failure, success), (failure, timeout),
1167      * (timeout, timeout), (timeout, success), (timeout, failure)
1168      *
1169      * Also tests that internal state is reset correctly after a transient AIDL RemoteException.
1170      */
1171     @Test
testSendMgmtFrameMixed()1172     public void testSendMgmtFrameMixed() throws Exception {
1173         testSendMgmtFrameThrowsException();
1174         testSendMgmtFrameSuccess();
1175         testSendMgmtFrameSuccess();
1176         testSendMgmtFrameFailure();
1177         testSendMgmtFrameFailure();
1178         testSendMgmtFrameTimeout();
1179         testSendMgmtFrameTimeout();
1180         testSendMgmtFrameSuccess();
1181         testSendMgmtFrameTimeout();
1182         testSendMgmtFrameFailure();
1183         testSendMgmtFrameSuccess();
1184     }
1185 
1186     /**
1187      * Tests that OnAck() does not perform any non-thread-safe operations on the binder thread.
1188      *
1189      * The sequence of instructions are:
1190      * 1. post onAlarm() onto main thread
1191      * 2. OnAck()
1192      * 3. mLooper.dispatchAll()
1193      *
1194      * The actual order of execution is:
1195      * 1. binder thread portion of OnAck()
1196      * 2. onAlarm() (which purely executes on the main thread)
1197      * 3. main thread portion of OnAck()
1198      *
1199      * If the binder thread portion of OnAck() is not thread-safe, it can possibly mess up
1200      * onAlarm(). Tests that this does not occur.
1201      */
1202     @Test
testSendMgmtFrameTimeoutAckThreadSafe()1203     public void testSendMgmtFrameTimeoutAckThreadSafe() throws Exception {
1204         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1205                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1206         doNothing().when(mClientInterface)
1207                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1208         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1209                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1210         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1211         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1212                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1213         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
1214                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1215 
1216         // AlarmManager should post the onAlarm() callback onto the handler, but since we are
1217         // triggering onAlarm() ourselves during the test, manually post onto handler
1218         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1219         // OnAck posts to the handler
1220         sendMgmtFrameEventCaptor.getValue().OnAck(TEST_SEND_MGMT_FRAME_ELAPSED_TIME_MS);
1221         mLooper.dispatchAll();
1222         verify(mSendMgmtFrameCallback, never()).onAck(anyInt());
1223         verify(mSendMgmtFrameCallback).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT));
1224     }
1225 
1226     /**
1227      * See {@link #testSendMgmtFrameTimeoutAckThreadSafe()}. This test replaces OnAck() with
1228      * OnFailure().
1229      */
1230     @Test
testSendMgmtFrameTimeoutFailureThreadSafe()1231     public void testSendMgmtFrameTimeoutFailureThreadSafe() throws Exception {
1232         final ArgumentCaptor<ISendMgmtFrameEvent> sendMgmtFrameEventCaptor =
1233                 ArgumentCaptor.forClass(ISendMgmtFrameEvent.class);
1234         doNothing().when(mClientInterface)
1235                 .SendMgmtFrame(any(), sendMgmtFrameEventCaptor.capture(), anyInt());
1236         final ArgumentCaptor<AlarmManager.OnAlarmListener> alarmListenerCaptor =
1237                 ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
1238         final ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
1239         doNothing().when(mAlarmManager).set(anyInt(), anyLong(), any(),
1240                 alarmListenerCaptor.capture(), handlerCaptor.capture());
1241         mWificondControl.sendMgmtFrame(TEST_INTERFACE_NAME, TEST_PROBE_FRAME,
1242                 mSendMgmtFrameCallback, TEST_MCS_RATE);
1243 
1244         // AlarmManager should post the onAlarm() callback onto the handler, but since we are
1245         // triggering onAlarm() ourselves during the test, manually post onto handler
1246         handlerCaptor.getValue().post(() -> alarmListenerCaptor.getValue().onAlarm());
1247         // OnFailure posts to the handler
1248         sendMgmtFrameEventCaptor.getValue().OnFailure(WifiNative.SEND_MGMT_FRAME_ERROR_UNKNOWN);
1249         mLooper.dispatchAll();
1250         verify(mSendMgmtFrameCallback).onFailure(eq(WifiNative.SEND_MGMT_FRAME_ERROR_TIMEOUT));
1251     }
1252 
assertRadioChainInfosEqual( List<RadioChainInfo> expected, android.net.wifi.ScanResult.RadioChainInfo[] actual)1253     private void assertRadioChainInfosEqual(
1254             List<RadioChainInfo> expected, android.net.wifi.ScanResult.RadioChainInfo[] actual) {
1255         assertEquals(expected.size(), actual.length);
1256         for (int i = 0; i < actual.length; i++) {
1257             RadioChainInfo nativeRadioChainInfo =
1258                     new RadioChainInfo(actual[i].id, actual[i].level);
1259             assertTrue(expected.contains(nativeRadioChainInfo));
1260         }
1261     }
1262 
1263     // Create a ArgumentMatcher which captures a SingleScanSettings parameter and checks if it
1264     // matches the provided frequency set and ssid set.
1265     private class ScanMatcher implements ArgumentMatcher<SingleScanSettings> {
1266         int mExpectedScanType;
1267         private final Set<Integer> mExpectedFreqs;
1268         private final List<String> mExpectedSsids;
ScanMatcher(int expectedScanType, Set<Integer> expectedFreqs, List<String> expectedSsids)1269         ScanMatcher(int expectedScanType, Set<Integer> expectedFreqs, List<String> expectedSsids) {
1270             this.mExpectedScanType = expectedScanType;
1271             this.mExpectedFreqs = expectedFreqs;
1272             this.mExpectedSsids = expectedSsids;
1273         }
1274 
1275         @Override
matches(SingleScanSettings settings)1276         public boolean matches(SingleScanSettings settings) {
1277             if (settings.scanType != mExpectedScanType) {
1278                 return false;
1279             }
1280             ArrayList<ChannelSettings> channelSettings = settings.channelSettings;
1281             ArrayList<HiddenNetwork> hiddenNetworks = settings.hiddenNetworks;
1282             if (mExpectedFreqs != null) {
1283                 Set<Integer> freqSet = new HashSet<Integer>();
1284                 for (ChannelSettings channel : channelSettings) {
1285                     freqSet.add(channel.frequency);
1286                 }
1287                 if (!mExpectedFreqs.equals(freqSet)) {
1288                     return false;
1289                 }
1290             } else {
1291                 if (channelSettings != null && channelSettings.size() > 0) {
1292                     return false;
1293                 }
1294             }
1295 
1296             if (mExpectedSsids != null) {
1297                 List<String> ssidSet = new ArrayList<String>();
1298                 for (HiddenNetwork network : hiddenNetworks) {
1299                     ssidSet.add(NativeUtil.encodeSsid(
1300                             NativeUtil.byteArrayToArrayList(network.ssid)));
1301                 }
1302                 if (!mExpectedSsids.equals(ssidSet)) {
1303                     return false;
1304                 }
1305 
1306             } else {
1307                 if (hiddenNetworks != null && hiddenNetworks.size() > 0) {
1308                     return false;
1309                 }
1310             }
1311             return true;
1312         }
1313 
1314         @Override
toString()1315         public String toString() {
1316             return "ScanMatcher{mExpectedFreqs=" + mExpectedFreqs
1317                     + ", mExpectedSsids=" + mExpectedSsids + '}';
1318         }
1319     }
1320 
1321     // Create a ArgumentMatcher which captures a PnoSettings parameter and checks if it
1322     // matches the WifiNative.PnoSettings;
1323     private class PnoScanMatcher implements ArgumentMatcher<PnoSettings> {
1324         private final WifiNative.PnoSettings mExpectedPnoSettings;
PnoScanMatcher(WifiNative.PnoSettings expectedPnoSettings)1325         PnoScanMatcher(WifiNative.PnoSettings expectedPnoSettings) {
1326             this.mExpectedPnoSettings = expectedPnoSettings;
1327         }
1328         @Override
matches(PnoSettings settings)1329         public boolean matches(PnoSettings settings) {
1330             if (mExpectedPnoSettings == null) {
1331                 return false;
1332             }
1333             if (settings.intervalMs != mExpectedPnoSettings.periodInMs
1334                     || settings.min2gRssi != mExpectedPnoSettings.min24GHzRssi
1335                     || settings.min5gRssi != mExpectedPnoSettings.min5GHzRssi) {
1336                 return false;
1337             }
1338             if (settings.pnoNetworks == null || mExpectedPnoSettings.networkList == null) {
1339                 return false;
1340             }
1341             if (settings.pnoNetworks.size() != mExpectedPnoSettings.networkList.length) {
1342                 return false;
1343             }
1344 
1345             for (int i = 0; i < settings.pnoNetworks.size(); i++) {
1346                 if (!mExpectedPnoSettings.networkList[i].ssid.equals(NativeUtil.encodeSsid(
1347                          NativeUtil.byteArrayToArrayList(settings.pnoNetworks.get(i).ssid)))) {
1348                     return false;
1349                 }
1350                 boolean isNetworkHidden = (mExpectedPnoSettings.networkList[i].flags
1351                         & WifiScanner.PnoSettings.PnoNetwork.FLAG_DIRECTED_SCAN) != 0;
1352                 if (isNetworkHidden != settings.pnoNetworks.get(i).isHidden) {
1353                     return false;
1354                 }
1355                 if (!Arrays.equals(mExpectedPnoSettings.networkList[i].frequencies,
1356                         settings.pnoNetworks.get(i).frequencies)) {
1357                     return false;
1358                 }
1359             }
1360             return true;
1361         }
1362 
1363         @Override
toString()1364         public String toString() {
1365             return "PnoScanMatcher{" + "mExpectedPnoSettings=" + mExpectedPnoSettings + '}';
1366         }
1367     }
1368 }
1369