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
17package com.android.server.wifi;
18import android.app.test.MockAnswerUtil.AnswerWithArguments;
19import android.hardware.wifi.V1_0.IWifiApIface;
20import android.hardware.wifi.V1_0.IWifiChip;
21import android.hardware.wifi.V1_0.IWifiChipEventCallback;
22import android.hardware.wifi.V1_0.IWifiIface;
23import android.hardware.wifi.V1_0.IWifiRttController;
24import android.hardware.wifi.V1_0.IWifiRttControllerEventCallback;
25import android.hardware.wifi.V1_0.IWifiStaIface;
26import android.hardware.wifi.V1_0.IWifiStaIfaceEventCallback;
27import android.hardware.wifi.V1_0.RttCapabilities;
28import android.hardware.wifi.V1_0.RttConfig;
29import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities;
30import android.hardware.wifi.V1_0.StaBackgroundScanCapabilities;
31import android.hardware.wifi.V1_0.StaBackgroundScanParameters;
32import android.hardware.wifi.V1_0.StaLinkLayerIfacePacketStats;
33import android.hardware.wifi.V1_0.StaLinkLayerRadioStats;
34import android.hardware.wifi.V1_0.StaLinkLayerStats;
35import android.hardware.wifi.V1_0.StaScanData;
36import android.hardware.wifi.V1_0.StaScanDataFlagMask;
37import android.hardware.wifi.V1_0.StaScanResult;
38import android.hardware.wifi.V1_0.WifiDebugHostWakeReasonStats;
39import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType;
40import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags;
41import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
42import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel;
43import android.hardware.wifi.V1_0.WifiDebugRxPacketFate;
44import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport;
45import android.hardware.wifi.V1_0.WifiDebugTxPacketFate;
46import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport;
47import android.hardware.wifi.V1_0.WifiInformationElement;
48import android.hardware.wifi.V1_0.WifiStatus;
49import android.hardware.wifi.V1_0.WifiStatusCode;
50import android.net.apf.ApfCapabilities;
51import android.net.wifi.RttManager;
52import android.net.wifi.ScanResult;
53import android.net.wifi.WifiLinkLayerStats;
54import android.net.wifi.WifiManager;
55import android.net.wifi.WifiScanner;
56import android.net.wifi.WifiSsid;
57import android.net.wifi.WifiWakeReasonAndCounts;
58import android.os.RemoteException;
59import android.os.test.TestLooper;
60import android.util.Pair;
61
62import com.android.server.connectivity.KeepalivePacketData;
63import com.android.server.wifi.util.NativeUtil;
64
65import static org.junit.Assert.*;
66import static org.mockito.Mockito.*;
67
68import org.junit.Before;
69import org.junit.Test;
70import org.mockito.ArgumentCaptor;
71import org.mockito.Mock;
72import org.mockito.MockitoAnnotations;
73import org.mockito.stubbing.Answer;
74
75import java.net.InetAddress;
76import java.util.ArrayList;
77import java.util.Arrays;
78import java.util.List;
79import java.util.Random;
80
81/**
82 * Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
83 */
84public 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     */
112    static Answer<WifiStatus> answerWifiStatus(Answer<WifiStatus> statusLambda) {
113        return (statusLambda);
114    }
115
116    /**
117     * Sets up for unit test
118     */
119    @Before
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */
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. */
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     */
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     */
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
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 {
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     */
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
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>>
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
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
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
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
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