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