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