WifiVendorHalTest.java revision 7e7e2e3fd4da1f5ccda2f03dcdb321654e9f6ff8
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.WifiStatus;
26import android.hardware.wifi.V1_0.WifiStatusCode;
27import android.net.wifi.WifiManager;
28
29
30import static org.junit.Assert.*;
31import static org.mockito.Mockito.*;
32
33import android.os.HandlerThread;
34import android.os.Looper;
35import android.os.RemoteException;
36
37import org.junit.Assert;
38import org.junit.Before;
39import org.junit.Test;
40import org.mockito.ArgumentCaptor;
41import org.mockito.Mock;
42import org.mockito.MockitoAnnotations;
43
44/**
45 * Unit tests for {@link com.android.server.wifi.WifiVendorHal}.
46 */
47public class WifiVendorHalTest {
48
49    WifiVendorHal mWifiVendorHal;
50    private WifiStatus mWifiStatusSuccess;
51    private WifiStatus mWifiStatusFailure;
52    @Mock
53    private HalDeviceManager mHalDeviceManager;
54    @Mock
55    private HandlerThread mWifiStateMachineHandlerThread;
56    @Mock
57    private WifiVendorHal.HalDeviceManagerStatusListener mHalDeviceManagerStatusCallbacks;
58    @Mock
59    private IWifiApIface mIWifiApIface;
60    @Mock
61    private IWifiChip mIWifiChip;
62    @Mock
63    private IWifiStaIface mIWifiStaIface;
64    @Mock
65    private IWifiRttController mIWifiRttController;
66
67    /**
68     * Sets up for unit test
69     */
70    @Before
71    public void setUp() throws Exception {
72        MockitoAnnotations.initMocks(this);
73        mWifiStatusSuccess = new WifiStatus();
74        mWifiStatusSuccess.code = WifiStatusCode.SUCCESS;
75        mWifiStatusFailure = new WifiStatus();
76        mWifiStatusFailure.code = WifiStatusCode.ERROR_UNKNOWN;
77        mWifiStatusFailure.description = "I don't even know what a Mock Turtle is.";
78        when(mIWifiStaIface.enableLinkLayerStatsCollection(false)).thenReturn(mWifiStatusSuccess);
79
80
81        // Setup the HalDeviceManager mock's start/stop behaviour. This can be overridden in
82        // individual tests, if needed.
83        doAnswer(new AnswerWithArguments() {
84            public boolean answer() {
85                when(mHalDeviceManager.isReady()).thenReturn(true);
86                when(mHalDeviceManager.isStarted()).thenReturn(true);
87                mHalDeviceManagerStatusCallbacks.onStatusChanged();
88                return true;
89            }
90        }).when(mHalDeviceManager).start();
91
92        doAnswer(new AnswerWithArguments() {
93            public void answer() {
94                when(mHalDeviceManager.isReady()).thenReturn(true);
95                when(mHalDeviceManager.isStarted()).thenReturn(false);
96                mHalDeviceManagerStatusCallbacks.onStatusChanged();
97            }
98        }).when(mHalDeviceManager).stop();
99        when(mHalDeviceManager.createStaIface(eq(null), eq(null)))
100                .thenReturn(mIWifiStaIface);
101        when(mHalDeviceManager.createApIface(eq(null), eq(null)))
102                .thenReturn(mIWifiApIface);
103        when(mHalDeviceManager.getChip(any(IWifiIface.class)))
104                .thenReturn(mIWifiChip);
105        when(mHalDeviceManager.createRttController(any(IWifiIface.class)))
106                .thenReturn(mIWifiRttController);
107
108        // Create the vendor HAL object under test.
109        mWifiVendorHal = new WifiVendorHal(mHalDeviceManager, mWifiStateMachineHandlerThread);
110
111        // Initialize the vendor HAL to capture the registered callback.
112        mWifiVendorHal.initialize();
113        ArgumentCaptor<WifiVendorHal.HalDeviceManagerStatusListener> callbackCaptor =
114                ArgumentCaptor.forClass(WifiVendorHal.HalDeviceManagerStatusListener.class);
115        verify(mHalDeviceManager).registerStatusListener(
116                callbackCaptor.capture(), any(Looper.class));
117        mHalDeviceManagerStatusCallbacks = callbackCaptor.getValue();
118    }
119
120    /**
121     * Test that parsing a typical colon-delimited MAC adddress works
122     */
123    @Test
124    public void testTypicalHexParse() throws Exception {
125        byte[] sixBytes = new byte[6];
126        mWifiVendorHal.parseUnquotedMacStrToByteArray("61:52:43:34:25:16", sixBytes);
127        Assert.assertArrayEquals(new byte[]{0x61, 0x52, 0x43, 0x34, 0x25, 0x16}, sixBytes);
128    }
129
130    /**
131     * Tests the successful starting of HAL in STA mode using
132     * {@link WifiVendorHal#startVendorHal(boolean)}.
133     */
134    @Test
135    public void testStartHalSuccessInStaMode() {
136        assertTrue(mWifiVendorHal.startVendorHal(true));
137        assertTrue(mWifiVendorHal.isHalStarted());
138
139        verify(mHalDeviceManager).start();
140        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
141        verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
142        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
143        verify(mHalDeviceManager).isReady();
144        verify(mHalDeviceManager).isStarted();
145
146        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
147    }
148
149    /**
150     * Tests the successful starting of HAL in AP mode using
151     * {@link WifiVendorHal#startVendorHal(boolean)}.
152     */
153    @Test
154    public void testStartHalSuccessInApMode() {
155        assertTrue(mWifiVendorHal.startVendorHal(false));
156        assertTrue(mWifiVendorHal.isHalStarted());
157
158        verify(mHalDeviceManager).start();
159        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
160        verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
161        verify(mHalDeviceManager).isReady();
162        verify(mHalDeviceManager).isStarted();
163
164        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
165        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
166    }
167
168    /**
169     * Tests the failure to start HAL in STA mode using
170     * {@link WifiVendorHal#startVendorHal(boolean)}.
171     */
172    @Test
173    public void testStartHalFailureInStaMode() {
174        // No callbacks are invoked in this case since the start itself failed. So, override
175        // default AnswerWithArguments that we setup.
176        doAnswer(new AnswerWithArguments() {
177            public boolean answer() {
178                return false;
179            }
180        }).when(mHalDeviceManager).start();
181        assertFalse(mWifiVendorHal.startVendorHal(true));
182        assertFalse(mWifiVendorHal.isHalStarted());
183
184        verify(mHalDeviceManager).start();
185
186        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
187        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
188        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
189        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
190    }
191
192    /**
193     * Tests the failure to start HAL in STA mode using
194     * {@link WifiVendorHal#startVendorHal(boolean)}.
195     */
196    @Test
197    public void testStartHalFailureInIfaceCreationInStaMode() {
198        when(mHalDeviceManager.createStaIface(eq(null), eq(null))).thenReturn(null);
199        assertFalse(mWifiVendorHal.startVendorHal(true));
200        assertFalse(mWifiVendorHal.isHalStarted());
201
202        verify(mHalDeviceManager).start();
203        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
204        verify(mHalDeviceManager).stop();
205
206        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
207        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
208        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
209    }
210
211    /**
212     * Tests the failure to start HAL in STA mode using
213     * {@link WifiVendorHal#startVendorHal(boolean)}.
214     */
215    @Test
216    public void testStartHalFailureInRttControllerCreationInStaMode() {
217        when(mHalDeviceManager.createRttController(any(IWifiIface.class))).thenReturn(null);
218        assertFalse(mWifiVendorHal.startVendorHal(true));
219        assertFalse(mWifiVendorHal.isHalStarted());
220
221        verify(mHalDeviceManager).start();
222        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
223        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
224        verify(mHalDeviceManager).stop();
225
226        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
227        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
228    }
229
230    /**
231     * Tests the failure to start HAL in STA mode using
232     * {@link WifiVendorHal#startVendorHal(boolean)}.
233     */
234    @Test
235    public void testStartHalFailureInChipGetInStaMode() {
236        when(mHalDeviceManager.getChip(any(IWifiIface.class))).thenReturn(null);
237        assertFalse(mWifiVendorHal.startVendorHal(true));
238        assertFalse(mWifiVendorHal.isHalStarted());
239
240        verify(mHalDeviceManager).start();
241        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
242        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
243        verify(mHalDeviceManager).getChip(any(IWifiIface.class));
244        verify(mHalDeviceManager).stop();
245
246        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
247    }
248
249    /**
250     * Tests the failure to start HAL in STA mode using
251     * {@link WifiVendorHal#startVendorHal(boolean)}.
252     */
253    @Test
254    public void testStartHalFailureInApMode() {
255        when(mHalDeviceManager.createApIface(eq(null), eq(null))).thenReturn(null);
256        assertFalse(mWifiVendorHal.startVendorHal(false));
257        assertFalse(mWifiVendorHal.isHalStarted());
258
259        verify(mHalDeviceManager).start();
260        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
261        verify(mHalDeviceManager).stop();
262
263        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
264        verify(mHalDeviceManager, never()).getChip(any(IWifiIface.class));
265        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
266    }
267
268    /**
269     * Tests the stopping of HAL in STA mode using
270     * {@link WifiVendorHal#stopVendorHal()}.
271     */
272    @Test
273    public void testStopHalInStaMode() {
274        assertTrue(mWifiVendorHal.startVendorHal(true));
275        assertTrue(mWifiVendorHal.isHalStarted());
276
277        mWifiVendorHal.stopVendorHal();
278        assertFalse(mWifiVendorHal.isHalStarted());
279
280        verify(mHalDeviceManager).start();
281        verify(mHalDeviceManager).stop();
282        verify(mHalDeviceManager).createStaIface(eq(null), eq(null));
283        verify(mHalDeviceManager).getChip(eq(mIWifiStaIface));
284        verify(mHalDeviceManager).createRttController(eq(mIWifiStaIface));
285        verify(mHalDeviceManager, times(2)).isReady();
286        verify(mHalDeviceManager, times(2)).isStarted();
287
288        verify(mHalDeviceManager, never()).createApIface(eq(null), eq(null));
289    }
290
291    /**
292     * Tests the stopping of HAL in AP mode using
293     * {@link WifiVendorHal#stopVendorHal()}.
294     */
295    @Test
296    public void testStopHalInApMode() {
297        assertTrue(mWifiVendorHal.startVendorHal(false));
298        assertTrue(mWifiVendorHal.isHalStarted());
299
300        mWifiVendorHal.stopVendorHal();
301        assertFalse(mWifiVendorHal.isHalStarted());
302
303        verify(mHalDeviceManager).start();
304        verify(mHalDeviceManager).stop();
305        verify(mHalDeviceManager).createApIface(eq(null), eq(null));
306        verify(mHalDeviceManager).getChip(eq(mIWifiApIface));
307        verify(mHalDeviceManager, times(2)).isReady();
308        verify(mHalDeviceManager, times(2)).isStarted();
309
310        verify(mHalDeviceManager, never()).createStaIface(eq(null), eq(null));
311        verify(mHalDeviceManager, never()).createRttController(any(IWifiIface.class));
312    }
313
314    /**
315     * Test translation to WifiManager.WIFI_FEATURE_*
316     *
317     * Just do a spot-check with a few feature bits here; since the code is table-
318     * driven we don't have to work hard to exercise all of it.
319     */
320    @Test
321    public void testFeatureMaskTranslation() {
322        int caps = (
323                IWifiStaIface.StaIfaceCapabilityMask.BACKGROUND_SCAN
324                | IWifiStaIface.StaIfaceCapabilityMask.LINK_LAYER_STATS
325            );
326        int expected = (
327                WifiManager.WIFI_FEATURE_INFRA
328                | WifiManager.WIFI_FEATURE_SCANNER
329                | WifiManager.WIFI_FEATURE_LINK_LAYER_STATS);
330        assertEquals(expected, mWifiVendorHal.wifiFeatureMaskFromStaCapabilities(caps));
331    }
332
333    /**
334     * Test enablement of link layer stats after startup
335     * <p>
336     * Request link layer stats before HAL start
337     * - should not make it to the HAL layer
338     * Start the HAL in STA mode
339     * Request link layer stats twice more
340     * - enable request should make it to the HAL layer
341     * - HAL layer should have been called to make the requests (i.e., two calls total)
342     */
343    @Test
344    public void testLinkLayerStatsEnableAfterStartup() throws Exception {
345        doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
346
347        assertNull(mWifiVendorHal.getWifiLinkLayerStats());
348        assertTrue(mWifiVendorHal.startVendorHalSta());
349        assertTrue(mWifiVendorHal.isHalStarted());
350
351        verify(mHalDeviceManager).start();
352        mWifiVendorHal.getWifiLinkLayerStats();
353        mWifiVendorHal.getWifiLinkLayerStats();
354        verify(mIWifiStaIface).enableLinkLayerStatsCollection(false); // mLinkLayerStatsDebug
355        verify(mIWifiStaIface, times(2)).getLinkLayerStats(any());
356    }
357
358    /**
359     * Test that link layer stats are not enabled and harmless in AP mode
360     * <p>
361     * Start the HAL in AP mode
362     * - stats should not be enabled
363     * Request link layer stats
364     * - HAL layer should have been called to make the request
365     */
366    @Test
367    public void testLinkLayerStatsNotEnabledAndHarmlessInApMode() throws Exception {
368        doNothing().when(mIWifiStaIface).getLinkLayerStats(any());
369
370        assertTrue(mWifiVendorHal.startVendorHalAp());
371        assertTrue(mWifiVendorHal.isHalStarted());
372        assertNull(mWifiVendorHal.getWifiLinkLayerStats());
373
374        verify(mHalDeviceManager).start();
375
376        verify(mIWifiStaIface, never()).enableLinkLayerStatsCollection(false);
377        verify(mIWifiStaIface, never()).getLinkLayerStats(any());
378    }
379
380    // TODO(b/34900534) add test for correct MOVE CORRESPONDING of fields
381
382    /**
383     * Test that getFirmwareVersion() and getDriverVersion() work
384     *
385     * Calls before the STA is started are expected to return null.
386     */
387    @Test
388    public void testVersionGetters() throws Exception {
389        String firmwareVersion = "fuzzy";
390        String driverVersion = "dizzy";
391        IWifiChip.ChipDebugInfo chipDebugInfo = new IWifiChip.ChipDebugInfo();
392        chipDebugInfo.firmwareDescription = firmwareVersion;
393        chipDebugInfo.driverDescription = driverVersion;
394
395        doAnswer(new AnswerWithArguments() {
396            public void answer(IWifiChip.requestChipDebugInfoCallback cb) throws RemoteException {
397                cb.onValues(mWifiStatusSuccess, chipDebugInfo);
398            }
399        }).when(mIWifiChip).requestChipDebugInfo(any(IWifiChip.requestChipDebugInfoCallback.class));
400
401        assertNull(mWifiVendorHal.getFirmwareVersion());
402        assertNull(mWifiVendorHal.getDriverVersion());
403
404        assertTrue(mWifiVendorHal.startVendorHalSta());
405
406        assertEquals(firmwareVersion, mWifiVendorHal.getFirmwareVersion());
407        assertEquals(driverVersion, mWifiVendorHal.getDriverVersion());
408    }
409}
410