• 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 import android.app.test.MockAnswerUtil.AnswerWithArguments;
19 import android.hardware.wifi.V1_0.IWifiApIface;
20 import android.hardware.wifi.V1_0.IWifiChip;
21 import android.hardware.wifi.V1_0.IWifiChipEventCallback;
22 import android.hardware.wifi.V1_0.IWifiIface;
23 import android.hardware.wifi.V1_0.IWifiRttController;
24 import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback;
25 import android.hardware.wifi.V1_0.IWifiStaIface;
26 import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback;
27 import android.hardware.wifi.V1_0.RttCapabilities;
28 import android.hardware.wifi.V1_0.RttConfig;
29 import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities;
30 import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities;
31 import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
32 import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats;
33 import android.hardware.wifi.V1_0.StaLinkLayerRadioStats;
34 import android.hardware.wifi.V1_0.StaLinkLayerStats;
35 import android.hardware.wifi.V1_0.StaScanData;
36 import android.hardware.wifi.V1_0.StaScanDataFlagMask;
37 import android.hardware.wifi.V1_0.StaScanResult;
38 import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats;
39 import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType;
40 import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags;
41 import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
42 import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel;
43 import android.hardware.wifi.V1_0.WifiDebugRxPacketFate;
44 import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport;
45 import android.hardware.wifi.V1_0.WifiDebugTxPacketFate;
46 import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport;
47 import android.hardware.wifi.V1_0.WifiInformationElement;
48 import android.hardware.wifi.V1_0.WifiStatus;
49 import android.hardware.wifi.V1_0.WifiStatusCode;
50 import android.net.apf.ApfCapabilities;
51 import android.net.wifi.RttManager;
52 import android.net.wifi.ScanResult;
53 import android.net.wifi.WifiLinkLayerStats;
54 import android.net.wifi.WifiManager;
55 import android.net.wifi.WifiScanner;
56 import android.net.wifi.WifiSsid;
57 import android.net.wifi.WifiWakeReasonAndCounts;
58 import android.os.RemoteException;
59 import android.os.test.TestLooper;
60 import android.util.Pair;
61 
62 import com.android.server.connectivity.KeepalivePacketData;
63 import com.android.server.wifi.util.NativeUtil;
64 
65 import static org.junit.Assert.*;
66 import static org.mockito.Mockito.*;
67 
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.mockito.ArgumentCaptor;
71 import org.mockito.Mock;
72 import org.mockito.MockitoAnnotations;
73 import org.mockito.stubbing.Answer;
74 
75 import java.net.InetAddress;
76 import java.util.ArrayList;
77 import java.util.Arrays;
78 import java.util.List;
79 import java.util.Random;
80 
81 /**
82  * Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
83  */
84 public class WifiVendorHalTest {
85 
86     WifiVendorHal mWifiVendorHal;
87     private WifiStatus mWifiStatusSuccess;
88     private WifiStatus mWifiStatusFailure;
89     WifiLog mWifiLog;
90     @Mock
91     private HalDeviceManager mHalDeviceManager;
92     @Mock
93     private TestLooper mLooper;
94     @Mock
95     private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
96     @Mock
97     private IWifiApIface mIWifiApIface;
98     @Mock
99     private IWifiChip mIWifiChip;
100     @Mock
101     private IWifiStaIface mIWifiStaIface;
102     @Mock
103     private IWifiRttController mIWifiRttController;
104     private IWifiStaIfaceEventCallback mIWifiStaIfaceEventCallback;
105     private IWifiChipEventCallback mIWifiChipEventCallback;
106     @Mock
107     private WifiNative.VendorHalDeathEventHandler mVendorHalDeathHandler;
108 
109     /**
110      * Identity function to supply a type to its argument, which is a lambda
111      */
answerWifiStatus(Answer<WifiStatus> statusLambda)112     static Answer<WifiStatus> answerWifiStatus(Answer<WifiStatus> statusLambda) {
113         return (statusLambda);
114     }
115 
116     /**
117      * Sets up for unit test
118      */
119     @Before
setUp()120     public void setUp() throws Exception {
121         MockitoAnnotations.initMocks(this);
122         mWifiLog = new FakeWifiLog();
123         mLooper = new TestLooper();
124         mWifiStatusSuccess = new WifiStatus();
125         mWifiStatusSuccess.code = WifiStatusCode.SUCCESS;
126         mWifiStatusFailure = new WifiStatus();
127         mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN;
128         mWifiStatusFailure.description = "I don't even know what a Mock Turtle is.";
129         when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess);
130 
131         // Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in
132         // individual tests, if needed.
133         doAnswer(new AnswerWithArguments() {
134             public boolean answer() {
135                 when(mHalDeviceManager.isReady()).thenReturn(true);
136                 when(mHalDeviceManager.isStarted()).thenReturn(true);
137                 mHalDeviceManagerStatusCallbacks.onStatusChanged();
138                 return true;
139             }
140         }).when(mHalDeviceManager).start();
141 
142         doAnswer(new AnswerWithArguments() {
143             public void answer() {
144                 when(mHalDeviceManager.isReady()).thenReturn(true);
145                 when(mHalDeviceManager.isStarted()).thenReturn(false);
146                 mHalDeviceManagerStatusCallbacks.onStatusChanged();
147             }
148         }).when(mHalDeviceManager).stop();
149         when(mHalDeviceManager.createStaIface(eq(null), eq(null)))
150                 .thenReturn(mIWifiStaIface);
151         when(mHalDeviceManager.createApIface(eq(null), eq(null)))
152                 .thenReturn(mIWifiApIface);
153         when(mHalDeviceManager.getChip(any(IWifiIface.class)))
154                 .thenReturn(mIWifiChip);
155         when(mHalDeviceManager.createRttController(any(IWifiIface.class)))
156                 .thenReturn(mIWifiRttController);
157         when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
158                 .thenReturn(mWifiStatusSuccess);
159         mIWifiStaIfaceEventCallback = null;
160         when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class)))
161                 .thenAnswer(answerWifiStatus((invocation) -> {
162                     Object[] args = invocation.getArguments();
163                     mIWifiStaIfaceEventCallback = (IWifiStaIfaceEventCallback) args[0];
164                     return (mWifiStatusSuccess);
165                 }));
166         mIWifiChipEventCallback = null;
167         when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
168                 .thenAnswer(answerWifiStatus((invocation) -> {
169                     Object[] args = invocation.getArguments();
170                     mIWifiChipEventCallback = (IWifiChipEventCallback) args[0];
171                     return (mWifiStatusSuccess);
172                 }));
173 
174         when(mIWifiRttController.registerEventCallback(any(IWifiRttControllerEventCallback.class)))
175                 .thenReturn(mWifiStatusSuccess);
176 
177         // Create the vendor HAL object under test.
178         mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mLooper.getLooper());
179 
180         // Initialize the vendor HAL to capture the registered callback.
181         mWifiVendorHal.initialize(mVendorHalDeathHandler);
182         ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> hdmCallbackCaptor =
183                 ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class);
184         verify(mHalDeviceManager).registerStatusListener(hdmCallbackCaptor.capture(), any());
185         mHalDeviceManagerStatusCallbacks = hdmCallbackCaptor.getValue();
186 
187     }
188 
189     /**
190      * Tests the successful starting of HAL in STA mode using
191      * {@link WifiVendorHal#startVendorHal(boolean)}.
192      */
193     @Test
testStartHalSuccessInStaMode()194     public void testStartHalSuccessInStaMode() throws  Exception {
195         assertTrue(mWifiVendorHal.startVendorHal(true));
196         assertTrue(mWifiVendorHal.isHalStarted());
197 
198         verify(mHalDeviceManager).start();
199         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
200         verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
201         verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
202         verify(mHalDeviceManager).isReady();
203         verify(mHalDeviceManager).isStarted();
204         verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
205         verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
206 
207         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
208     }
209 
210     /**
211      * Tests the successful starting of HAL in AP mode using
212      * {@link WifiVendorHal#startVendorHal(boolean)}.
213      */
214     @Test
testStartHalSuccessInApMode()215     public void testStartHalSuccessInApMode() throws Exception {
216         assertTrue(mWifiVendorHal.startVendorHal(false));
217         assertTrue(mWifiVendorHal.isHalStarted());
218 
219         verify(mHalDeviceManager).start();
220         verify(mHalDeviceManager).createApIface(eq(null), eq(null));
221         verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
222         verify(mHalDeviceManager).isReady();
223         verify(mHalDeviceManager).isStarted();
224 
225         verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
226         verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
227     }
228 
229     /**
230      * Tests the failure to start HAL in STA mode using
231      * {@link WifiVendorHal#startVendorHal(boolean)}.
232      */
233     @Test
testStartHalFailureInStaMode()234     public void testStartHalFailureInStaMode() throws Exception {
235         // No callbacks are invoked in this case since the start itself failed. So, override
236         // default AnswerWithArguments that we setup.
237         doAnswer(new AnswerWithArguments() {
238             public boolean answer() throws Exception {
239                 return false;
240             }
241         }).when(mHalDeviceManager).start();
242         assertFalse(mWifiVendorHal.startVendorHal(true));
243         assertFalse(mWifiVendorHal.isHalStarted());
244 
245         verify(mHalDeviceManager).start();
246 
247         verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
248         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
249         verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
250         verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
251         verify(mIWifiStaIface, never())
252                 .registerEventCallback(any(IWifiStaIfaceEventCallback.class));
253     }
254 
255     /**
256      * Tests the failure to start HAL in STA mode using
257      * {@link WifiVendorHal#startVendorHal(boolean)}.
258      */
259     @Test
testStartHalFailureInIfaceCreationInStaMode()260     public void testStartHalFailureInIfaceCreationInStaMode() throws Exception {
261         when(mHalDeviceManager.createStaIface(eq(null), eq(null))).thenReturn(null);
262         assertFalse(mWifiVendorHal.startVendorHal(true));
263         assertFalse(mWifiVendorHal.isHalStarted());
264 
265         verify(mHalDeviceManager).start();
266         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
267         verify(mHalDeviceManager).stop();
268 
269         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
270         verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
271         verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
272         verify(mIWifiStaIface, never())
273                 .registerEventCallback(any(IWifiStaIfaceEventCallback.class));
274     }
275 
276     /**
277      * Tests the failure to start HAL in STA mode using
278      * {@link WifiVendorHal#startVendorHal(boolean)}.
279      */
280     @Test
testStartHalFailureInRttControllerCreationInStaMode()281     public void testStartHalFailureInRttControllerCreationInStaMode() throws Exception {
282         when(mHalDeviceManager.createRttController(any(IWifiIface.class))).thenReturn(null);
283         assertFalse(mWifiVendorHal.startVendorHal(true));
284         assertFalse(mWifiVendorHal.isHalStarted());
285 
286         verify(mHalDeviceManager).start();
287         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
288         verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
289         verify(mHalDeviceManager).stop();
290         verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
291 
292         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
293         verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
294     }
295 
296     /**
297      * Tests the failure to start HAL in STA mode using
298      * {@link WifiVendorHal#startVendorHal(boolean)}.
299      */
300     @Test
testStartHalFailureInChipGetInStaMode()301     public void testStartHalFailureInChipGetInStaMode() throws Exception {
302         when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null);
303         assertFalse(mWifiVendorHal.startVendorHal(true));
304         assertFalse(mWifiVendorHal.isHalStarted());
305 
306         verify(mHalDeviceManager).start();
307         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
308         verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
309         verify(mHalDeviceManager).getChip(any(IWifiIface.class));
310         verify(mHalDeviceManager).stop();
311         verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
312 
313         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
314     }
315 
316     /**
317      * Tests the failure to start HAL in STA mode using
318      * {@link WifiVendorHal#startVendorHal(boolean)}.
319      */
320     @Test
testStartHalFailureInStaIfaceCallbackRegistration()321     public void testStartHalFailureInStaIfaceCallbackRegistration() throws Exception {
322         when(mIWifiStaIface.registerEventCallback(any(IWifiStaIfaceEventCallback.class)))
323                 .thenReturn(mWifiStatusFailure);
324         assertFalse(mWifiVendorHal.startVendorHal(true));
325         assertFalse(mWifiVendorHal.isHalStarted());
326 
327         verify(mHalDeviceManager).start();
328         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
329         verify(mHalDeviceManager).stop();
330         verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
331 
332         verify(mHalDeviceManager, never()).createRttController(eq(mIWifiStaIface));
333         verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
334         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
335     }
336 
337     /**
338      * Tests the failure to start HAL in STA mode using
339      * {@link WifiVendorHal#startVendorHal(boolean)}.
340      */
341     @Test
testStartHalFailureInChipCallbackRegistration()342     public void testStartHalFailureInChipCallbackRegistration() throws Exception {
343         when(mIWifiChip.registerEventCallback(any(IWifiChipEventCallback.class)))
344                 .thenReturn(mWifiStatusFailure);
345         assertFalse(mWifiVendorHal.startVendorHal(true));
346         assertFalse(mWifiVendorHal.isHalStarted());
347 
348         verify(mHalDeviceManager).start();
349         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
350         verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
351         verify(mHalDeviceManager).getChip(any(IWifiIface.class));
352         verify(mHalDeviceManager).stop();
353         verify(mIWifiStaIface).registerEventCallback(any(IWifiStaIfaceEventCallback.class));
354         verify(mIWifiChip).registerEventCallback(any(IWifiChipEventCallback.class));
355 
356         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
357     }
358 
359     /**
360      * Tests the failure to start HAL in STA mode using
361      * {@link WifiVendorHal#startVendorHal(boolean)}.
362      */
363     @Test
testStartHalFailureInApMode()364     public void testStartHalFailureInApMode() throws Exception {
365         when(mHalDeviceManager.createApIface(eq(null), eq(null))).thenReturn(null);
366         assertFalse(mWifiVendorHal.startVendorHal(false));
367         assertFalse(mWifiVendorHal.isHalStarted());
368 
369         verify(mHalDeviceManager).start();
370         verify(mHalDeviceManager).createApIface(eq(null), eq(null));
371         verify(mHalDeviceManager).stop();
372 
373         verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
374         verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
375         verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
376     }
377 
378     /**
379      * Tests the stopping of HAL in STA mode using
380      * {@link WifiVendorHal#stopVendorHal()}.
381      */
382     @Test
testStopHalInStaMode()383     public void testStopHalInStaMode() {
384         assertTrue(mWifiVendorHal.startVendorHal(true));
385         assertTrue(mWifiVendorHal.isHalStarted());
386 
387         mWifiVendorHal.stopVendorHal();
388         assertFalse(mWifiVendorHal.isHalStarted());
389 
390         verify(mHalDeviceManager).start();
391         verify(mHalDeviceManager).stop();
392         verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
393         verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
394         verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
395         verify(mHalDeviceManager, times(2)).isReady();
396         verify(mHalDeviceManager, times(2)).isStarted();
397 
398         verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
399     }
400 
401     /**
402      * Tests the stopping of HAL in AP mode using
403      * {@link WifiVendorHal#stopVendorHal()}.
404      */
405     @Test
testStopHalInApMode()406     public void testStopHalInApMode() {
407         assertTrue(mWifiVendorHal.startVendorHal(false));
408         assertTrue(mWifiVendorHal.isHalStarted());
409 
410         mWifiVendorHal.stopVendorHal();
411         assertFalse(mWifiVendorHal.isHalStarted());
412 
413         verify(mHalDeviceManager).start();
414         verify(mHalDeviceManager).stop();
415         verify(mHalDeviceManager).createApIface(eq(null), eq(null));
416         verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
417         verify(mHalDeviceManager, times(2)).isReady();
418         verify(mHalDeviceManager, times(2)).isStarted();
419 
420         verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
421         verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
422     }
423 
424     /**
425      * Test that enter logs when verbose logging is enabled
426      */
427     @Test
testEnterLogging()428     public void testEnterLogging() {
429         mWifiVendorHal.mLog = spy(mWifiLog);
430         mWifiVendorHal.enableVerboseLogging(true);
431         mWifiVendorHal.installPacketFilter(new byte[0]);
432         verify(mWifiVendorHal.mLog).trace(eq("% filter length %"));
433     }
434 
435     /**
436      * Test that enter does not log when verbose logging is not enabled
437      */
438     @Test
testEnterSilenceWhenNotEnabled()439     public void testEnterSilenceWhenNotEnabled() {
440         mWifiVendorHal.mLog = spy(mWifiLog);
441         mWifiVendorHal.installPacketFilter(new byte[0]);
442         mWifiVendorHal.enableVerboseLogging(true);
443         mWifiVendorHal.enableVerboseLogging(false);
444         mWifiVendorHal.installPacketFilter(new byte[0]);
445         verify(mWifiVendorHal.mLog, never()).trace(eq("% filter length %"));
446     }
447 
448     /**
449      * Test that boolResult logs a false result
450      */
451     @Test
testBoolResultFalse()452     public void testBoolResultFalse() {
453         mWifiLog = spy(mWifiLog);
454         mWifiVendorHal.mLog = mWifiLog;
455         mWifiVendorHal.mVerboseLog = mWifiLog;
456         assertFalse(mWifiVendorHal.getBgScanCapabilities(new WifiNative.ScanCapabilities()));
457         verify(mWifiLog).err("% returns %");
458     }
459 
460     /**
461      * Test that getBgScanCapabilities is hooked up to the HAL correctly
462      *
463      * A call before the vendor HAL is started should return a non-null result with version 0
464      *
465      * A call after the HAL is started should return the mocked values.
466      */
467     @Test
testGetBgScanCapabilities()468     public void testGetBgScanCapabilities() throws Exception {
469         StaBackgroundScanCapabilities capabilities = new StaBackgroundScanCapabilities();
470         capabilities.maxCacheSize = 12;
471         capabilities.maxBuckets = 34;
472         capabilities.maxApCachePerScan = 56;
473         capabilities.maxReportingThreshold = 78;
474 
475         doAnswer(new AnswerWithArguments() {
476             public void answer(IWifiStaIface.getBackgroundScanCapabilitiesCallback cb)
477                     throws RemoteException {
478                 cb.onValues(mWifiStatusSuccess, capabilities);
479             }
480         }).when(mIWifiStaIface).getBackgroundScanCapabilities(any(
481                 IWifiStaIface.getBackgroundScanCapabilitiesCallback.class));
482 
483         WifiNative.ScanCapabilities result = new WifiNative.ScanCapabilities();
484 
485         assertFalse(mWifiVendorHal.getBgScanCapabilities(result));  // should fail - not started
486         assertTrue(mWifiVendorHal.startVendorHalSta());           // Start the vendor hal
487         assertTrue(mWifiVendorHal.getBgScanCapabilities(result));   // should succeed
488 
489         assertEquals(12, result.max_scan_cache_size);
490         assertEquals(34, result.max_scan_buckets);
491         assertEquals(56, result.max_ap_cache_per_scan);
492         assertEquals(78, result.max_scan_reporting_threshold);
493     }
494 
setupValidFrequenciesForBand(ArrayList<Integer> frequencies)495     private void setupValidFrequenciesForBand(ArrayList<Integer> frequencies) throws Exception {
496 
497         doAnswer(new AnswerWithArguments() {
498             public void answer(int band, IWifiStaIface.getValidFrequenciesForBandCallback cb)
499                     throws RemoteException {
500                 cb.onValues(mWifiStatusSuccess, frequencies);
501             }
502         }).when(mIWifiStaIface).getValidFrequenciesForBand(anyInt(), any(
503                 IWifiStaIface.getValidFrequenciesForBandCallback.class));
504 
505         doAnswer(new AnswerWithArguments() {
506             public void answer(int band, IWifiApIface.getValidFrequenciesForBandCallback cb)
507                     throws RemoteException {
508                 cb.onValues(mWifiStatusSuccess, frequencies);
509             }
510         }).when(mIWifiApIface).getValidFrequenciesForBand(anyInt(), any(
511                 IWifiApIface.getValidFrequenciesForBandCallback.class));
512 
513     }
514 
intArrayFromArrayList(ArrayList<Integer> in)515     private int[] intArrayFromArrayList(ArrayList<Integer> in) {
516         int[] ans = new int[in.size()];
517         int i = 0;
518         for (Integer e : in) ans[i++] = e;
519         return ans;
520     }
521 
522     /**
523      * Test that isGetChannelsForBandSupported works in STA mode
524      */
525     @Test
testGetChannelsForBandSupportedSta()526     public void testGetChannelsForBandSupportedSta() throws Exception {
527         ArrayList<Integer> freq = new ArrayList<>();
528         freq.add(2405);
529 
530         setupValidFrequenciesForBand(freq);
531 
532         assertFalse(mWifiVendorHal.isGetChannelsForBandSupported());
533 
534         assertTrue(mWifiVendorHal.startVendorHalSta());
535 
536         assertTrue(mWifiVendorHal.isGetChannelsForBandSupported());
537     }
538 
539     /**
540      * Test that isGetChannelsForBandSupported works in AP mode
541      */
542     @Test
testGetChannelsForBandSupportedAp()543     public void testGetChannelsForBandSupportedAp() throws Exception {
544         ArrayList<Integer> freq = new ArrayList<>();
545         freq.add(2405);
546 
547         setupValidFrequenciesForBand(freq);
548 
549         assertFalse(mWifiVendorHal.isGetChannelsForBandSupported());
550 
551         assertTrue(mWifiVendorHal.startVendorHalAp());
552 
553         assertTrue(mWifiVendorHal.isGetChannelsForBandSupported());
554     }
555 
556     /**
557      * Test translation to WifiManager.WIFI_FEATURE_*
558      *
559      * Just do a spot-check with a few feature bits here; since the code is table-
560      * driven we don't have to work hard to exercise all of it.
561      */
562     @Test
testFeatureMaskTranslation()563     public void testFeatureMaskTranslation() {
564         int caps = (
565                 IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
566                 | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
567             );
568         int expected = (
569                 WifiManager.WIFI_FEATURE_SCANNER
570                 | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
571         assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps));
572     }
573 
574     /**
575      * Test enablement of link layer stats after startup
576      *
577      * Request link layer stats before HAL start
578      * - should not make it to the HAL layer
579      * Start the HAL in STA mode
580      * Request link layer stats twice more
581      * - enable request should make it to the HAL layer
582      * - HAL layer should have been called to make the requests (i.e., two calls total)
583      */
584     @Test
testLinkLayerStatsEnableAfterStartup()585     public void testLinkLayerStatsEnableAfterStartup() throws Exception {
586         doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
587 
588         assertNull(mWifiVendorHal.getWifiLinkLayerStats());
589         assertTrue(mWifiVendorHal.startVendorHalSta());
590         assertTrue(mWifiVendorHal.isHalStarted());
591 
592         verify(mHalDeviceManager).start();
593         mWifiVendorHal.getWifiLinkLayerStats();
594         mWifiVendorHal.getWifiLinkLayerStats();
595         verify(mIWifiStaIface).enableLinkLayerStatsCollection(false); // mLinkLayerStatsDebug
596         verify(mIWifiStaIface, times(2)).getLinkLayerStats(any());
597     }
598 
599     /**
600      * Test that link layer stats are not enabled and harmless in AP mode
601      *
602      * Start the HAL in AP mode
603      * - stats should not be enabled
604      * Request link layer stats
605      * - HAL layer should have been called to make the request
606      */
607     @Test
testLinkLayerStatsNotEnabledAndHarmlessInApMode()608     public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception {
609         doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
610 
611         assertTrue(mWifiVendorHal.startVendorHalAp());
612         assertTrue(mWifiVendorHal.isHalStarted());
613         assertNull(mWifiVendorHal.getWifiLinkLayerStats());
614 
615         verify(mHalDeviceManager).start();
616 
617         verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false);
618         verify(mIWifiStaIface, never()).getLinkLayerStats(any());
619     }
620 
621     /**
622      * Test that the link layer stats fields are populated correctly.
623      *
624      * This is done by filling with random values and then using toString on the
625      * original and converted values, comparing just the numerics in the result.
626      * This makes the assumption that the fields are in the same order in both string
627      * representations, which is not quite true. So apply some fixups before the final
628      * comparison.
629      */
630     @Test
testLinkLayerStatsAssignment()631     public void testLinkLayerStatsAssignment() throws Exception {
632         Random r = new Random(1775968256);
633         StaLinkLayerStats stats = new StaLinkLayerStats();
634         randomizePacketStats(r, stats.iface.wmeBePktStats);
635         randomizePacketStats(r, stats.iface.wmeBkPktStats);
636         randomizePacketStats(r, stats.iface.wmeViPktStats);
637         randomizePacketStats(r, stats.iface.wmeVoPktStats);
638         randomizeRadioStats(r, stats.radios);
639 
640         stats.timeStampInMs = 42; // currently dropped in conversion
641 
642         String expected = numbersOnly(stats.toString());
643 
644         WifiLinkLayerStats converted = WifiVendorHal.frameworkFromHalLinkLayerStats(stats);
645 
646         String actual = numbersOnly(converted.toString());
647 
648         // Do the required fixups to the both expected and actual
649         expected = rmValue(expected, stats.radios.get(0).rxTimeInMs);
650         expected = rmValue(expected, stats.radios.get(0).onTimeInMsForScan);
651 
652         actual = rmValue(actual, stats.radios.get(0).rxTimeInMs);
653         actual = rmValue(actual, stats.radios.get(0).onTimeInMsForScan);
654         actual = actual + "42 ";
655 
656         // The remaining fields should agree
657         assertEquals(expected, actual);
658     }
659 
660     /** Just the digits with delimiting spaces, please */
numbersOnly(String s)661     private static String numbersOnly(String s) {
662         return s.replaceAll("[^0-9]+", " ");
663     }
664 
665     /** Remove the given value from the space-delimited string, or die trying. */
rmValue(String s, long value)666     private static String rmValue(String s, long value) throws Exception {
667         String ans = s.replaceAll(" " + value + " ", " ");
668         assertNotEquals(s, ans);
669         return ans;
670     }
671 
672     /**
673      * Populate packet stats with non-negative random values
674      */
randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats)675     private static void randomizePacketStats(Random r, StaLinkLayerIfacePacketStats pstats) {
676         pstats.rxMpdu = r.nextLong() & 0xFFFFFFFFFFL; // more than 32 bits
677         pstats.txMpdu = r.nextLong() & 0xFFFFFFFFFFL;
678         pstats.lostMpdu = r.nextLong() & 0xFFFFFFFFFFL;
679         pstats.retries = r.nextLong() & 0xFFFFFFFFFFL;
680     }
681 
682    /**
683      * Populate radio stats with non-negative random values
684      */
randomizeRadioStats(Random r, ArrayList<StaLinkLayerRadioStats> rstats)685     private static void randomizeRadioStats(Random r, ArrayList<StaLinkLayerRadioStats> rstats) {
686         StaLinkLayerRadioStats rstat = new StaLinkLayerRadioStats();
687         rstat.onTimeInMs = r.nextInt() & 0xFFFFFF;
688         rstat.txTimeInMs = r.nextInt() & 0xFFFFFF;
689         for (int i = 0; i < 4; i++) {
690             Integer v = r.nextInt() & 0xFFFFFF;
691             rstat.txTimeInMsPerLevel.add(v);
692         }
693         rstat.rxTimeInMs = r.nextInt() & 0xFFFFFF;
694         rstat.onTimeInMsForScan = r.nextInt() & 0xFFFFFF;
695         rstats.add(rstat);
696     }
697 
698     /**
699      * Test that getFirmwareVersion() and getDriverVersion() work
700      *
701      * Calls before the STA is started are expected to return null.
702      */
703     @Test
testVersionGetters()704     public void testVersionGetters() throws Exception {
705         String firmwareVersion = "fuzzy";
706         String driverVersion = "dizzy";
707         IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo();
708         chipDebugInfo.firmwareDescription = firmwareVersion;
709         chipDebugInfo.driverDescription = driverVersion;
710 
711         doAnswer(new AnswerWithArguments() {
712             public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException {
713                 cb.onValues(mWifiStatusSuccess, chipDebugInfo);
714             }
715         }).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class));
716 
717         assertNull(mWifiVendorHal.getFirmwareVersion());
718         assertNull(mWifiVendorHal.getDriverVersion());
719 
720         assertTrue(mWifiVendorHal.startVendorHalSta());
721 
722         assertEquals(firmwareVersion, mWifiVendorHal.getFirmwareVersion());
723         assertEquals(driverVersion, mWifiVendorHal.getDriverVersion());
724     }
725 
726     /**
727      * For checkRoundTripIntTranslation lambdas
728      */
729     interface IntForInt {
translate(int value)730         int translate(int value);
731     }
732 
733     /**
734      * Checks that translation from x to y and back again is the identity function
735      *
736      * @param xFromY reverse translator
737      * @param yFromX forward translator
738      * @param xLimit non-inclusive upper bound on x (lower bound is zero)
739      */
checkRoundTripIntTranslation( IntForInt xFromY, IntForInt yFromX, int xFirst, int xLimit)740     private void checkRoundTripIntTranslation(
741             IntForInt xFromY, IntForInt yFromX, int xFirst, int xLimit) throws Exception {
742         int ex = 0;
743         for (int i = xFirst; i < xLimit; i++) {
744             assertEquals(i, xFromY.translate(yFromX.translate(i)));
745         }
746         try {
747             yFromX.translate(xLimit);
748             assertTrue("expected an exception here", false);
749         } catch (IllegalArgumentException e) {
750             ex++;
751         }
752         try {
753             xFromY.translate(yFromX.translate(xLimit - 1) + 1);
754             assertTrue("expected an exception here", false);
755         } catch (IllegalArgumentException e) {
756             ex++;
757         }
758         assertEquals(2, ex);
759     }
760 
761 
762     /**
763      * Test translations of RTT type
764      */
765     @Test
testRttTypeTranslation()766     public void testRttTypeTranslation() throws Exception {
767         checkRoundTripIntTranslation(
768                 (y) -> WifiVendorHal.halRttTypeFromFrameworkRttType(y),
769                 (x) -> WifiVendorHal.frameworkRttTypeFromHalRttType(x),
770                 1, 3);
771     }
772 
773     /**
774      * Test translations of peer type
775      */
776     @Test
testPeerTranslation()777     public void testPeerTranslation() throws Exception {
778         checkRoundTripIntTranslation(
779                 (y) -> WifiVendorHal.halPeerFromFrameworkPeer(y),
780                 (x) -> WifiVendorHal.frameworkPeerFromHalPeer(x),
781                 1, 6);
782     }
783 
784     /**
785      * Test translations of channel width
786      */
787     @Test
testChannelWidth()788     public void testChannelWidth() throws Exception {
789         checkRoundTripIntTranslation(
790                 (y) -> WifiVendorHal.halChannelWidthFromFrameworkChannelWidth(y),
791                 (x) -> WifiVendorHal.frameworkChannelWidthFromHalChannelWidth(x),
792                 0, 5);
793     }
794 
795     /**
796      * Test translations of preamble type mask
797      */
798     @Test
testPreambleTranslation()799     public void testPreambleTranslation() throws Exception {
800         checkRoundTripIntTranslation(
801                 (y) -> WifiVendorHal.halPreambleFromFrameworkPreamble(y),
802                 (x) -> WifiVendorHal.frameworkPreambleFromHalPreamble(x),
803                 0, 8);
804     }
805 
806     /**
807      * Test translations of bandwidth mask
808      */
809     @Test
testBandwidthTranslations()810     public void testBandwidthTranslations() throws Exception {
811         checkRoundTripIntTranslation(
812                 (y) -> WifiVendorHal.halBwFromFrameworkBw(y),
813                 (x) -> WifiVendorHal.frameworkBwFromHalBw(x),
814                 0, 64);
815     }
816 
817     @Test
testGetRttStuff()818     public void testGetRttStuff() throws Exception {
819         RttManager.RttParams params = new RttManager.RttParams();
820         //TODO(b/34901744) populate
821         RttConfig config = WifiVendorHal.halRttConfigFromFrameworkRttParams(params);
822         //TODO(b/34901744) check
823     }
824 
825     @Test
testGetRttCapabilities()826     public void testGetRttCapabilities() throws Exception {
827         RttCapabilities capabilities = new RttCapabilities();
828         //TODO(b/34901744) populate
829 
830         doAnswer(new AnswerWithArguments() {
831             public void answer(IWifiRttController.getCapabilitiesCallback cb)
832                     throws RemoteException {
833                 cb.onValues(mWifiStatusSuccess, capabilities);
834             }
835         }).when(mIWifiRttController).getCapabilities(any(
836                 IWifiRttController.getCapabilitiesCallback.class));
837 
838         assertNull(mWifiVendorHal.getRttCapabilities());
839 
840         assertTrue(mWifiVendorHal.startVendorHalSta());
841 
842         RttManager.RttCapabilities actual = mWifiVendorHal.getRttCapabilities();
843         //TODO(b/34901744) check
844 
845     }
846 
847     //TODO(b/34901744) negative RTT test cases as well.
848     // e.g. invoke RTT without putting the HAL in the correct mode.
849 
850     /**
851      * Test that setScanningMacOui is hooked up to the HAL correctly
852      */
853     @Test
testSetScanningMacOui()854     public void testSetScanningMacOui() throws Exception {
855         byte[] oui = NativeUtil.macAddressOuiToByteArray("DA:A1:19");
856         byte[] zzz = NativeUtil.macAddressOuiToByteArray("00:00:00");
857 
858         when(mIWifiStaIface.setScanningMacOui(any())).thenReturn(mWifiStatusSuccess);
859 
860         assertFalse(mWifiVendorHal.setScanningMacOui(oui)); // expect fail - STA not started
861         assertTrue(mWifiVendorHal.startVendorHalSta());
862         assertFalse(mWifiVendorHal.setScanningMacOui(null));  // expect fail - null
863         assertFalse(mWifiVendorHal.setScanningMacOui(new byte[]{(byte) 1})); // expect fail - len
864         assertTrue(mWifiVendorHal.setScanningMacOui(oui));
865         assertTrue(mWifiVendorHal.setScanningMacOui(zzz));
866 
867         verify(mIWifiStaIface).setScanningMacOui(eq(oui));
868         verify(mIWifiStaIface).setScanningMacOui(eq(zzz));
869     }
870 
871     @Test
testStartSendingOffloadedPacket()872     public void testStartSendingOffloadedPacket() throws Exception {
873         byte[] srcMac = NativeUtil.macAddressToByteArray("4007b2088c81");
874         InetAddress src = InetAddress.parseNumericAddress("192.168.13.13");
875         InetAddress dst = InetAddress.parseNumericAddress("93.184.216.34");
876         int slot = 13;
877         int millis = 16000;
878 
879         KeepalivePacketData kap = KeepalivePacketData.nattKeepalivePacket(src, 63000, dst, 4500);
880 
881         when(mIWifiStaIface.startSendingKeepAlivePackets(
882                 anyInt(), any(), anyShort(), any(), any(), anyInt()
883         )).thenReturn(mWifiStatusSuccess);
884 
885         assertTrue(mWifiVendorHal.startVendorHalSta());
886         assertTrue(0 == mWifiVendorHal.startSendingOffloadedPacket(slot, srcMac, kap, millis));
887 
888         verify(mIWifiStaIface).startSendingKeepAlivePackets(
889                 eq(slot), any(), anyShort(), any(), any(), eq(millis));
890     }
891 
892     @Test
testStopSendingOffloadedPacket()893     public void testStopSendingOffloadedPacket() throws Exception {
894         int slot = 13;
895 
896         when(mIWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(mWifiStatusSuccess);
897 
898         assertTrue(mWifiVendorHal.startVendorHalSta());
899         assertTrue(0 == mWifiVendorHal.stopSendingOffloadedPacket(slot));
900 
901         verify(mIWifiStaIface).stopSendingKeepAlivePackets(eq(slot));
902     }
903 
904     /**
905      * Test the setup, invocation, and removal of a RSSI event handler
906      *
907      */
908     @Test
testRssiMonitoring()909     public void testRssiMonitoring() throws Exception {
910         when(mIWifiStaIface.startRssiMonitoring(anyInt(), anyInt(), anyInt()))
911                 .thenReturn(mWifiStatusSuccess);
912         when(mIWifiStaIface.stopRssiMonitoring(anyInt()))
913                 .thenReturn(mWifiStatusSuccess);
914 
915         ArrayList<Byte> breach = new ArrayList<>(10);
916         byte hi = -21;
917         byte med = -42;
918         byte lo = -84;
919         Byte lower = -88;
920         WifiNative.WifiRssiEventHandler handler;
921         handler = ((cur) -> {
922             breach.add(cur);
923         });
924         assertEquals(-1, mWifiVendorHal.startRssiMonitoring(hi, lo, handler)); // not started
925         assertEquals(-1, mWifiVendorHal.stopRssiMonitoring()); // not started
926         assertTrue(mWifiVendorHal.startVendorHalSta());
927         assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
928         int theCmdId = mWifiVendorHal.sRssiMonCmdId;
929         breach.clear();
930         mIWifiStaIfaceEventCallback.onRssiThresholdBreached(theCmdId, new byte[6], lower);
931         assertEquals(breach.get(0), lower);
932         assertEquals(0, mWifiVendorHal.stopRssiMonitoring());
933         assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
934         assertEquals(0, mWifiVendorHal.startRssiMonitoring(med, lo, handler)); // replacing works
935         assertEquals(-1, mWifiVendorHal.startRssiMonitoring(hi, lo, null)); // null handler fails
936         assertEquals(0, mWifiVendorHal.startRssiMonitoring(hi, lo, handler));
937         assertEquals(-1, mWifiVendorHal.startRssiMonitoring(lo, hi, handler)); // empty range
938     }
939 
940     /**
941      * Test that getApfCapabilities is hooked up to the HAL correctly
942      *
943      * A call before the vendor HAL is started should return a non-null result with version 0
944      *
945      * A call after the HAL is started should return the mocked values.
946      */
947     @Test
testApfCapabilities()948     public void testApfCapabilities() throws Exception {
949         int myVersion = 33;
950         int myMaxSize = 1234;
951 
952         StaApfPacketFilterCapabilities capabilities = new StaApfPacketFilterCapabilities();
953         capabilities.version = myVersion;
954         capabilities.maxLength = myMaxSize;
955 
956         doAnswer(new AnswerWithArguments() {
957             public void answer(IWifiStaIface.getApfPacketFilterCapabilitiesCallback cb)
958                     throws RemoteException {
959                 cb.onValues(mWifiStatusSuccess, capabilities);
960             }
961         }).when(mIWifiStaIface).getApfPacketFilterCapabilities(any(
962                 IWifiStaIface.getApfPacketFilterCapabilitiesCallback.class));
963 
964 
965         assertEquals(0, mWifiVendorHal.getApfCapabilities().apfVersionSupported);
966 
967         assertTrue(mWifiVendorHal.startVendorHalSta());
968 
969         ApfCapabilities actual = mWifiVendorHal.getApfCapabilities();
970 
971         assertEquals(myVersion, actual.apfVersionSupported);
972         assertEquals(myMaxSize, actual.maximumApfProgramSize);
973         assertEquals(android.system.OsConstants.ARPHRD_ETHER, actual.apfPacketFormat);
974         assertNotEquals(0, actual.apfPacketFormat);
975     }
976 
977     /**
978      * Test that an APF program can be installed.
979      */
980     @Test
testInstallApf()981     public void testInstallApf() throws Exception {
982         byte[] filter = new byte[] {19, 53, 10};
983 
984         ArrayList<Byte> expected = new ArrayList<>(3);
985         for (byte b : filter) expected.add(b);
986 
987         when(mIWifiStaIface.installApfPacketFilter(anyInt(), any(ArrayList.class)))
988                 .thenReturn(mWifiStatusSuccess);
989 
990         assertTrue(mWifiVendorHal.startVendorHalSta());
991         assertTrue(mWifiVendorHal.installPacketFilter(filter));
992 
993         verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected));
994     }
995 
996     /**
997      * Test that the country code is set in AP mode (when it should be).
998      */
999     @Test
testSetCountryCodeHal()1000     public void testSetCountryCodeHal() throws Exception {
1001         byte[] expected = new byte[]{(byte) 'C', (byte) 'A'};
1002 
1003         when(mIWifiApIface.setCountryCode(any()))
1004                 .thenReturn(mWifiStatusSuccess);
1005 
1006         assertTrue(mWifiVendorHal.startVendorHalAp());
1007 
1008         assertFalse(mWifiVendorHal.setCountryCodeHal(null));
1009         assertFalse(mWifiVendorHal.setCountryCodeHal(""));
1010         assertFalse(mWifiVendorHal.setCountryCodeHal("A"));
1011         assertTrue(mWifiVendorHal.setCountryCodeHal("CA")); // Only one expected to succeed
1012         assertFalse(mWifiVendorHal.setCountryCodeHal("ZZZ"));
1013 
1014         verify(mIWifiApIface).setCountryCode(eq(expected));
1015     }
1016 
1017     /**
1018      * Test that RemoteException is caught and logged.
1019      */
1020     @Test
testRemoteExceptionIsHandled()1021     public void testRemoteExceptionIsHandled() throws Exception {
1022         mWifiLog = spy(mWifiLog);
1023         mWifiVendorHal.mVerboseLog = mWifiLog;
1024         when(mIWifiApIface.setCountryCode(any()))
1025                 .thenThrow(new RemoteException("oops"));
1026         assertTrue(mWifiVendorHal.startVendorHalAp());
1027         assertFalse(mWifiVendorHal.setCountryCodeHal("CA"));
1028         assertFalse(mWifiVendorHal.isHalStarted());
1029         verify(mWifiLog).err(any());
1030     }
1031 
1032     /**
1033      * Test that startLoggingToDebugRingBuffer is plumbed to chip
1034      *
1035      * A call before the vendor hal is started should just return false.
1036      * After starting in STA mode, the call should succeed, and pass ther right things down.
1037      */
1038     @Test
testStartLoggingRingBuffer()1039     public void testStartLoggingRingBuffer() throws Exception {
1040         when(mIWifiChip.startLoggingToDebugRingBuffer(
1041                 any(String.class), anyInt(), anyInt(), anyInt()
1042         )).thenReturn(mWifiStatusSuccess);
1043 
1044         assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
1045         assertTrue(mWifiVendorHal.startVendorHalSta());
1046         assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
1047 
1048         verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
1049     }
1050 
1051     /**
1052      * Same test as testStartLoggingRingBuffer, but in AP mode rather than STA.
1053      */
1054     @Test
testStartLoggingRingBufferOnAp()1055     public void testStartLoggingRingBufferOnAp() throws Exception {
1056         when(mIWifiChip.startLoggingToDebugRingBuffer(
1057                 any(String.class), anyInt(), anyInt(), anyInt()
1058         )).thenReturn(mWifiStatusSuccess);
1059 
1060         assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
1061         assertTrue(mWifiVendorHal.startVendorHalAp());
1062         assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
1063 
1064         verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
1065     }
1066 
1067     /**
1068      * Test that getRingBufferStatus gets and translates its stuff correctly
1069      */
1070     @Test
testRingBufferStatus()1071     public void testRingBufferStatus() throws Exception {
1072         WifiDebugRingBufferStatus one = new WifiDebugRingBufferStatus();
1073         one.ringName = "One";
1074         one.flags = WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES;
1075         one.ringId = 5607371;
1076         one.sizeInBytes = 54321;
1077         one.freeSizeInBytes = 42;
1078         one.verboseLevel = WifiDebugRingBufferVerboseLevel.VERBOSE;
1079         String oneExpect = "name: One flag: 1 ringBufferId: 5607371 ringBufferByteSize: 54321"
1080                 + " verboseLevel: 2 writtenBytes: 0 readBytes: 0 writtenRecords: 0";
1081 
1082         WifiDebugRingBufferStatus two = new WifiDebugRingBufferStatus();
1083         two.ringName = "Two";
1084         two.flags = WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES
1085                 | WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES;
1086         two.ringId = 4512470;
1087         two.sizeInBytes = 300;
1088         two.freeSizeInBytes = 42;
1089         two.verboseLevel = WifiDebugRingBufferVerboseLevel.DEFAULT;
1090 
1091         ArrayList<WifiDebugRingBufferStatus> halBufferStatus = new ArrayList<>(2);
1092         halBufferStatus.add(one);
1093         halBufferStatus.add(two);
1094 
1095         WifiNative.RingBufferStatus[] actual;
1096 
1097         doAnswer(new AnswerWithArguments() {
1098             public void answer(IWifiChip.getDebugRingBuffersStatusCallback cb)
1099                     throws RemoteException {
1100                 cb.onValues(mWifiStatusSuccess, halBufferStatus);
1101             }
1102         }).when(mIWifiChip).getDebugRingBuffersStatus(any(
1103                 IWifiChip.getDebugRingBuffersStatusCallback.class));
1104 
1105         assertTrue(mWifiVendorHal.startVendorHalSta());
1106         actual = mWifiVendorHal.getRingBufferStatus();
1107 
1108         assertEquals(halBufferStatus.size(), actual.length);
1109         assertEquals(oneExpect, actual[0].toString());
1110         assertEquals(two.ringId, actual[1].ringBufferId);
1111 
1112     }
1113 
1114     /**
1115      * Test that getRingBufferData calls forceDumpToDebugRingBuffer
1116      *
1117      * Try once before hal start, and twice after (one success, one failure).
1118      */
1119     @Test
testForceRingBufferDump()1120     public void testForceRingBufferDump() throws Exception {
1121         when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(mWifiStatusSuccess);
1122         when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(mWifiStatusFailure);
1123 
1124         assertFalse(mWifiVendorHal.getRingBufferData("Gunk")); // hal not started
1125 
1126         assertTrue(mWifiVendorHal.startVendorHalSta());
1127 
1128         assertTrue(mWifiVendorHal.getRingBufferData("Gunk")); // mocked call succeeds
1129         assertFalse(mWifiVendorHal.getRingBufferData("Glop")); // mocked call fails
1130 
1131         verify(mIWifiChip).forceDumpToDebugRingBuffer("Gunk");
1132         verify(mIWifiChip).forceDumpToDebugRingBuffer("Glop");
1133     }
1134 
1135     /**
1136      * Tests the start of packet fate monitoring.
1137      *
1138      * Try once before hal start, and once after (one success, one failure).
1139      */
1140     @Test
testStartPktFateMonitoring()1141     public void testStartPktFateMonitoring() throws Exception {
1142         when(mIWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(mWifiStatusSuccess);
1143 
1144         assertFalse(mWifiVendorHal.startPktFateMonitoring());
1145         verify(mIWifiStaIface, never()).startDebugPacketFateMonitoring();
1146 
1147         assertTrue(mWifiVendorHal.startVendorHalSta());
1148         assertTrue(mWifiVendorHal.startPktFateMonitoring());
1149         verify(mIWifiStaIface).startDebugPacketFateMonitoring();
1150     }
1151 
1152     /**
1153      * Tests the retrieval of tx packet fates.
1154      *
1155      * Try once before hal start, and once after.
1156      */
1157     @Test
testGetTxPktFates()1158     public void testGetTxPktFates() throws Exception {
1159         byte[] frameContentBytes = new byte[30];
1160         new Random().nextBytes(frameContentBytes);
1161         WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
1162         fateReport.fate = WifiDebugTxPacketFate.DRV_QUEUED;
1163         fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
1164         fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
1165         fateReport.frameInfo.frameContent.addAll(
1166                 NativeUtil.byteArrayToArrayList(frameContentBytes));
1167 
1168         doAnswer(new AnswerWithArguments() {
1169             public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
1170                 cb.onValues(mWifiStatusSuccess,
1171                         new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(fateReport)));
1172             }
1173         }).when(mIWifiStaIface)
1174                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1175 
1176         WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
1177         assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
1178         verify(mIWifiStaIface, never())
1179                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1180 
1181         assertTrue(mWifiVendorHal.startVendorHalSta());
1182 
1183         assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
1184         verify(mIWifiStaIface)
1185                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1186         assertEquals(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, retrievedFates[0].mFate);
1187         assertEquals(fateReport.frameInfo.driverTimestampUsec,
1188                 retrievedFates[0].mDriverTimestampUSec);
1189         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
1190         assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
1191     }
1192 
1193     /**
1194      * Tests the retrieval of tx packet fates when the number of fates retrieved exceeds the
1195      * input array.
1196      *
1197      * Try once before hal start, and once after.
1198      */
1199     @Test
testGetTxPktFatesExceedsInputArrayLength()1200     public void testGetTxPktFatesExceedsInputArrayLength() throws Exception {
1201         byte[] frameContentBytes = new byte[30];
1202         new Random().nextBytes(frameContentBytes);
1203         WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
1204         fateReport.fate = WifiDebugTxPacketFate.FW_DROP_OTHER;
1205         fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
1206         fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
1207         fateReport.frameInfo.frameContent.addAll(
1208                 NativeUtil.byteArrayToArrayList(frameContentBytes));
1209 
1210         doAnswer(new AnswerWithArguments() {
1211             public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
1212                 cb.onValues(mWifiStatusSuccess,
1213                         new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(
1214                                 fateReport, fateReport)));
1215             }
1216         }).when(mIWifiStaIface)
1217                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1218 
1219         WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
1220         assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
1221         verify(mIWifiStaIface, never())
1222                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1223 
1224         assertTrue(mWifiVendorHal.startVendorHalSta());
1225 
1226         assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
1227         verify(mIWifiStaIface)
1228                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1229         assertEquals(WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, retrievedFates[0].mFate);
1230         assertEquals(fateReport.frameInfo.driverTimestampUsec,
1231                 retrievedFates[0].mDriverTimestampUSec);
1232         assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
1233         assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
1234     }
1235 
1236     /**
1237      * Tests the retrieval of rx packet fates.
1238      *
1239      * Try once before hal start, and once after.
1240      */
1241     @Test
testGetRxPktFates()1242     public void testGetRxPktFates() throws Exception {
1243         byte[] frameContentBytes = new byte[30];
1244         new Random().nextBytes(frameContentBytes);
1245         WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
1246         fateReport.fate = WifiDebugRxPacketFate.SUCCESS;
1247         fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
1248         fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
1249         fateReport.frameInfo.frameContent.addAll(
1250                 NativeUtil.byteArrayToArrayList(frameContentBytes));
1251 
1252         doAnswer(new AnswerWithArguments() {
1253             public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
1254                 cb.onValues(mWifiStatusSuccess,
1255                         new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(fateReport)));
1256             }
1257         }).when(mIWifiStaIface)
1258                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1259 
1260         WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
1261         assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
1262         verify(mIWifiStaIface, never())
1263                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1264 
1265         assertTrue(mWifiVendorHal.startVendorHalSta());
1266 
1267         assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
1268         verify(mIWifiStaIface)
1269                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1270         assertEquals(WifiLoggerHal.RX_PKT_FATE_SUCCESS, retrievedFates[0].mFate);
1271         assertEquals(fateReport.frameInfo.driverTimestampUsec,
1272                 retrievedFates[0].mDriverTimestampUSec);
1273         assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
1274         assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
1275     }
1276 
1277     /**
1278      * Tests the retrieval of rx packet fates when the number of fates retrieved exceeds the
1279      * input array.
1280      *
1281      * Try once before hal start, and once after.
1282      */
1283     @Test
testGetRxPktFatesExceedsInputArrayLength()1284     public void testGetRxPktFatesExceedsInputArrayLength() throws Exception {
1285         byte[] frameContentBytes = new byte[30];
1286         new Random().nextBytes(frameContentBytes);
1287         WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
1288         fateReport.fate = WifiDebugRxPacketFate.FW_DROP_FILTER;
1289         fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
1290         fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
1291         fateReport.frameInfo.frameContent.addAll(
1292                 NativeUtil.byteArrayToArrayList(frameContentBytes));
1293 
1294         doAnswer(new AnswerWithArguments() {
1295             public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
1296                 cb.onValues(mWifiStatusSuccess,
1297                         new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(
1298                                 fateReport, fateReport)));
1299             }
1300         }).when(mIWifiStaIface)
1301                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1302 
1303         WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
1304         assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
1305         verify(mIWifiStaIface, never())
1306                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1307 
1308         assertTrue(mWifiVendorHal.startVendorHalSta());
1309 
1310         assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
1311         verify(mIWifiStaIface)
1312                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1313         assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, retrievedFates[0].mFate);
1314         assertEquals(fateReport.frameInfo.driverTimestampUsec,
1315                 retrievedFates[0].mDriverTimestampUSec);
1316         assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
1317         assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
1318     }
1319 
1320     /**
1321      * Tests the failure to retrieve tx packet fates when the input array is empty.
1322      */
1323     @Test
testGetTxPktFatesEmptyInputArray()1324     public void testGetTxPktFatesEmptyInputArray() throws Exception {
1325         assertTrue(mWifiVendorHal.startVendorHalSta());
1326         assertFalse(mWifiVendorHal.getTxPktFates(new WifiNative.TxFateReport[0]));
1327         verify(mIWifiStaIface, never())
1328                 .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
1329     }
1330 
1331     /**
1332      * Tests the failure to retrieve rx packet fates when the input array is empty.
1333      */
1334     @Test
testGetRxPktFatesEmptyInputArray()1335     public void testGetRxPktFatesEmptyInputArray() throws Exception {
1336         assertTrue(mWifiVendorHal.startVendorHalSta());
1337         assertFalse(mWifiVendorHal.getRxPktFates(new WifiNative.RxFateReport[0]));
1338         verify(mIWifiStaIface, never())
1339                 .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
1340     }
1341 
1342     /**
1343      * Tests the nd offload enable/disable.
1344      */
1345     @Test
testEnableDisableNdOffload()1346     public void testEnableDisableNdOffload() throws Exception {
1347         when(mIWifiStaIface.enableNdOffload(anyBoolean())).thenReturn(mWifiStatusSuccess);
1348 
1349         assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
1350         verify(mIWifiStaIface, never()).enableNdOffload(anyBoolean());
1351 
1352         assertTrue(mWifiVendorHal.startVendorHalSta());
1353 
1354         assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
1355         verify(mIWifiStaIface).enableNdOffload(eq(true));
1356         assertTrue(mWifiVendorHal.configureNeighborDiscoveryOffload(false));
1357         verify(mIWifiStaIface).enableNdOffload(eq(false));
1358     }
1359 
1360     /**
1361      * Tests the nd offload enable failure.
1362      */
1363     @Test
testEnableNdOffloadFailure()1364     public void testEnableNdOffloadFailure() throws Exception {
1365         when(mIWifiStaIface.enableNdOffload(eq(true))).thenReturn(mWifiStatusFailure);
1366 
1367         assertTrue(mWifiVendorHal.startVendorHalSta());
1368 
1369         assertFalse(mWifiVendorHal.configureNeighborDiscoveryOffload(true));
1370         verify(mIWifiStaIface).enableNdOffload(eq(true));
1371     }
1372 
1373     /**
1374      * Tests the retrieval of wlan wake reason stats.
1375      */
1376     @Test
testGetWlanWakeReasonCount()1377     public void testGetWlanWakeReasonCount() throws Exception {
1378         WifiDebugHostWakeReasonStats stats = new WifiDebugHostWakeReasonStats();
1379         Random rand = new Random();
1380         stats.totalCmdEventWakeCnt = rand.nextInt();
1381         stats.totalDriverFwLocalWakeCnt = rand.nextInt();
1382         stats.totalRxPacketWakeCnt = rand.nextInt();
1383         stats.rxPktWakeDetails.rxUnicastCnt = rand.nextInt();
1384         stats.rxPktWakeDetails.rxMulticastCnt = rand.nextInt();
1385         stats.rxIcmpPkWakeDetails.icmpPkt = rand.nextInt();
1386         stats.rxIcmpPkWakeDetails.icmp6Pkt = rand.nextInt();
1387         stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt = rand.nextInt();
1388         stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt = rand.nextInt();
1389 
1390         doAnswer(new AnswerWithArguments() {
1391             public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) {
1392                 cb.onValues(mWifiStatusSuccess, stats);
1393             }
1394         }).when(mIWifiChip).getDebugHostWakeReasonStats(
1395                 any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
1396 
1397         assertNull(mWifiVendorHal.getWlanWakeReasonCount());
1398         verify(mIWifiChip, never())
1399                 .getDebugHostWakeReasonStats(
1400                         any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
1401 
1402         assertTrue(mWifiVendorHal.startVendorHalSta());
1403 
1404         WifiWakeReasonAndCounts retrievedStats = mWifiVendorHal.getWlanWakeReasonCount();
1405         verify(mIWifiChip).getDebugHostWakeReasonStats(
1406                 any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
1407         assertNotNull(retrievedStats);
1408         assertEquals(stats.totalCmdEventWakeCnt, retrievedStats.totalCmdEventWake);
1409         assertEquals(stats.totalDriverFwLocalWakeCnt, retrievedStats.totalDriverFwLocalWake);
1410         assertEquals(stats.totalRxPacketWakeCnt, retrievedStats.totalRxDataWake);
1411         assertEquals(stats.rxPktWakeDetails.rxUnicastCnt, retrievedStats.rxUnicast);
1412         assertEquals(stats.rxPktWakeDetails.rxMulticastCnt, retrievedStats.rxMulticast);
1413         assertEquals(stats.rxIcmpPkWakeDetails.icmpPkt, retrievedStats.icmp);
1414         assertEquals(stats.rxIcmpPkWakeDetails.icmp6Pkt, retrievedStats.icmp6);
1415         assertEquals(stats.rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt,
1416                 retrievedStats.ipv4RxMulticast);
1417         assertEquals(stats.rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt,
1418                 retrievedStats.ipv6Multicast);
1419     }
1420 
1421     /**
1422      * Tests the failure in retrieval of wlan wake reason stats.
1423      */
1424     @Test
testGetWlanWakeReasonCountFailure()1425     public void testGetWlanWakeReasonCountFailure() throws Exception {
1426         doAnswer(new AnswerWithArguments() {
1427             public void answer(IWifiChip.getDebugHostWakeReasonStatsCallback cb) {
1428                 cb.onValues(mWifiStatusFailure, new WifiDebugHostWakeReasonStats());
1429             }
1430         }).when(mIWifiChip).getDebugHostWakeReasonStats(
1431                 any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
1432 
1433         // This should work in both AP & STA mode.
1434         assertTrue(mWifiVendorHal.startVendorHalAp());
1435 
1436         assertNull(mWifiVendorHal.getWlanWakeReasonCount());
1437         verify(mIWifiChip).getDebugHostWakeReasonStats(
1438                 any(IWifiChip.getDebugHostWakeReasonStatsCallback.class));
1439     }
1440 
1441     /**
1442      * Test that getFwMemoryDump is properly plumbed
1443      */
1444     @Test
testGetFwMemoryDump()1445     public void testGetFwMemoryDump() throws Exception {
1446         byte [] sample = NativeUtil.hexStringToByteArray("268c7a3fbfa4661c0bdd6a36");
1447         ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample);
1448 
1449         doAnswer(new AnswerWithArguments() {
1450             public void answer(IWifiChip.requestFirmwareDebugDumpCallback cb)
1451                     throws RemoteException {
1452                 cb.onValues(mWifiStatusSuccess, halBlob);
1453             }
1454         }).when(mIWifiChip).requestFirmwareDebugDump(any(
1455                 IWifiChip.requestFirmwareDebugDumpCallback.class));
1456 
1457         assertTrue(mWifiVendorHal.startVendorHalSta());
1458         assertArrayEquals(sample, mWifiVendorHal.getFwMemoryDump());
1459     }
1460 
1461     /**
1462      * Test that getDriverStateDump is properly plumbed
1463      *
1464      * Just for variety, use AP mode here.
1465      */
1466     @Test
testGetDriverStateDump()1467     public void testGetDriverStateDump() throws Exception {
1468         byte [] sample = NativeUtil.hexStringToByteArray("e83ff543cf80083e6459d20f");
1469         ArrayList<Byte> halBlob = NativeUtil.byteArrayToArrayList(sample);
1470 
1471         doAnswer(new AnswerWithArguments() {
1472             public void answer(IWifiChip.requestDriverDebugDumpCallback cb)
1473                     throws RemoteException {
1474                 cb.onValues(mWifiStatusSuccess, halBlob);
1475             }
1476         }).when(mIWifiChip).requestDriverDebugDump(any(
1477                 IWifiChip.requestDriverDebugDumpCallback.class));
1478 
1479         assertTrue(mWifiVendorHal.startVendorHalAp());
1480         assertArrayEquals(sample, mWifiVendorHal.getDriverStateDump());
1481     }
1482 
1483     /**
1484      * Test that background scan failure is handled correctly.
1485      */
1486     @Test
testBgScanFailureCallback()1487     public void testBgScanFailureCallback() throws Exception {
1488         assertTrue(mWifiVendorHal.startVendorHalSta());
1489         assertNotNull(mIWifiStaIfaceEventCallback);
1490 
1491         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1492         startBgScan(eventHandler);
1493 
1494         mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId);
1495         verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_FAILED);
1496     }
1497 
1498     /**
1499      * Test that background scan failure with wrong id is not reported.
1500      */
1501     @Test
testBgScanFailureCallbackWithInvalidCmdId()1502     public void testBgScanFailureCallbackWithInvalidCmdId() throws Exception {
1503         assertTrue(mWifiVendorHal.startVendorHalSta());
1504         assertNotNull(mIWifiStaIfaceEventCallback);
1505 
1506         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1507         startBgScan(eventHandler);
1508 
1509         mIWifiStaIfaceEventCallback.onBackgroundScanFailure(mWifiVendorHal.mScan.cmdId + 1);
1510         verify(eventHandler, never()).onScanStatus(WifiNative.WIFI_SCAN_FAILED);
1511     }
1512 
1513     /**
1514      * Test that background scan full results are handled correctly.
1515      */
1516     @Test
testBgScanFullScanResults()1517     public void testBgScanFullScanResults() throws Exception {
1518         assertTrue(mWifiVendorHal.startVendorHalSta());
1519         assertNotNull(mIWifiStaIfaceEventCallback);
1520 
1521         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1522         startBgScan(eventHandler);
1523 
1524         Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult();
1525         mIWifiStaIfaceEventCallback.onBackgroundFullScanResult(
1526                 mWifiVendorHal.mScan.cmdId, 5, result.first);
1527 
1528         ArgumentCaptor<ScanResult> scanResultCaptor = ArgumentCaptor.forClass(ScanResult.class);
1529         verify(eventHandler).onFullScanResult(scanResultCaptor.capture(), eq(5));
1530 
1531         assertScanResultEqual(result.second, scanResultCaptor.getValue());
1532     }
1533 
1534     /**
1535      * Test that background scan results are handled correctly.
1536      */
1537     @Test
testBgScanScanResults()1538     public void testBgScanScanResults() throws Exception {
1539         assertTrue(mWifiVendorHal.startVendorHalSta());
1540         assertNotNull(mIWifiStaIfaceEventCallback);
1541 
1542         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1543         startBgScan(eventHandler);
1544 
1545         Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>> data =
1546                 createHidlAndFrameworkBgScanDatas();
1547         mIWifiStaIfaceEventCallback.onBackgroundScanResults(
1548                 mWifiVendorHal.mScan.cmdId, data.first);
1549 
1550         verify(eventHandler).onScanStatus(WifiNative.WIFI_SCAN_RESULTS_AVAILABLE);
1551         assertScanDatasEqual(
1552                 data.second, Arrays.asList(mWifiVendorHal.mScan.latestScanResults));
1553     }
1554 
1555     /**
1556      * Test that starting a new background scan when one is active will stop the previous one.
1557      */
1558     @Test
testBgScanReplacement()1559     public void testBgScanReplacement() throws Exception {
1560         when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
1561         assertTrue(mWifiVendorHal.startVendorHalSta());
1562         assertNotNull(mIWifiStaIfaceEventCallback);
1563         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1564         startBgScan(eventHandler);
1565         int cmdId1 = mWifiVendorHal.mScan.cmdId;
1566         startBgScan(eventHandler);
1567         assertNotEquals(mWifiVendorHal.mScan.cmdId, cmdId1);
1568         verify(mIWifiStaIface, times(2)).startBackgroundScan(anyInt(), any());
1569         verify(mIWifiStaIface).stopBackgroundScan(cmdId1);
1570     }
1571 
1572     /**
1573      * Test stopping a background scan.
1574      */
1575     @Test
testBgScanStop()1576     public void testBgScanStop() throws Exception {
1577         when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
1578         assertTrue(mWifiVendorHal.startVendorHalSta());
1579         assertNotNull(mIWifiStaIfaceEventCallback);
1580         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1581         startBgScan(eventHandler);
1582 
1583         int cmdId = mWifiVendorHal.mScan.cmdId;
1584 
1585         mWifiVendorHal.stopBgScan();
1586         mWifiVendorHal.stopBgScan(); // second call should not do anything
1587         verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once
1588     }
1589 
1590     /**
1591      * Test pausing and restarting a background scan.
1592      */
1593     @Test
testBgScanPauseAndRestart()1594     public void testBgScanPauseAndRestart() throws Exception {
1595         when(mIWifiStaIface.stopBackgroundScan(anyInt())).thenReturn(mWifiStatusSuccess);
1596         assertTrue(mWifiVendorHal.startVendorHalSta());
1597         assertNotNull(mIWifiStaIfaceEventCallback);
1598         WifiNative.ScanEventHandler eventHandler = mock(WifiNative.ScanEventHandler.class);
1599         startBgScan(eventHandler);
1600 
1601         int cmdId = mWifiVendorHal.mScan.cmdId;
1602 
1603         mWifiVendorHal.pauseBgScan();
1604         mWifiVendorHal.restartBgScan();
1605         verify(mIWifiStaIface).stopBackgroundScan(cmdId); // Should be called just once
1606         verify(mIWifiStaIface, times(2)).startBackgroundScan(eq(cmdId), any());
1607     }
1608 
1609     /**
1610      * Test the handling of log handler set.
1611      */
1612     @Test
testSetLogHandler()1613     public void testSetLogHandler() throws Exception {
1614         when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
1615 
1616         WifiNative.WifiLoggerEventHandler eventHandler =
1617                 mock(WifiNative.WifiLoggerEventHandler.class);
1618 
1619         assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler));
1620         verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
1621 
1622         assertTrue(mWifiVendorHal.startVendorHalSta());
1623 
1624         assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
1625         verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
1626         reset(mIWifiChip);
1627 
1628         // Second call should fail.
1629         assertFalse(mWifiVendorHal.setLoggingEventHandler(eventHandler));
1630         verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
1631     }
1632 
1633     /**
1634      * Test the handling of log handler reset.
1635      */
1636     @Test
testResetLogHandler()1637     public void testResetLogHandler() throws Exception {
1638         when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
1639         when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
1640 
1641         assertFalse(mWifiVendorHal.resetLogHandler());
1642         verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
1643         verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
1644 
1645         assertTrue(mWifiVendorHal.startVendorHalSta());
1646 
1647         // Not set, so this should fail.
1648         assertFalse(mWifiVendorHal.resetLogHandler());
1649         verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
1650         verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
1651 
1652         // Now set and then reset.
1653         assertTrue(mWifiVendorHal.setLoggingEventHandler(
1654                 mock(WifiNative.WifiLoggerEventHandler.class)));
1655         assertTrue(mWifiVendorHal.resetLogHandler());
1656         verify(mIWifiChip).enableDebugErrorAlerts(eq(false));
1657         verify(mIWifiChip).stopLoggingToDebugRingBuffer();
1658         reset(mIWifiChip);
1659 
1660         // Second reset should fail.
1661         assertFalse(mWifiVendorHal.resetLogHandler());
1662         verify(mIWifiChip, never()).enableDebugErrorAlerts(anyBoolean());
1663         verify(mIWifiChip, never()).stopLoggingToDebugRingBuffer();
1664     }
1665 
1666     /**
1667      * Test the handling of alert callback.
1668      */
1669     @Test
testAlertCallback()1670     public void testAlertCallback() throws Exception {
1671         when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
1672         when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
1673 
1674         assertTrue(mWifiVendorHal.startVendorHalSta());
1675         assertNotNull(mIWifiChipEventCallback);
1676 
1677         int errorCode = 5;
1678         byte[] errorData = new byte[45];
1679         new Random().nextBytes(errorData);
1680 
1681         // Randomly raise the HIDL callback before we register for the log callback.
1682         // This should be safely ignored. (Not trigger NPE.)
1683         mIWifiChipEventCallback.onDebugErrorAlert(
1684                 errorCode, NativeUtil.byteArrayToArrayList(errorData));
1685         mLooper.dispatchAll();
1686 
1687         WifiNative.WifiLoggerEventHandler eventHandler =
1688                 mock(WifiNative.WifiLoggerEventHandler.class);
1689         assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
1690         verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
1691 
1692         // Now raise the HIDL callback, this should be properly handled.
1693         mIWifiChipEventCallback.onDebugErrorAlert(
1694                 errorCode, NativeUtil.byteArrayToArrayList(errorData));
1695         mLooper.dispatchAll();
1696         verify(eventHandler).onWifiAlert(eq(errorCode), eq(errorData));
1697 
1698         // Now stop the logging and invoke the callback. This should be ignored.
1699         reset(eventHandler);
1700         assertTrue(mWifiVendorHal.resetLogHandler());
1701         mIWifiChipEventCallback.onDebugErrorAlert(
1702                 errorCode, NativeUtil.byteArrayToArrayList(errorData));
1703         mLooper.dispatchAll();
1704         verify(eventHandler, never()).onWifiAlert(anyInt(), anyObject());
1705     }
1706 
1707     /**
1708      * Test the handling of ring buffer callback.
1709      */
1710     @Test
testRingBufferDataCallback()1711     public void testRingBufferDataCallback() throws Exception {
1712         when(mIWifiChip.enableDebugErrorAlerts(anyBoolean())).thenReturn(mWifiStatusSuccess);
1713         when(mIWifiChip.stopLoggingToDebugRingBuffer()).thenReturn(mWifiStatusSuccess);
1714 
1715         assertTrue(mWifiVendorHal.startVendorHalSta());
1716         assertNotNull(mIWifiChipEventCallback);
1717 
1718         byte[] errorData = new byte[45];
1719         new Random().nextBytes(errorData);
1720 
1721         // Randomly raise the HIDL callback before we register for the log callback.
1722         // This should be safely ignored. (Not trigger NPE.)
1723         mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
1724                 new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
1725         mLooper.dispatchAll();
1726 
1727         WifiNative.WifiLoggerEventHandler eventHandler =
1728                 mock(WifiNative.WifiLoggerEventHandler.class);
1729         assertTrue(mWifiVendorHal.setLoggingEventHandler(eventHandler));
1730         verify(mIWifiChip).enableDebugErrorAlerts(eq(true));
1731 
1732         // Now raise the HIDL callback, this should be properly handled.
1733         mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
1734                 new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
1735         mLooper.dispatchAll();
1736         verify(eventHandler).onRingBufferData(
1737                 any(WifiNative.RingBufferStatus.class), eq(errorData));
1738 
1739         // Now stop the logging and invoke the callback. This should be ignored.
1740         reset(eventHandler);
1741         assertTrue(mWifiVendorHal.resetLogHandler());
1742         mIWifiChipEventCallback.onDebugRingBufferDataAvailable(
1743                 new WifiDebugRingBufferStatus(), NativeUtil.byteArrayToArrayList(errorData));
1744         mLooper.dispatchAll();
1745         verify(eventHandler, never()).onRingBufferData(anyObject(), anyObject());
1746     }
1747 
1748     /**
1749      * Test the handling of Vendor HAL death.
1750      */
1751     @Test
testVendorHalDeath()1752     public void testVendorHalDeath() {
1753         // Invoke the HAL device manager status callback with ready set to false to indicate the
1754         // death of the HAL.
1755         when(mHalDeviceManager.isReady()).thenReturn(false);
1756         mHalDeviceManagerStatusCallbacks.onStatusChanged();
1757 
1758         verify(mVendorHalDeathHandler).onDeath();
1759     }
1760 
startBgScan(WifiNative.ScanEventHandler eventHandler)1761     private void startBgScan(WifiNative.ScanEventHandler eventHandler) throws Exception {
1762         when(mIWifiStaIface.startBackgroundScan(
1763                 anyInt(), any(StaBackgroundScanParameters.class))).thenReturn(mWifiStatusSuccess);
1764         WifiNative.ScanSettings settings = new WifiNative.ScanSettings();
1765         settings.num_buckets = 1;
1766         WifiNative.BucketSettings bucketSettings = new WifiNative.BucketSettings();
1767         bucketSettings.bucket = 0;
1768         bucketSettings.period_ms = 16000;
1769         bucketSettings.report_events = WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN;
1770         settings.buckets = new WifiNative.BucketSettings[] {bucketSettings};
1771         assertTrue(mWifiVendorHal.startBgScan(settings, eventHandler));
1772     }
1773 
1774     // Create a pair of HIDL scan result and its corresponding framework scan result for
1775     // comparison.
createHidlAndFrameworkBgScanResult()1776     private Pair<StaScanResult, ScanResult> createHidlAndFrameworkBgScanResult() {
1777         StaScanResult staScanResult = new StaScanResult();
1778         Random random = new Random();
1779         byte[] ssid = new byte[8];
1780         random.nextBytes(ssid);
1781         staScanResult.ssid.addAll(NativeUtil.byteArrayToArrayList(ssid));
1782         random.nextBytes(staScanResult.bssid);
1783         staScanResult.frequency = 2432;
1784         staScanResult.rssi = -45;
1785         staScanResult.timeStampInUs = 5;
1786         WifiInformationElement ie1 = new WifiInformationElement();
1787         byte[] ie1_data = new byte[56];
1788         random.nextBytes(ie1_data);
1789         ie1.id = 1;
1790         ie1.data.addAll(NativeUtil.byteArrayToArrayList(ie1_data));
1791         staScanResult.informationElements.add(ie1);
1792 
1793         // Now create the corresponding Scan result structure.
1794         ScanResult scanResult = new ScanResult();
1795         scanResult.SSID = NativeUtil.encodeSsid(staScanResult.ssid);
1796         scanResult.BSSID = NativeUtil.macAddressFromByteArray(staScanResult.bssid);
1797         scanResult.wifiSsid = WifiSsid.createFromByteArray(ssid);
1798         scanResult.frequency = staScanResult.frequency;
1799         scanResult.level = staScanResult.rssi;
1800         scanResult.timestamp = staScanResult.timeStampInUs;
1801         scanResult.bytes = new byte[57];
1802         scanResult.bytes[0] = ie1.id;
1803         System.arraycopy(ie1_data, 0, scanResult.bytes, 1, ie1_data.length);
1804 
1805         return Pair.create(staScanResult, scanResult);
1806     }
1807 
1808     // Create a pair of HIDL scan datas and its corresponding framework scan datas for
1809     // comparison.
1810     private Pair<ArrayList<StaScanData>, ArrayList<WifiScanner.ScanData>>
createHidlAndFrameworkBgScanDatas()1811             createHidlAndFrameworkBgScanDatas() {
1812         ArrayList<StaScanData> staScanDatas = new ArrayList<>();
1813         StaScanData staScanData = new StaScanData();
1814 
1815         Pair<StaScanResult, ScanResult> result = createHidlAndFrameworkBgScanResult();
1816         staScanData.results.add(result.first);
1817         staScanData.bucketsScanned = 5;
1818         staScanData.flags = StaScanDataFlagMask.INTERRUPTED;
1819         staScanDatas.add(staScanData);
1820 
1821         ArrayList<WifiScanner.ScanData> scanDatas = new ArrayList<>();
1822         ScanResult[] scanResults = new ScanResult[1];
1823         scanResults[0] = result.second;
1824         WifiScanner.ScanData scanData =
1825                 new WifiScanner.ScanData(mWifiVendorHal.mScan.cmdId, 1,
1826                         staScanData.bucketsScanned, false, scanResults);
1827         scanDatas.add(scanData);
1828         return Pair.create(staScanDatas, scanDatas);
1829     }
1830 
assertScanResultEqual(ScanResult expected, ScanResult actual)1831     private void assertScanResultEqual(ScanResult expected, ScanResult actual) {
1832         assertEquals(expected.SSID, actual.SSID);
1833         assertEquals(expected.wifiSsid.getHexString(), actual.wifiSsid.getHexString());
1834         assertEquals(expected.BSSID, actual.BSSID);
1835         assertEquals(expected.frequency, actual.frequency);
1836         assertEquals(expected.level, actual.level);
1837         assertEquals(expected.timestamp, actual.timestamp);
1838         assertArrayEquals(expected.bytes, actual.bytes);
1839     }
1840 
assertScanResultsEqual(ScanResult[] expected, ScanResult[] actual)1841     private void assertScanResultsEqual(ScanResult[] expected, ScanResult[] actual) {
1842         assertEquals(expected.length, actual.length);
1843         for (int i = 0; i < expected.length; i++) {
1844             assertScanResultEqual(expected[i], actual[i]);
1845         }
1846     }
1847 
assertScanDataEqual(WifiScanner.ScanData expected, WifiScanner.ScanData actual)1848     private void assertScanDataEqual(WifiScanner.ScanData expected, WifiScanner.ScanData actual) {
1849         assertEquals(expected.getId(), actual.getId());
1850         assertEquals(expected.getFlags(), actual.getFlags());
1851         assertEquals(expected.getBucketsScanned(), actual.getBucketsScanned());
1852         assertScanResultsEqual(expected.getResults(), actual.getResults());
1853     }
1854 
assertScanDatasEqual( List<WifiScanner.ScanData> expected, List<WifiScanner.ScanData> actual)1855     private void assertScanDatasEqual(
1856             List<WifiScanner.ScanData> expected, List<WifiScanner.ScanData> actual) {
1857         assertEquals(expected.size(), actual.size());
1858         for (int i = 0; i < expected.size(); i++) {
1859             assertScanDataEqual(expected.get(i), actual.get(i));
1860         }
1861     }
1862 }
1863