WifiVendorHalTest.java revision 5a801ea1dd4da217cb2ea03ecfcfc02985e4f1df
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.IWifiIface;
23import android.hardware.wifi.V1_0.IWifiRttController;
24import android.hardware.wifi.V1_0.IWifiStaIface;
25import android.hardware.wifi.V1_0.StaApfPacketFilterCapabilities;
26import android.hardware.wifi.V1_0.WifiDebugPacketFateFrameType;
27import android.hardware.wifi.V1_0.WifiDebugRingBufferFlags;
28import android.hardware.wifi.V1_0.WifiDebugRingBufferStatus;
29import android.hardware.wifi.V1_0.WifiDebugRingBufferVerboseLevel;
30import android.hardware.wifi.V1_0.WifiDebugRxPacketFate;
31import android.hardware.wifi.V1_0.WifiDebugRxPacketFateReport;
32import android.hardware.wifi.V1_0.WifiDebugTxPacketFate;
33import android.hardware.wifi.V1_0.WifiDebugTxPacketFateReport;
34import android.hardware.wifi.V1_0.WifiStatus;
35import android.hardware.wifi.V1_0.WifiStatusCode;
36import android.net.apf.ApfCapabilities;
37import android.net.wifi.WifiManager;
38import android.os.HandlerThread;
39import android.os.Looper;
40import android.os.RemoteException;
41
42import com.android.server.connectivity.KeepalivePacketData;
43import com.android.server.wifi.util.NativeUtil;
44
45import static org.junit.Assert.*;
46import static org.mockito.Mockito.*;
47
48import org.junit.Before;
49import org.junit.Test;
50import org.mockito.ArgumentCaptor;
51import org.mockito.Mock;
52import org.mockito.MockitoAnnotations;
53
54import java.net.InetAddress;
55import java.util.ArrayList;
56import java.util.Arrays;
57import java.util.Random;
58
59/**
60 * Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
61 */
62public class WifiVendorHalTest {
63
64    WifiVendorHal mWifiVendorHal;
65    private WifiStatus mWifiStatusSuccess;
66    private WifiStatus mWifiStatusFailure;
67    @Mock
68    private HalDeviceManager mHalDeviceManager;
69    @Mock
70    private HandlerThread mWifiStateMachineHandlerThread;
71    @Mock
72    private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
73    @Mock
74    private IWifiApIface mIWifiApIface;
75    @Mock
76    private IWifiChip mIWifiChip;
77    @Mock
78    private IWifiStaIface mIWifiStaIface;
79    @Mock
80    private IWifiRttController mIWifiRttController;
81
82    /**
83     * Sets up for unit test
84     */
85    @Before
86    public void setUp() throws Exception {
87        MockitoAnnotations.initMocks(this);
88        mWifiStatusSuccess = new WifiStatus();
89        mWifiStatusSuccess.code = WifiStatusCode.SUCCESS;
90        mWifiStatusFailure = new WifiStatus();
91        mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN;
92        mWifiStatusFailure.description = "I don't even know what a Mock Turtle is.";
93        when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess);
94
95
96        // Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in
97        // individual tests, if needed.
98        doAnswer(new AnswerWithArguments() {
99            public boolean answer() {
100                when(mHalDeviceManager.isReady()).thenReturn(true);
101                when(mHalDeviceManager.isStarted()).thenReturn(true);
102                mHalDeviceManagerStatusCallbacks.onStatusChanged();
103                return true;
104            }
105        }).when(mHalDeviceManager).start();
106
107        doAnswer(new AnswerWithArguments() {
108            public void answer() {
109                when(mHalDeviceManager.isReady()).thenReturn(true);
110                when(mHalDeviceManager.isStarted()).thenReturn(false);
111                mHalDeviceManagerStatusCallbacks.onStatusChanged();
112            }
113        }).when(mHalDeviceManager).stop();
114        when(mHalDeviceManager.createStaIface(eq(null), eq(null)))
115                .thenReturn(mIWifiStaIface);
116        when(mHalDeviceManager.createApIface(eq(null), eq(null)))
117                .thenReturn(mIWifiApIface);
118        when(mHalDeviceManager.getChip(any(IWifiIface.class)))
119                .thenReturn(mIWifiChip);
120        when(mHalDeviceManager.createRttController(any(IWifiIface.class)))
121                .thenReturn(mIWifiRttController);
122
123        // Create the vendor HAL object under test.
124        mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mWifiStateMachineHandlerThread);
125
126        // Initialize the vendor HAL to capture the registered callback.
127        mWifiVendorHal.initialize();
128        ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> callbackCaptor =
129                ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class);
130        verify(mHalDeviceManager).registerStatusListener(
131                callbackCaptor.capture(), any(Looper.class));
132        mHalDeviceManagerStatusCallbacks = callbackCaptor.getValue();
133    }
134
135    /**
136     * Tests the successful starting of HAL in STA mode using
137     * {@link WifiVendorHal#startVendorHal(boolean)}.
138     */
139    @Test
140    public void testStartHalSuccessInStaMode() {
141        assertTrue(mWifiVendorHal.startVendorHal(true));
142        assertTrue(mWifiVendorHal.isHalStarted());
143
144        verify(mHalDeviceManager).start();
145        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
146        verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
147        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
148        verify(mHalDeviceManager).isReady();
149        verify(mHalDeviceManager).isStarted();
150
151        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
152    }
153
154    /**
155     * Tests the successful starting of HAL in AP mode using
156     * {@link WifiVendorHal#startVendorHal(boolean)}.
157     */
158    @Test
159    public void testStartHalSuccessInApMode() {
160        assertTrue(mWifiVendorHal.startVendorHal(false));
161        assertTrue(mWifiVendorHal.isHalStarted());
162
163        verify(mHalDeviceManager).start();
164        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
165        verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
166        verify(mHalDeviceManager).isReady();
167        verify(mHalDeviceManager).isStarted();
168
169        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
170        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
171    }
172
173    /**
174     * Tests the failure to start HAL in STA mode using
175     * {@link WifiVendorHal#startVendorHal(boolean)}.
176     */
177    @Test
178    public void testStartHalFailureInStaMode() {
179        // No callbacks are invoked in this case since the start itself failed. So, override
180        // default AnswerWithArguments that we setup.
181        doAnswer(new AnswerWithArguments() {
182            public boolean answer() {
183                return false;
184            }
185        }).when(mHalDeviceManager).start();
186        assertFalse(mWifiVendorHal.startVendorHal(true));
187        assertFalse(mWifiVendorHal.isHalStarted());
188
189        verify(mHalDeviceManager).start();
190
191        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
192        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
193        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
194        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
195    }
196
197    /**
198     * Tests the failure to start HAL in STA mode using
199     * {@link WifiVendorHal#startVendorHal(boolean)}.
200     */
201    @Test
202    public void testStartHalFailureInIfaceCreationInStaMode() {
203        when(mHalDeviceManager.createStaIface(eq(null), eq(null))).thenReturn(null);
204        assertFalse(mWifiVendorHal.startVendorHal(true));
205        assertFalse(mWifiVendorHal.isHalStarted());
206
207        verify(mHalDeviceManager).start();
208        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
209        verify(mHalDeviceManager).stop();
210
211        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
212        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
213        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
214    }
215
216    /**
217     * Tests the failure to start HAL in STA mode using
218     * {@link WifiVendorHal#startVendorHal(boolean)}.
219     */
220    @Test
221    public void testStartHalFailureInRttControllerCreationInStaMode() {
222        when(mHalDeviceManager.createRttController(any(IWifiIface.class))).thenReturn(null);
223        assertFalse(mWifiVendorHal.startVendorHal(true));
224        assertFalse(mWifiVendorHal.isHalStarted());
225
226        verify(mHalDeviceManager).start();
227        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
228        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
229        verify(mHalDeviceManager).stop();
230
231        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
232        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
233    }
234
235    /**
236     * Tests the failure to start HAL in STA mode using
237     * {@link WifiVendorHal#startVendorHal(boolean)}.
238     */
239    @Test
240    public void testStartHalFailureInChipGetInStaMode() {
241        when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null);
242        assertFalse(mWifiVendorHal.startVendorHal(true));
243        assertFalse(mWifiVendorHal.isHalStarted());
244
245        verify(mHalDeviceManager).start();
246        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
247        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
248        verify(mHalDeviceManager).getChip(any(IWifiIface.class));
249        verify(mHalDeviceManager).stop();
250
251        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
252    }
253
254    /**
255     * Tests the failure to start HAL in STA mode using
256     * {@link WifiVendorHal#startVendorHal(boolean)}.
257     */
258    @Test
259    public void testStartHalFailureInApMode() {
260        when(mHalDeviceManager.createApIface(eq(null), eq(null))).thenReturn(null);
261        assertFalse(mWifiVendorHal.startVendorHal(false));
262        assertFalse(mWifiVendorHal.isHalStarted());
263
264        verify(mHalDeviceManager).start();
265        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
266        verify(mHalDeviceManager).stop();
267
268        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
269        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
270        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
271    }
272
273    /**
274     * Tests the stopping of HAL in STA mode using
275     * {@link WifiVendorHal#stopVendorHal()}.
276     */
277    @Test
278    public void testStopHalInStaMode() {
279        assertTrue(mWifiVendorHal.startVendorHal(true));
280        assertTrue(mWifiVendorHal.isHalStarted());
281
282        mWifiVendorHal.stopVendorHal();
283        assertFalse(mWifiVendorHal.isHalStarted());
284
285        verify(mHalDeviceManager).start();
286        verify(mHalDeviceManager).stop();
287        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
288        verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
289        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
290        verify(mHalDeviceManager, times(2)).isReady();
291        verify(mHalDeviceManager, times(2)).isStarted();
292
293        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
294    }
295
296    /**
297     * Tests the stopping of HAL in AP mode using
298     * {@link WifiVendorHal#stopVendorHal()}.
299     */
300    @Test
301    public void testStopHalInApMode() {
302        assertTrue(mWifiVendorHal.startVendorHal(false));
303        assertTrue(mWifiVendorHal.isHalStarted());
304
305        mWifiVendorHal.stopVendorHal();
306        assertFalse(mWifiVendorHal.isHalStarted());
307
308        verify(mHalDeviceManager).start();
309        verify(mHalDeviceManager).stop();
310        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
311        verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
312        verify(mHalDeviceManager, times(2)).isReady();
313        verify(mHalDeviceManager, times(2)).isStarted();
314
315        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
316        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
317    }
318
319    /**
320     * Test translation to WifiManager.WIFI_FEATURE_*
321     *
322     * Just do a spot-check with a few feature bits here; since the code is table-
323     * driven we don't have to work hard to exercise all of it.
324     */
325    @Test
326    public void testFeatureMaskTranslation() {
327        int caps = (
328                IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
329                | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
330            );
331        int expected = (
332                WifiManager.WIFI_FEATURE_SCANNER
333                | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
334        assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps));
335    }
336
337    /**
338     * Test enablement of link layer stats after startup
339     * <p>
340     * Request link layer stats before HAL start
341     * - should not make it to the HAL layer
342     * Start the HAL in STA mode
343     * Request link layer stats twice more
344     * - enable request should make it to the HAL layer
345     * - HAL layer should have been called to make the requests (i.e., two calls total)
346     */
347    @Test
348    public void testLinkLayerStatsEnableAfterStartup() throws Exception {
349        doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
350
351        assertNull(mWifiVendorHal.getWifiLinkLayerStats());
352        assertTrue(mWifiVendorHal.startVendorHalSta());
353        assertTrue(mWifiVendorHal.isHalStarted());
354
355        verify(mHalDeviceManager).start();
356        mWifiVendorHal.getWifiLinkLayerStats();
357        mWifiVendorHal.getWifiLinkLayerStats();
358        verify(mIWifiStaIface).enableLinkLayerStatsCollection(false); // mLinkLayerStatsDebug
359        verify(mIWifiStaIface, times(2)).getLinkLayerStats(any());
360    }
361
362    /**
363     * Test that link layer stats are not enabled and harmless in AP mode
364     * <p>
365     * Start the HAL in AP mode
366     * - stats should not be enabled
367     * Request link layer stats
368     * - HAL layer should have been called to make the request
369     */
370    @Test
371    public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception {
372        doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
373
374        assertTrue(mWifiVendorHal.startVendorHalAp());
375        assertTrue(mWifiVendorHal.isHalStarted());
376        assertNull(mWifiVendorHal.getWifiLinkLayerStats());
377
378        verify(mHalDeviceManager).start();
379
380        verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false);
381        verify(mIWifiStaIface, never()).getLinkLayerStats(any());
382    }
383
384    // TODO(b/34900534) add test for correct MOVE CORRESPONDING of fields
385
386    /**
387     * Test that getFirmwareVersion() and getDriverVersion() work
388     *
389     * Calls before the STA is started are expected to return null.
390     */
391    @Test
392    public void testVersionGetters() throws Exception {
393        String firmwareVersion = "fuzzy";
394        String driverVersion = "dizzy";
395        IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo();
396        chipDebugInfo.firmwareDescription = firmwareVersion;
397        chipDebugInfo.driverDescription = driverVersion;
398
399        doAnswer(new AnswerWithArguments() {
400            public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException {
401                cb.onValues(mWifiStatusSuccess, chipDebugInfo);
402            }
403        }).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class));
404
405        assertNull(mWifiVendorHal.getFirmwareVersion());
406        assertNull(mWifiVendorHal.getDriverVersion());
407
408        assertTrue(mWifiVendorHal.startVendorHalSta());
409
410        assertEquals(firmwareVersion, mWifiVendorHal.getFirmwareVersion());
411        assertEquals(driverVersion, mWifiVendorHal.getDriverVersion());
412    }
413
414    /**
415     * Test that setScanningMacOui is hooked up to the HAL correctly
416     */
417    @Test
418    public void testSetScanningMacOui() throws Exception {
419        byte[] oui = NativeUtil.macAddressOuiToByteArray("DA:A1:19");
420        byte[] zzz = NativeUtil.macAddressOuiToByteArray("00:00:00");
421
422        when(mIWifiStaIface.setScanningMacOui(any())).thenReturn(mWifiStatusSuccess);
423
424        assertFalse(mWifiVendorHal.setScanningMacOui(oui)); // expect fail - STA not started
425        assertTrue(mWifiVendorHal.startVendorHalSta());
426        assertFalse(mWifiVendorHal.setScanningMacOui(null));  // expect fail - null
427        assertFalse(mWifiVendorHal.setScanningMacOui(new byte[]{(byte) 1})); // expect fail - len
428        assertTrue(mWifiVendorHal.setScanningMacOui(oui));
429        assertTrue(mWifiVendorHal.setScanningMacOui(zzz));
430
431        verify(mIWifiStaIface).setScanningMacOui(eq(oui));
432        verify(mIWifiStaIface).setScanningMacOui(eq(zzz));
433    }
434
435    @Test
436    public void testStartSendingOffloadedPacket() throws Exception {
437        byte[] srcMac = NativeUtil.macAddressToByteArray("4007b2088c81");
438        InetAddress src = InetAddress.parseNumericAddress("192.168.13.13");
439        InetAddress dst = InetAddress.parseNumericAddress("93.184.216.34");
440        int slot = 13;
441        int millis = 16000;
442
443        KeepalivePacketData kap = KeepalivePacketData.nattKeepalivePacket(src, 63000, dst, 4500);
444
445        when(mIWifiStaIface.startSendingKeepAlivePackets(
446                anyInt(), any(), anyShort(), any(), any(), anyInt()
447        )).thenReturn(mWifiStatusSuccess);
448
449        assertTrue(mWifiVendorHal.startVendorHalSta());
450        assertTrue(0 == mWifiVendorHal.startSendingOffloadedPacket(slot, srcMac, kap, millis));
451
452        verify(mIWifiStaIface).startSendingKeepAlivePackets(
453                eq(slot), any(), anyShort(), any(), any(), eq(millis));
454    }
455
456    @Test
457    public void testStopSendingOffloadedPacket() throws Exception {
458        int slot = 13;
459
460        when(mIWifiStaIface.stopSendingKeepAlivePackets(anyInt())).thenReturn(mWifiStatusSuccess);
461
462        assertTrue(mWifiVendorHal.startVendorHalSta());
463        assertTrue(0 == mWifiVendorHal.stopSendingOffloadedPacket(slot));
464
465        verify(mIWifiStaIface).stopSendingKeepAlivePackets(eq(slot));
466    }
467
468    /**
469     * Test that getApfCapabilities is hooked up to the HAL correctly
470     *
471     * A call before the vendor HAL is started should return a non-null result with version 0
472     *
473     * A call after the HAL is started should return the mocked values.
474     */
475    @Test
476    public void testApfCapabilities() throws Exception {
477        int myVersion = 33;
478        int myMaxSize = 1234;
479
480        StaApfPacketFilterCapabilities capabilities = new StaApfPacketFilterCapabilities();
481        capabilities.version = myVersion;
482        capabilities.maxLength = myMaxSize;
483
484        doAnswer(new AnswerWithArguments() {
485            public void answer(IWifiStaIface.getApfPacketFilterCapabilitiesCallback cb)
486                    throws RemoteException {
487                cb.onValues(mWifiStatusSuccess, capabilities);
488            }
489        }).when(mIWifiStaIface).getApfPacketFilterCapabilities(any(
490                IWifiStaIface.getApfPacketFilterCapabilitiesCallback.class));
491
492
493        assertEquals(0, mWifiVendorHal.getApfCapabilities().apfVersionSupported);
494
495        assertTrue(mWifiVendorHal.startVendorHalSta());
496
497        ApfCapabilities actual = mWifiVendorHal.getApfCapabilities();
498
499        assertEquals(myVersion, actual.apfVersionSupported);
500        assertEquals(myMaxSize, actual.maximumApfProgramSize);
501        assertEquals(android.system.OsConstants.ARPHRD_ETHER, actual.apfPacketFormat);
502        assertNotEquals(0, actual.apfPacketFormat);
503    }
504
505    /**
506     * Test that an APF program can be installed.
507     */
508    @Test
509    public void testInstallApf() throws Exception {
510        byte[] filter = new byte[] {19, 53, 10};
511
512        ArrayList<Byte> expected = new ArrayList<>(3);
513        for (byte b : filter) expected.add(b);
514
515        when(mIWifiStaIface.installApfPacketFilter(anyInt(), any(ArrayList.class)))
516                .thenReturn(mWifiStatusSuccess);
517
518        assertTrue(mWifiVendorHal.startVendorHalSta());
519        assertTrue(mWifiVendorHal.installPacketFilter(filter));
520
521        verify(mIWifiStaIface).installApfPacketFilter(eq(0), eq(expected));
522    }
523
524    /**
525     * Test that the country code is set in AP mode (when it should be).
526     */
527    @Test
528    public void testSetCountryCodeHal() throws Exception {
529        byte[] expected = new byte[]{(byte) 'C', (byte) 'A'};
530
531        when(mIWifiApIface.setCountryCode(any()))
532                .thenReturn(mWifiStatusSuccess);
533
534        assertTrue(mWifiVendorHal.startVendorHalAp());
535
536        assertFalse(mWifiVendorHal.setCountryCodeHal(null));
537        assertFalse(mWifiVendorHal.setCountryCodeHal(""));
538        assertFalse(mWifiVendorHal.setCountryCodeHal("A"));
539        assertTrue(mWifiVendorHal.setCountryCodeHal("CA")); // Only one expected to succeed
540        assertFalse(mWifiVendorHal.setCountryCodeHal("ZZZ"));
541
542        verify(mIWifiApIface).setCountryCode(eq(expected));
543    }
544
545    /**
546     * Test that startLoggingToDebugRingBuffer is plumbed to chip
547     *
548     * A call before the vendor hal is started should just return false.
549     * After starting in STA mode, the call should succeed, and pass ther right things down.
550     */
551    @Test
552    public void testStartLoggingRingBuffer() throws Exception {
553        when(mIWifiChip.startLoggingToDebugRingBuffer(
554                any(String.class), anyInt(), anyInt(), anyInt()
555        )).thenReturn(mWifiStatusSuccess);
556
557        assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
558        assertTrue(mWifiVendorHal.startVendorHalSta());
559        assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
560
561        verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
562    }
563
564    /**
565     * Same test as testStartLoggingRingBuffer, but in AP mode rather than STA.
566     */
567    @Test
568    public void testStartLoggingRingBufferOnAp() throws Exception {
569        when(mIWifiChip.startLoggingToDebugRingBuffer(
570                any(String.class), anyInt(), anyInt(), anyInt()
571        )).thenReturn(mWifiStatusSuccess);
572
573        assertFalse(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 0, 0, "One"));
574        assertTrue(mWifiVendorHal.startVendorHalAp());
575        assertTrue(mWifiVendorHal.startLoggingRingBuffer(1, 0x42, 11, 3000, "One"));
576
577        verify(mIWifiChip).startLoggingToDebugRingBuffer("One", 1, 11, 3000);
578    }
579
580    /**
581     * Test that getRingBufferStatus gets and translates its stuff correctly
582     */
583    @Test
584    public void testRingBufferStatus() throws Exception {
585        WifiDebugRingBufferStatus one = new WifiDebugRingBufferStatus();
586        one.ringName = "One";
587        one.flags = WifiDebugRingBufferFlags.HAS_BINARY_ENTRIES;
588        one.ringId = 5607371;
589        one.sizeInBytes = 54321;
590        one.freeSizeInBytes = 42;
591        one.verboseLevel = WifiDebugRingBufferVerboseLevel.VERBOSE;
592        String oneExpect = "name: One flag: 1 ringBufferId: 5607371 ringBufferByteSize: 54321"
593                + " verboseLevel: 2 writtenBytes: 0 readBytes: 0 writtenRecords: 0";
594
595        WifiDebugRingBufferStatus two = new WifiDebugRingBufferStatus();
596        two.ringName = "Two";
597        two.flags = WifiDebugRingBufferFlags.HAS_ASCII_ENTRIES
598                | WifiDebugRingBufferFlags.HAS_PER_PACKET_ENTRIES;
599        two.ringId = 4512470;
600        two.sizeInBytes = 300;
601        two.freeSizeInBytes = 42;
602        two.verboseLevel = WifiDebugRingBufferVerboseLevel.DEFAULT;
603
604        ArrayList<WifiDebugRingBufferStatus> halBufferStatus = new ArrayList<>(2);
605        halBufferStatus.add(one);
606        halBufferStatus.add(two);
607
608        WifiNative.RingBufferStatus[] actual;
609
610        doAnswer(new AnswerWithArguments() {
611            public void answer(IWifiChip.getDebugRingBuffersStatusCallback cb)
612                    throws RemoteException {
613                cb.onValues(mWifiStatusSuccess, halBufferStatus);
614            }
615        }).when(mIWifiChip).getDebugRingBuffersStatus(any(
616                IWifiChip.getDebugRingBuffersStatusCallback.class));
617
618        assertTrue(mWifiVendorHal.startVendorHalSta());
619        actual = mWifiVendorHal.getRingBufferStatus();
620
621        assertEquals(halBufferStatus.size(), actual.length);
622        assertEquals(oneExpect, actual[0].toString());
623        assertEquals(two.ringId, actual[1].ringBufferId);
624
625    }
626
627    /**
628     * Test that getRingBufferData calls forceDumpToDebugRingBuffer
629     *
630     * Try once before hal start, and twice after (one success, one failure).
631     */
632    @Test
633    public void testForceRingBufferDump() throws Exception {
634        when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Gunk"))).thenReturn(mWifiStatusSuccess);
635        when(mIWifiChip.forceDumpToDebugRingBuffer(eq("Glop"))).thenReturn(mWifiStatusFailure);
636
637        assertFalse(mWifiVendorHal.getRingBufferData("Gunk")); // hal not started
638
639        assertTrue(mWifiVendorHal.startVendorHalSta());
640
641        assertTrue(mWifiVendorHal.getRingBufferData("Gunk")); // mocked call succeeds
642        assertFalse(mWifiVendorHal.getRingBufferData("Glop")); // mocked call fails
643
644        verify(mIWifiChip).forceDumpToDebugRingBuffer("Gunk");
645        verify(mIWifiChip).forceDumpToDebugRingBuffer("Glop");
646    }
647
648    /**
649     * Tests the start of packet fate monitoring.
650     *
651     * Try once before hal start, and once after (one success, one failure).
652     */
653    @Test
654    public void testStartPktFateMonitoring() throws Exception {
655        when(mIWifiStaIface.startDebugPacketFateMonitoring()).thenReturn(mWifiStatusSuccess);
656
657        assertFalse(mWifiVendorHal.startPktFateMonitoring());
658        verify(mIWifiStaIface, never()).startDebugPacketFateMonitoring();
659
660        assertTrue(mWifiVendorHal.startVendorHalSta());
661        assertTrue(mWifiVendorHal.startPktFateMonitoring());
662        verify(mIWifiStaIface).startDebugPacketFateMonitoring();
663    }
664
665    /**
666     * Tests the retrieval of tx packet fates.
667     *
668     * Try once before hal start, and once after.
669     */
670    @Test
671    public void testGetTxPktFates() throws Exception {
672        byte[] frameContentBytes = new byte[30];
673        new Random().nextBytes(frameContentBytes);
674        WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
675        fateReport.fate = WifiDebugTxPacketFate.DRV_QUEUED;
676        fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
677        fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
678        fateReport.frameInfo.frameContent.addAll(
679                NativeUtil.byteArrayToArrayList(frameContentBytes));
680
681        doAnswer(new AnswerWithArguments() {
682            public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
683                cb.onValues(mWifiStatusSuccess,
684                        new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(fateReport)));
685            }
686        }).when(mIWifiStaIface)
687                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
688
689        WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
690        assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
691        verify(mIWifiStaIface, never())
692                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
693
694        assertTrue(mWifiVendorHal.startVendorHalSta());
695
696        assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
697        verify(mIWifiStaIface)
698                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
699        assertEquals(WifiLoggerHal.TX_PKT_FATE_DRV_QUEUED, retrievedFates[0].mFate);
700        assertEquals(fateReport.frameInfo.driverTimestampUsec,
701                retrievedFates[0].mDriverTimestampUSec);
702        assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
703        assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
704    }
705
706    /**
707     * Tests the retrieval of tx packet fates when the number of fates retrieved exceeds the
708     * input array.
709     *
710     * Try once before hal start, and once after.
711     */
712    @Test
713    public void testGetTxPktFatesExceedsInputArrayLength() throws Exception {
714        byte[] frameContentBytes = new byte[30];
715        new Random().nextBytes(frameContentBytes);
716        WifiDebugTxPacketFateReport fateReport = new WifiDebugTxPacketFateReport();
717        fateReport.fate = WifiDebugTxPacketFate.FW_DROP_OTHER;
718        fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
719        fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
720        fateReport.frameInfo.frameContent.addAll(
721                NativeUtil.byteArrayToArrayList(frameContentBytes));
722
723        doAnswer(new AnswerWithArguments() {
724            public void answer(IWifiStaIface.getDebugTxPacketFatesCallback cb) {
725                cb.onValues(mWifiStatusSuccess,
726                        new ArrayList<WifiDebugTxPacketFateReport>(Arrays.asList(
727                                fateReport, fateReport)));
728            }
729        }).when(mIWifiStaIface)
730                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
731
732        WifiNative.TxFateReport[] retrievedFates = new WifiNative.TxFateReport[1];
733        assertFalse(mWifiVendorHal.getTxPktFates(retrievedFates));
734        verify(mIWifiStaIface, never())
735                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
736
737        assertTrue(mWifiVendorHal.startVendorHalSta());
738
739        assertTrue(mWifiVendorHal.getTxPktFates(retrievedFates));
740        verify(mIWifiStaIface)
741                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
742        assertEquals(WifiLoggerHal.TX_PKT_FATE_FW_DROP_OTHER, retrievedFates[0].mFate);
743        assertEquals(fateReport.frameInfo.driverTimestampUsec,
744                retrievedFates[0].mDriverTimestampUSec);
745        assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
746        assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
747    }
748
749    /**
750     * Tests the retrieval of rx packet fates.
751     *
752     * Try once before hal start, and once after.
753     */
754    @Test
755    public void testGetRxPktFates() throws Exception {
756        byte[] frameContentBytes = new byte[30];
757        new Random().nextBytes(frameContentBytes);
758        WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
759        fateReport.fate = WifiDebugRxPacketFate.SUCCESS;
760        fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
761        fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.ETHERNET_II;
762        fateReport.frameInfo.frameContent.addAll(
763                NativeUtil.byteArrayToArrayList(frameContentBytes));
764
765        doAnswer(new AnswerWithArguments() {
766            public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
767                cb.onValues(mWifiStatusSuccess,
768                        new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(fateReport)));
769            }
770        }).when(mIWifiStaIface)
771                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
772
773        WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
774        assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
775        verify(mIWifiStaIface, never())
776                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
777
778        assertTrue(mWifiVendorHal.startVendorHalSta());
779
780        assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
781        verify(mIWifiStaIface)
782                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
783        assertEquals(WifiLoggerHal.RX_PKT_FATE_SUCCESS, retrievedFates[0].mFate);
784        assertEquals(fateReport.frameInfo.driverTimestampUsec,
785                retrievedFates[0].mDriverTimestampUSec);
786        assertEquals(WifiLoggerHal.FRAME_TYPE_ETHERNET_II, retrievedFates[0].mFrameType);
787        assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
788    }
789
790    /**
791     * Tests the retrieval of rx packet fates when the number of fates retrieved exceeds the
792     * input array.
793     *
794     * Try once before hal start, and once after.
795     */
796    @Test
797    public void testGetRxPktFatesExceedsInputArrayLength() throws Exception {
798        byte[] frameContentBytes = new byte[30];
799        new Random().nextBytes(frameContentBytes);
800        WifiDebugRxPacketFateReport fateReport = new WifiDebugRxPacketFateReport();
801        fateReport.fate = WifiDebugRxPacketFate.FW_DROP_FILTER;
802        fateReport.frameInfo.driverTimestampUsec = new Random().nextLong();
803        fateReport.frameInfo.frameType = WifiDebugPacketFateFrameType.MGMT_80211;
804        fateReport.frameInfo.frameContent.addAll(
805                NativeUtil.byteArrayToArrayList(frameContentBytes));
806
807        doAnswer(new AnswerWithArguments() {
808            public void answer(IWifiStaIface.getDebugRxPacketFatesCallback cb) {
809                cb.onValues(mWifiStatusSuccess,
810                        new ArrayList<WifiDebugRxPacketFateReport>(Arrays.asList(
811                                fateReport, fateReport)));
812            }
813        }).when(mIWifiStaIface)
814                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
815
816        WifiNative.RxFateReport[] retrievedFates = new WifiNative.RxFateReport[1];
817        assertFalse(mWifiVendorHal.getRxPktFates(retrievedFates));
818        verify(mIWifiStaIface, never())
819                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
820
821        assertTrue(mWifiVendorHal.startVendorHalSta());
822
823        assertTrue(mWifiVendorHal.getRxPktFates(retrievedFates));
824        verify(mIWifiStaIface)
825                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
826        assertEquals(WifiLoggerHal.RX_PKT_FATE_FW_DROP_FILTER, retrievedFates[0].mFate);
827        assertEquals(fateReport.frameInfo.driverTimestampUsec,
828                retrievedFates[0].mDriverTimestampUSec);
829        assertEquals(WifiLoggerHal.FRAME_TYPE_80211_MGMT, retrievedFates[0].mFrameType);
830        assertArrayEquals(frameContentBytes, retrievedFates[0].mFrameBytes);
831    }
832
833    /**
834     * Tests the failure to retrieve tx packet fates when the input array is empty.
835     */
836    @Test
837    public void testGetTxPktFatesEmptyInputArray() throws Exception {
838        assertTrue(mWifiVendorHal.startVendorHalSta());
839        assertFalse(mWifiVendorHal.getTxPktFates(new WifiNative.TxFateReport[0]));
840        verify(mIWifiStaIface, never())
841                .getDebugTxPacketFates(any(IWifiStaIface.getDebugTxPacketFatesCallback.class));
842    }
843
844    /**
845     * Tests the failure to retrieve rx packet fates when the input array is empty.
846     */
847    @Test
848    public void testGetRxPktFatesEmptyInputArray() throws Exception {
849        assertTrue(mWifiVendorHal.startVendorHalSta());
850        assertFalse(mWifiVendorHal.getRxPktFates(new WifiNative.RxFateReport[0]));
851        verify(mIWifiStaIface, never())
852                .getDebugRxPacketFates(any(IWifiStaIface.getDebugRxPacketFatesCallback.class));
853    }
854}
855