HalDeviceManagerTest.java revision 448a7b6b7b16cf39ed25729ceaf61edb30368567
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 static org.hamcrest.core.IsEqual.equalTo;
20import static org.mockito.Matchers.any;
21import static org.mockito.Matchers.anyInt;
22import static org.mockito.Matchers.anyLong;
23import static org.mockito.Matchers.anyString;
24import static org.mockito.Matchers.eq;
25import static org.mockito.Mockito.doAnswer;
26import static org.mockito.Mockito.inOrder;
27import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.times;
29import static org.mockito.Mockito.verify;
30import static org.mockito.Mockito.verifyNoMoreInteractions;
31import static org.mockito.Mockito.when;
32
33import android.app.test.MockAnswerUtil;
34import android.hardware.wifi.V1_0.IWifi;
35import android.hardware.wifi.V1_0.IWifiApIface;
36import android.hardware.wifi.V1_0.IWifiChip;
37import android.hardware.wifi.V1_0.IWifiChipEventCallback;
38import android.hardware.wifi.V1_0.IWifiEventCallback;
39import android.hardware.wifi.V1_0.IWifiIface;
40import android.hardware.wifi.V1_0.IWifiNanIface;
41import android.hardware.wifi.V1_0.IWifiP2pIface;
42import android.hardware.wifi.V1_0.IWifiStaIface;
43import android.hardware.wifi.V1_0.IfaceType;
44import android.hardware.wifi.V1_0.WifiStatus;
45import android.hardware.wifi.V1_0.WifiStatusCode;
46import android.hidl.manager.V1_0.IServiceManager;
47import android.hidl.manager.V1_0.IServiceNotification;
48import android.os.IHwBinder;
49import android.os.test.TestLooper;
50import android.util.Log;
51
52import org.hamcrest.core.IsNull;
53import org.junit.After;
54import org.junit.Before;
55import org.junit.Rule;
56import org.junit.Test;
57import org.junit.rules.ErrorCollector;
58import org.mockito.ArgumentCaptor;
59import org.mockito.InOrder;
60import org.mockito.Mock;
61import org.mockito.MockitoAnnotations;
62
63import java.io.PrintWriter;
64import java.io.StringWriter;
65import java.util.ArrayList;
66import java.util.HashMap;
67import java.util.Map;
68
69/**
70 * Unit test harness for HalDeviceManagerTest.
71 */
72public class HalDeviceManagerTest {
73    private HalDeviceManager mDut;
74    @Mock IServiceManager mServiceManagerMock;
75    @Mock IWifi mWifiMock;
76    @Mock HalDeviceManager.ManagerStatusListener mManagerStatusListenerMock;
77    private TestLooper mTestLooper;
78    private ArgumentCaptor<IHwBinder.DeathRecipient> mDeathRecipientCaptor =
79            ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
80    private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor =
81            ArgumentCaptor.forClass(IServiceNotification.Stub.class);
82    private ArgumentCaptor<IWifiEventCallback> mWifiEventCallbackCaptor = ArgumentCaptor.forClass(
83            IWifiEventCallback.class);
84    private InOrder mInOrder;
85    @Rule public ErrorCollector collector = new ErrorCollector();
86    private WifiStatus mStatusOk;
87    private WifiStatus mStatusFail;
88
89    private class HalDeviceManagerSpy extends HalDeviceManager {
90        @Override
91        protected IWifi getWifiServiceMockable() {
92            return mWifiMock;
93        }
94
95        @Override
96        protected IServiceManager getServiceManagerMockable() {
97            return mServiceManagerMock;
98        }
99    }
100
101    @Before
102    public void before() throws Exception {
103        MockitoAnnotations.initMocks(this);
104
105        mTestLooper = new TestLooper();
106
107        // initialize dummy status objects
108        mStatusOk = getStatus(WifiStatusCode.SUCCESS);
109        mStatusFail = getStatus(WifiStatusCode.ERROR_UNKNOWN);
110
111        when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
112                anyLong())).thenReturn(true);
113        when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
114                any(IServiceNotification.Stub.class))).thenReturn(true);
115        when(mWifiMock.linkToDeath(any(IHwBinder.DeathRecipient.class), anyLong())).thenReturn(
116                true);
117        when(mWifiMock.registerEventCallback(any(IWifiEventCallback.class))).thenReturn(mStatusOk);
118        when(mWifiMock.start()).thenReturn(mStatusOk);
119        when(mWifiMock.stop()).thenReturn(mStatusOk);
120
121        mDut = new HalDeviceManagerSpy();
122    }
123
124    /**
125     * Print out the dump of the device manager after each test. Not used in test validation
126     * (internal state) - but can help in debugging failed tests.
127     */
128    @After
129    public void after() throws Exception {
130        dumpDut("after: ");
131    }
132
133    /**
134     * Test basic startup flow:
135     * - IServiceManager registrations
136     * - IWifi registrations
137     * - IWifi startup delayed
138     * - Start Wi-Fi -> onStart
139     * - Stop Wi-Fi -> onStop
140     */
141    @Test
142    public void testStartStopFlow() throws Exception {
143        mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
144        executeAndValidateInitializationSequence();
145        executeAndValidateStartupSequence();
146
147        // act: stop Wi-Fi
148        mDut.stop();
149        mTestLooper.dispatchAll();
150
151        // verify: onStop called
152        mInOrder.verify(mWifiMock).stop();
153        mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
154
155        verifyNoMoreInteractions(mManagerStatusListenerMock);
156    }
157
158    /**
159     * Validate that multiple callback registrations are called and that duplicate ones are
160     * only called once.
161     */
162    @Test
163    public void testMultipleCallbackRegistrations() throws Exception {
164        mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
165        executeAndValidateInitializationSequence();
166
167        // register another 2 callbacks - one of them twice
168        HalDeviceManager.ManagerStatusListener callback1 = mock(
169                HalDeviceManager.ManagerStatusListener.class);
170        HalDeviceManager.ManagerStatusListener callback2 = mock(
171                HalDeviceManager.ManagerStatusListener.class);
172        mDut.registerStatusListener(callback2, mTestLooper.getLooper());
173        mDut.registerStatusListener(callback1, mTestLooper.getLooper());
174        mDut.registerStatusListener(callback2, mTestLooper.getLooper());
175
176        // startup
177        executeAndValidateStartupSequence();
178
179        // verify
180        verify(callback1).onStatusChanged();
181        verify(callback2).onStatusChanged();
182
183        verifyNoMoreInteractions(mManagerStatusListenerMock, callback1, callback2);
184    }
185
186    /**
187     * Validate IWifi death listener and registration flow.
188     */
189    @Test
190    public void testWifiDeathAndRegistration() throws Exception {
191        mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
192        executeAndValidateInitializationSequence();
193        executeAndValidateStartupSequence();
194
195        // act: IWifi service death
196        mDeathRecipientCaptor.getValue().serviceDied(0);
197        mTestLooper.dispatchAll();
198
199        // verify: getting onStop
200        mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
201
202        // act: service startup
203        mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", false);
204
205        // verify: initialization of IWifi
206        mInOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
207        mInOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
208
209        // act: start
210        mDut.start();
211        mWifiEventCallbackCaptor.getValue().onStart();
212        mTestLooper.dispatchAll();
213
214        // verify: service and callback calls
215        mInOrder.verify(mWifiMock).start();
216        mInOrder.verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
217
218        verifyNoMoreInteractions(mManagerStatusListenerMock);
219    }
220
221    /**
222     * Validate IWifi onFailure causes notification
223     */
224    @Test
225    public void testWifiFail() throws Exception {
226        mInOrder = inOrder(mServiceManagerMock, mWifiMock, mManagerStatusListenerMock);
227        executeAndValidateInitializationSequence();
228        executeAndValidateStartupSequence();
229
230        // act: IWifi failure
231        mWifiEventCallbackCaptor.getValue().onFailure(mStatusFail);
232        mTestLooper.dispatchAll();
233
234        // verify: getting onStop
235        mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
236
237        // act: start again
238        mDut.start();
239        mWifiEventCallbackCaptor.getValue().onStart();
240        mTestLooper.dispatchAll();
241
242        // verify: service and callback calls
243        mInOrder.verify(mWifiMock).start();
244        mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
245
246        verifyNoMoreInteractions(mManagerStatusListenerMock);
247    }
248
249    /**
250     * Validate creation of STA interface from blank start-up. The remove interface.
251     */
252    @Test
253    public void testCreateStaInterfaceNoInitMode() throws Exception {
254        final String name = "sta0";
255
256        BaselineChip chipMock = new BaselineChip();
257        chipMock.initialize();
258        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
259                mManagerStatusListenerMock);
260        executeAndValidateInitializationSequence();
261        executeAndValidateStartupSequence();
262
263        HalDeviceManager.InterfaceDestroyedListener idl = mock(
264                HalDeviceManager.InterfaceDestroyedListener.class);
265        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
266                HalDeviceManager.InterfaceAvailableForRequestListener.class);
267
268        IWifiStaIface iface = (IWifiStaIface) validateInterfaceSequence(chipMock,
269                false, // chipModeValid
270                -1000, // chipModeId (only used if chipModeValid is true)
271                IfaceType.STA, // ifaceTypeToCreate
272                name, // ifaceName
273                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
274                null, // tearDownList
275                idl, // destroyedListener
276                iafrl // availableListener
277        );
278        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
279
280        // act: remove interface
281        mDut.removeIface(iface);
282        mTestLooper.dispatchAll();
283
284        // verify: callback triggered
285        mInOrder.verify(chipMock.chip).removeStaIface(name);
286        verify(idl).onDestroyed();
287        verify(iafrl).onAvailableForRequest();
288
289        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
290    }
291
292    /**
293     * Validate creation of AP interface from blank start-up. The remove interface.
294     */
295    @Test
296    public void testCreateApInterfaceNoInitMode() throws Exception {
297        final String name = "ap0";
298
299        BaselineChip chipMock = new BaselineChip();
300        chipMock.initialize();
301        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
302                mManagerStatusListenerMock);
303        executeAndValidateInitializationSequence();
304        executeAndValidateStartupSequence();
305
306        HalDeviceManager.InterfaceDestroyedListener idl = mock(
307                HalDeviceManager.InterfaceDestroyedListener.class);
308        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
309                HalDeviceManager.InterfaceAvailableForRequestListener.class);
310
311        IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
312                false, // chipModeValid
313                -1000, // chipModeId (only used if chipModeValid is true)
314                IfaceType.AP, // ifaceTypeToCreate
315                name, // ifaceName
316                BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
317                null, // tearDownList
318                idl, // destroyedListener
319                iafrl // availableListener
320        );
321        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
322
323        // act: remove interface
324        mDut.removeIface(iface);
325        mTestLooper.dispatchAll();
326
327        // verify: callback triggered
328        mInOrder.verify(chipMock.chip).removeApIface(name);
329        verify(idl).onDestroyed();
330        verify(iafrl).onAvailableForRequest();
331
332        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
333    }
334
335    /**
336     * Validate creation of P2P interface from blank start-up. The remove interface.
337     */
338    @Test
339    public void testCreateP2pInterfaceNoInitMode() throws Exception {
340        final String name = "p2p0";
341
342        BaselineChip chipMock = new BaselineChip();
343        chipMock.initialize();
344        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
345                mManagerStatusListenerMock);
346        executeAndValidateInitializationSequence();
347        executeAndValidateStartupSequence();
348
349        HalDeviceManager.InterfaceDestroyedListener idl = mock(
350                HalDeviceManager.InterfaceDestroyedListener.class);
351        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
352                HalDeviceManager.InterfaceAvailableForRequestListener.class);
353
354        IWifiP2pIface iface = (IWifiP2pIface) validateInterfaceSequence(chipMock,
355                false, // chipModeValid
356                -1000, // chipModeId (only used if chipModeValid is true)
357                IfaceType.P2P, // ifaceTypeToCreate
358                name, // ifaceName
359                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
360                null, // tearDownList
361                idl, // destroyedListener
362                iafrl // availableListener
363        );
364        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
365
366        // act: remove interface
367        mDut.removeIface(iface);
368        mTestLooper.dispatchAll();
369
370        // verify: callback triggered
371        mInOrder.verify(chipMock.chip).removeP2pIface(name);
372        verify(idl).onDestroyed();
373        verify(iafrl).onAvailableForRequest();
374
375        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
376    }
377
378    /**
379     * Validate creation of NAN interface from blank start-up. The remove interface.
380     */
381    @Test
382    public void testCreateNanInterfaceNoInitMode() throws Exception {
383        final String name = "nan0";
384
385        BaselineChip chipMock = new BaselineChip();
386        chipMock.initialize();
387        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
388                mManagerStatusListenerMock);
389        executeAndValidateInitializationSequence();
390        executeAndValidateStartupSequence();
391
392        HalDeviceManager.InterfaceDestroyedListener idl = mock(
393                HalDeviceManager.InterfaceDestroyedListener.class);
394        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
395                HalDeviceManager.InterfaceAvailableForRequestListener.class);
396
397        IWifiNanIface iface = (IWifiNanIface) validateInterfaceSequence(chipMock,
398                false, // chipModeValid
399                -1000, // chipModeId (only used if chipModeValid is true)
400                IfaceType.NAN, // ifaceTypeToCreate
401                name, // ifaceName
402                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
403                null, // tearDownList
404                idl, // destroyedListener
405                iafrl // availableListener
406        );
407        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
408
409        // act: remove interface
410        mDut.removeIface(iface);
411        mTestLooper.dispatchAll();
412
413        // verify: callback triggered
414        mInOrder.verify(chipMock.chip).removeNanIface(name);
415        verify(idl).onDestroyed();
416        verify(iafrl).onAvailableForRequest();
417
418        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
419    }
420
421    /**
422     * Validate creation of AP interface when in STA mode - but with no interface created. Expect
423     * a change in chip mode.
424     */
425    @Test
426    public void testCreateApWithStaModeUp() throws Exception {
427        final String name = "ap0";
428
429        BaselineChip chipMock = new BaselineChip();
430        chipMock.initialize();
431        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
432                mManagerStatusListenerMock);
433        executeAndValidateInitializationSequence();
434        executeAndValidateStartupSequence();
435
436        HalDeviceManager.InterfaceDestroyedListener idl = mock(
437                HalDeviceManager.InterfaceDestroyedListener.class);
438        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
439                HalDeviceManager.InterfaceAvailableForRequestListener.class);
440
441        IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
442                true, // chipModeValid
443                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
444                IfaceType.AP, // ifaceTypeToCreate
445                name, // ifaceName
446                BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
447                null, // tearDownList
448                idl, // destroyedListener
449                iafrl // availableListener
450        );
451        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
452
453        // act: stop Wi-Fi
454        mDut.stop();
455        mTestLooper.dispatchAll();
456
457        // verify: callback triggered
458        verify(idl).onDestroyed();
459        verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
460
461        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
462    }
463
464    /**
465     * Validate creation of AP interface when in AP mode - but with no interface created. Expect
466     * no change in chip mode.
467     */
468    @Test
469    public void testCreateApWithApModeUp() throws Exception {
470        final String name = "ap0";
471
472        BaselineChip chipMock = new BaselineChip();
473        chipMock.initialize();
474        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
475                mManagerStatusListenerMock);
476        executeAndValidateInitializationSequence();
477        executeAndValidateStartupSequence();
478
479        HalDeviceManager.InterfaceDestroyedListener idl = mock(
480                HalDeviceManager.InterfaceDestroyedListener.class);
481        HalDeviceManager.InterfaceAvailableForRequestListener iafrl = mock(
482                HalDeviceManager.InterfaceAvailableForRequestListener.class);
483
484        IWifiApIface iface = (IWifiApIface) validateInterfaceSequence(chipMock,
485                true, // chipModeValid
486                BaselineChip.AP_CHIP_MODE_ID, // chipModeId
487                IfaceType.AP, // ifaceTypeToCreate
488                name, // ifaceName
489                BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
490                null, // tearDownList
491                idl, // destroyedListener
492                iafrl // availableListener
493        );
494        collector.checkThat("allocated interface", iface, IsNull.notNullValue());
495
496        // act: stop Wi-Fi
497        mDut.stop();
498        mTestLooper.dispatchAll();
499
500        // verify: callback triggered
501        verify(idl).onDestroyed();
502        verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
503
504        verifyNoMoreInteractions(mManagerStatusListenerMock, idl, iafrl);
505    }
506
507    /**
508     * Validate AP up/down creation of AP interface when a STA already created. Expect:
509     * - STA created
510     * - P2P created
511     * - When AP requested:
512     *   - STA & P2P torn down
513     *   - AP created
514     * - P2P creation refused
515     * - Request STA: will tear down AP
516     * - When AP destroyed:
517     *   - Get p2p available listener callback
518     *   - Can create P2P when requested
519     * - Create P2P
520     * - Request NAN: will get refused
521     * - Tear down P2P:
522     *    - should get nan available listener callback
523     *    - Can create NAN when requested
524     */
525    @Test
526    public void testCreateSameAndDiffPriorities() throws Exception {
527        BaselineChip chipMock = new BaselineChip();
528        chipMock.initialize();
529        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
530                mManagerStatusListenerMock);
531        executeAndValidateInitializationSequence();
532        executeAndValidateStartupSequence();
533
534        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
535                HalDeviceManager.InterfaceDestroyedListener.class);
536        HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
537                HalDeviceManager.InterfaceAvailableForRequestListener.class);
538
539        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock(
540                HalDeviceManager.InterfaceDestroyedListener.class);
541
542        HalDeviceManager.InterfaceDestroyedListener apDestroyedListener = mock(
543                HalDeviceManager.InterfaceDestroyedListener.class);
544        HalDeviceManager.InterfaceAvailableForRequestListener apAvailListener = mock(
545                HalDeviceManager.InterfaceAvailableForRequestListener.class);
546
547        HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock(
548                HalDeviceManager.InterfaceDestroyedListener.class);
549        HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = mock(
550                HalDeviceManager.InterfaceAvailableForRequestListener.class);
551
552        HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener2 = mock(
553                HalDeviceManager.InterfaceDestroyedListener.class);
554
555        HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
556                HalDeviceManager.InterfaceDestroyedListener.class);
557        HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
558                HalDeviceManager.InterfaceAvailableForRequestListener.class);
559
560        // Request STA
561        IWifiIface staIface = validateInterfaceSequence(chipMock,
562                false, // chipModeValid
563                -1000, // chipModeId (only used if chipModeValid is true)
564                IfaceType.STA, // ifaceTypeToCreate
565                "sta0", // ifaceName
566                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
567                null, // tearDownList
568                staDestroyedListener, // destroyedListener
569                staAvailListener // availableListener
570        );
571        collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
572
573        // register additional InterfaceDestroyedListeners - including a duplicate (verify that
574        // only called once!)
575        mDut.registerDestroyedListener(staIface, staDestroyedListener2, mTestLooper.getLooper());
576        mDut.registerDestroyedListener(staIface, staDestroyedListener, mTestLooper.getLooper());
577
578        // Request P2P
579        IWifiIface p2pIface = validateInterfaceSequence(chipMock,
580                true, // chipModeValid
581                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
582                IfaceType.P2P, // ifaceTypeToCreate
583                "p2p0", // ifaceName
584                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
585                null, // tearDownList
586                p2pDestroyedListener, // destroyedListener
587                p2pAvailListener // availableListener
588        );
589        collector.checkThat("allocated P2P interface", p2pIface, IsNull.notNullValue());
590
591        // Request AP
592        IWifiIface apIface = validateInterfaceSequence(chipMock,
593                true, // chipModeValid
594                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
595                IfaceType.AP, // ifaceTypeToCreate
596                "ap0", // ifaceName
597                BaselineChip.AP_CHIP_MODE_ID, // finalChipMode
598                new IWifiIface[]{staIface, p2pIface}, // tearDownList
599                apDestroyedListener, // destroyedListener
600                apAvailListener, // availableListener
601                // destroyedInterfacesDestroyedListeners...
602                staDestroyedListener, staDestroyedListener2, p2pDestroyedListener
603        );
604        collector.checkThat("allocated AP interface", apIface, IsNull.notNullValue());
605
606        // Request P2P: expect failure
607        p2pIface = mDut.createP2pIface(p2pDestroyedListener, mTestLooper.getLooper());
608        collector.checkThat("P2P can't be created", p2pIface, IsNull.nullValue());
609
610        // Request STA: expect success
611        staIface = validateInterfaceSequence(chipMock,
612                true, // chipModeValid
613                BaselineChip.AP_CHIP_MODE_ID, // chipModeId
614                IfaceType.STA, // ifaceTypeToCreate
615                "sta0", // ifaceName
616                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
617                null, // tearDownList
618                staDestroyedListener, // destroyedListener
619                staAvailListener, // availableListener
620                apDestroyedListener // destroyedInterfacesDestroyedListeners...
621        );
622        collector.checkThat("allocated STA interface", staIface, IsNull.notNullValue());
623
624        mTestLooper.dispatchAll();
625        verify(apDestroyedListener).onDestroyed();
626
627        // Request P2P: expect success now
628        p2pIface = validateInterfaceSequence(chipMock,
629                true, // chipModeValid
630                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
631                IfaceType.P2P, // ifaceTypeToCreate
632                "p2p0", // ifaceName
633                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
634                null, // tearDownList
635                p2pDestroyedListener2, // destroyedListener
636                p2pAvailListener // availableListener
637        );
638
639        // Request NAN: should fail
640        IWifiIface nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
641        mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
642                mTestLooper.getLooper());
643        collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
644
645        // Tear down P2P
646        mDut.removeIface(p2pIface);
647        mTestLooper.dispatchAll();
648
649        verify(chipMock.chip, times(2)).removeP2pIface("p2p0");
650        verify(p2pDestroyedListener2).onDestroyed();
651
652        // Should now be able to request and get NAN
653        nanIface = validateInterfaceSequence(chipMock,
654                true, // chipModeValid
655                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
656                IfaceType.NAN, // ifaceTypeToCreate
657                "nan0", // ifaceName
658                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
659                null, // tearDownList
660                nanDestroyedListener, // destroyedListener
661                nanAvailListener // availableListener
662        );
663        collector.checkThat("allocated NAN interface", nanIface, IsNull.notNullValue());
664
665        // available callback verification
666        verify(staAvailListener).onAvailableForRequest();
667        verify(apAvailListener, times(4)).onAvailableForRequest();
668        verify(p2pAvailListener, times(3)).onAvailableForRequest();
669        verify(nanAvailListener).onAvailableForRequest();
670
671        verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
672                staDestroyedListener2, apDestroyedListener, apAvailListener, p2pDestroyedListener,
673                nanDestroyedListener, nanAvailListener, p2pDestroyedListener2);
674    }
675
676    /**
677     * Validate P2P and NAN interactions. Expect:
678     * - STA created
679     * - NAN created
680     * - When P2P requested:
681     *   - NAN torn down
682     *   - P2P created
683     * - NAN creation refused
684     * - When P2P destroyed:
685     *   - get nan available listener
686     *   - Can create NAN when requested
687     */
688    @Test
689    public void testP2pAndNanInteractions() throws Exception {
690        BaselineChip chipMock = new BaselineChip();
691        chipMock.initialize();
692        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
693                mManagerStatusListenerMock);
694        executeAndValidateInitializationSequence();
695        executeAndValidateStartupSequence();
696
697        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
698                HalDeviceManager.InterfaceDestroyedListener.class);
699        HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
700                HalDeviceManager.InterfaceAvailableForRequestListener.class);
701
702        HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
703                HalDeviceManager.InterfaceDestroyedListener.class);
704        HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
705                HalDeviceManager.InterfaceAvailableForRequestListener.class);
706
707        HalDeviceManager.InterfaceDestroyedListener p2pDestroyedListener = mock(
708                HalDeviceManager.InterfaceDestroyedListener.class);
709        HalDeviceManager.InterfaceAvailableForRequestListener p2pAvailListener = null;
710
711        // Request STA
712        IWifiIface staIface = validateInterfaceSequence(chipMock,
713                false, // chipModeValid
714                -1000, // chipModeId (only used if chipModeValid is true)
715                IfaceType.STA, // ifaceTypeToCreate
716                "sta0", // ifaceName
717                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
718                null, // tearDownList
719                staDestroyedListener, // destroyedListener
720                staAvailListener // availableListener
721        );
722
723        // Request NAN
724        IWifiIface nanIface = validateInterfaceSequence(chipMock,
725                true, // chipModeValid
726                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
727                IfaceType.NAN, // ifaceTypeToCreate
728                "nan0", // ifaceName
729                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
730                null, // tearDownList
731                nanDestroyedListener, // destroyedListener
732                nanAvailListener // availableListener
733        );
734
735        // Request P2P
736        IWifiIface p2pIface = validateInterfaceSequence(chipMock,
737                true, // chipModeValid
738                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
739                IfaceType.P2P, // ifaceTypeToCreate
740                "p2p0", // ifaceName
741                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
742                new IWifiIface[]{nanIface}, // tearDownList
743                p2pDestroyedListener, // destroyedListener
744                p2pAvailListener, // availableListener
745                nanDestroyedListener // destroyedInterfacesDestroyedListeners...
746        );
747
748        // Request NAN: expect failure
749        nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
750        mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
751                mTestLooper.getLooper());
752        collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
753
754        // Destroy P2P interface
755        boolean status = mDut.removeIface(p2pIface);
756        mInOrder.verify(chipMock.chip).removeP2pIface("p2p0");
757        collector.checkThat("P2P removal success", status, equalTo(true));
758
759        mTestLooper.dispatchAll();
760        verify(p2pDestroyedListener).onDestroyed();
761        verify(nanAvailListener).onAvailableForRequest();
762
763        // Request NAN: expect success now
764        nanIface = validateInterfaceSequence(chipMock,
765                true, // chipModeValid
766                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
767                IfaceType.NAN, // ifaceTypeToCreate
768                "nan0", // ifaceName
769                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
770                null, // tearDownList
771                nanDestroyedListener, // destroyedListener
772                nanAvailListener // availableListener
773        );
774
775        verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
776                nanDestroyedListener, nanAvailListener, p2pDestroyedListener);
777    }
778
779    /**
780     * Validates that when (for some reason) the cache is out-of-sync with the actual chip status
781     * then Wi-Fi is shut-down.
782     */
783    @Test
784    public void testCacheMismatchError() throws Exception {
785        BaselineChip chipMock = new BaselineChip();
786        chipMock.initialize();
787        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
788                mManagerStatusListenerMock);
789        executeAndValidateInitializationSequence();
790        executeAndValidateStartupSequence();
791
792        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener = mock(
793                HalDeviceManager.InterfaceDestroyedListener.class);
794        HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
795                HalDeviceManager.InterfaceAvailableForRequestListener.class);
796
797        HalDeviceManager.InterfaceDestroyedListener nanDestroyedListener = mock(
798                HalDeviceManager.InterfaceDestroyedListener.class);
799        HalDeviceManager.InterfaceAvailableForRequestListener nanAvailListener = mock(
800                HalDeviceManager.InterfaceAvailableForRequestListener.class);
801
802        // Request STA
803        IWifiIface staIface = validateInterfaceSequence(chipMock,
804                false, // chipModeValid
805                -1000, // chipModeId (only used if chipModeValid is true)
806                IfaceType.STA, // ifaceTypeToCreate
807                "sta0", // ifaceName
808                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
809                null, // tearDownList
810                staDestroyedListener, // destroyedListener
811                staAvailListener // availableListener
812        );
813
814        // Request NAN
815        IWifiIface nanIface = validateInterfaceSequence(chipMock,
816                true, // chipModeValid
817                BaselineChip.STA_CHIP_MODE_ID, // chipModeId
818                IfaceType.NAN, // ifaceTypeToCreate
819                "nan0", // ifaceName
820                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
821                null, // tearDownList
822                nanDestroyedListener, // destroyedListener
823                nanAvailListener // availableListener
824        );
825
826        // fiddle with the "chip" by removing the STA
827        chipMock.interfaceNames.get(IfaceType.STA).remove("sta0");
828
829        // now try to request another NAN
830        nanIface = mDut.createNanIface(nanDestroyedListener, mTestLooper.getLooper());
831        mDut.registerInterfaceAvailableForRequestListener(IfaceType.NAN, nanAvailListener,
832                mTestLooper.getLooper());
833        collector.checkThat("NAN can't be created", nanIface, IsNull.nullValue());
834
835        // verify that Wi-Fi is shut-down: should also get all onDestroyed messages that are
836        // registered (even if they seem out-of-sync to chip)
837        mTestLooper.dispatchAll();
838        verify(mWifiMock).stop();
839        verify(mManagerStatusListenerMock, times(2)).onStatusChanged();
840        verify(staDestroyedListener).onDestroyed();
841        verify(nanDestroyedListener).onDestroyed();
842
843        verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener, staAvailListener,
844                nanDestroyedListener, nanAvailListener);
845    }
846
847    /**
848     * Validates that trying to allocate a STA and then another STA fails. Only one STA at a time
849     * is permitted (by baseline chip).
850     */
851    @Test
852    public void testDuplicateStaRequests() throws Exception {
853        BaselineChip chipMock = new BaselineChip();
854        chipMock.initialize();
855        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
856                mManagerStatusListenerMock);
857        executeAndValidateInitializationSequence();
858        executeAndValidateStartupSequence();
859
860        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener1 = mock(
861                HalDeviceManager.InterfaceDestroyedListener.class);
862        HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener1 = mock(
863                HalDeviceManager.InterfaceAvailableForRequestListener.class);
864
865        HalDeviceManager.InterfaceDestroyedListener staDestroyedListener2 = mock(
866                HalDeviceManager.InterfaceDestroyedListener.class);
867
868        // get STA interface
869        IWifiIface staIface1 = validateInterfaceSequence(chipMock,
870                false, // chipModeValid
871                -1000, // chipModeId (only used if chipModeValid is true)
872                IfaceType.STA, // ifaceTypeToCreate
873                "sta0", // ifaceName
874                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
875                null, // tearDownList
876                staDestroyedListener1, // destroyedListener
877                staAvailListener1 // availableListener
878        );
879        collector.checkThat("STA created", staIface1, IsNull.notNullValue());
880
881        // get STA interface again
882        IWifiIface staIface2 = mDut.createStaIface(staDestroyedListener2, mTestLooper.getLooper());
883        collector.checkThat("STA created", staIface2, IsNull.nullValue());
884
885        verifyNoMoreInteractions(mManagerStatusListenerMock, staDestroyedListener1,
886                staAvailListener1, staDestroyedListener2);
887    }
888
889    /**
890     * Validates that a duplicate registration of the same InterfaceAvailableForRequestListener
891     * listener will result in a single callback.
892     *
893     * Also validates that get an immediate call on registration if available.
894     */
895    @Test
896    public void testDuplicateAvailableRegistrations() throws Exception {
897        BaselineChip chipMock = new BaselineChip();
898        chipMock.initialize();
899        mInOrder = inOrder(mServiceManagerMock, mWifiMock, chipMock.chip,
900                mManagerStatusListenerMock);
901        executeAndValidateInitializationSequence();
902        executeAndValidateStartupSequence();
903
904        HalDeviceManager.InterfaceAvailableForRequestListener staAvailListener = mock(
905                HalDeviceManager.InterfaceAvailableForRequestListener.class);
906
907        // get STA interface
908        IWifiIface staIface = validateInterfaceSequence(chipMock,
909                false, // chipModeValid
910                -1000, // chipModeId (only used if chipModeValid is true)
911                IfaceType.STA, // ifaceTypeToCreate
912                "sta0", // ifaceName
913                BaselineChip.STA_CHIP_MODE_ID, // finalChipMode
914                null, // tearDownList
915                null, // destroyedListener
916                null // availableListener
917        );
918        collector.checkThat("STA created", staIface, IsNull.notNullValue());
919
920        // act: register the same listener twice
921        mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
922                mTestLooper.getLooper());
923        mDut.registerInterfaceAvailableForRequestListener(IfaceType.STA, staAvailListener,
924                mTestLooper.getLooper());
925        mTestLooper.dispatchAll();
926
927        // remove STA interface -> should trigger callbacks
928        mDut.removeIface(staIface);
929        mTestLooper.dispatchAll();
930
931        // verify: only a single trigger
932        verify(staAvailListener).onAvailableForRequest();
933
934        verifyNoMoreInteractions(staAvailListener);
935    }
936
937    // utilities
938    private void dumpDut(String prefix) {
939        StringWriter sw = new StringWriter();
940        mDut.dump(null, new PrintWriter(sw), null);
941        Log.e("HalDeviceManager", prefix + sw.toString());
942    }
943
944    private void executeAndValidateInitializationSequence() throws Exception {
945        InOrder inOrder = inOrder(mServiceManagerMock, mWifiMock);
946
947        // act:
948        mDut.initialize();
949
950        // verify: service manager initialization sequence
951        mInOrder.verify(mServiceManagerMock).linkToDeath(any(IHwBinder.DeathRecipient.class),
952                anyLong());
953        inOrder.verify(mServiceManagerMock).registerForNotifications(eq(IWifi.kInterfaceName),
954                eq(""), mServiceNotificationCaptor.capture());
955
956        // act: get the service started (which happens even when service was already up)
957        mServiceNotificationCaptor.getValue().onRegistration(IWifi.kInterfaceName, "", true);
958
959        // verify: wifi initialization sequence
960        inOrder.verify(mWifiMock).linkToDeath(mDeathRecipientCaptor.capture(), anyLong());
961        inOrder.verify(mWifiMock).registerEventCallback(mWifiEventCallbackCaptor.capture());
962        collector.checkThat("isReady is true", mDut.isReady(), equalTo(true));
963    }
964
965    private void executeAndValidateStartupSequence() throws Exception {
966        // act: register listener & start Wi-Fi
967        mDut.registerStatusListener(mManagerStatusListenerMock, mTestLooper.getLooper());
968        mDut.start();
969
970        // verify
971        mInOrder.verify(mWifiMock).start();
972
973        // act: trigger onStart callback of IWifiEventCallback
974        mWifiEventCallbackCaptor.getValue().onStart();
975        mTestLooper.dispatchAll();
976
977        // verify: onStart called on registered listener
978        mInOrder.verify(mManagerStatusListenerMock).onStatusChanged();
979    }
980
981    private IWifiIface validateInterfaceSequence(ChipMockBase chipMock,
982            boolean chipModeValid, int chipModeId,
983            int ifaceTypeToCreate, String ifaceName, int finalChipMode, IWifiIface[] tearDownList,
984            HalDeviceManager.InterfaceDestroyedListener destroyedListener,
985            HalDeviceManager.InterfaceAvailableForRequestListener availableListener,
986            HalDeviceManager.InterfaceDestroyedListener... destroyedInterfacesDestroyedListeners)
987            throws Exception {
988        // configure chip mode response
989        chipMock.chipModeValid = chipModeValid;
990        chipMock.chipModeId = chipModeId;
991
992        IWifiIface iface = null;
993
994        // configure: interface to be created
995        // act: request the interface
996        switch (ifaceTypeToCreate) {
997            case IfaceType.STA:
998                iface = mock(IWifiStaIface.class);
999                doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
1000                        any(IWifiIface.getNameCallback.class));
1001                doAnswer(new GetTypeAnswer(IfaceType.STA)).when(iface).getType(
1002                        any(IWifiIface.getTypeCallback.class));
1003                doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
1004                        chipMock.chip).createStaIface(any(IWifiChip.createStaIfaceCallback.class));
1005
1006                mDut.createStaIface(destroyedListener, mTestLooper.getLooper());
1007                break;
1008            case IfaceType.AP:
1009                iface = mock(IWifiApIface.class);
1010                doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
1011                        any(IWifiIface.getNameCallback.class));
1012                doAnswer(new GetTypeAnswer(IfaceType.AP)).when(iface).getType(
1013                        any(IWifiIface.getTypeCallback.class));
1014                doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
1015                        chipMock.chip).createApIface(any(IWifiChip.createApIfaceCallback.class));
1016
1017                mDut.createApIface(destroyedListener, mTestLooper.getLooper());
1018                break;
1019            case IfaceType.P2P:
1020                iface = mock(IWifiP2pIface.class);
1021                doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
1022                        any(IWifiIface.getNameCallback.class));
1023                doAnswer(new GetTypeAnswer(IfaceType.P2P)).when(iface).getType(
1024                        any(IWifiIface.getTypeCallback.class));
1025                doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
1026                        chipMock.chip).createP2pIface(any(IWifiChip.createP2pIfaceCallback.class));
1027
1028                mDut.createP2pIface(destroyedListener, mTestLooper.getLooper());
1029                break;
1030            case IfaceType.NAN:
1031                iface = mock(IWifiNanIface.class);
1032                doAnswer(new GetNameAnswer(ifaceName)).when(iface).getName(
1033                        any(IWifiIface.getNameCallback.class));
1034                doAnswer(new GetTypeAnswer(IfaceType.NAN)).when(iface).getType(
1035                        any(IWifiIface.getTypeCallback.class));
1036                doAnswer(new CreateXxxIfaceAnswer(chipMock, mStatusOk, iface)).when(
1037                        chipMock.chip).createNanIface(any(IWifiChip.createNanIfaceCallback.class));
1038
1039                mDut.createNanIface(destroyedListener, mTestLooper.getLooper());
1040                break;
1041        }
1042        if (availableListener != null) {
1043            mDut.registerInterfaceAvailableForRequestListener(ifaceTypeToCreate, availableListener,
1044                    mTestLooper.getLooper());
1045        }
1046
1047        // validate: optional tear down of interfaces
1048        if (tearDownList != null) {
1049            for (IWifiIface tearDownIface: tearDownList) {
1050                switch (getType(tearDownIface)) {
1051                    case IfaceType.STA:
1052                        mInOrder.verify(chipMock.chip).removeStaIface(getName(tearDownIface));
1053                        break;
1054                    case IfaceType.AP:
1055                        mInOrder.verify(chipMock.chip).removeApIface(getName(tearDownIface));
1056                        break;
1057                    case IfaceType.P2P:
1058                        mInOrder.verify(chipMock.chip).removeP2pIface(getName(tearDownIface));
1059                        break;
1060                    case IfaceType.NAN:
1061                        mInOrder.verify(chipMock.chip).removeNanIface(getName(tearDownIface));
1062                        break;
1063                }
1064            }
1065        }
1066
1067        // validate: optional switch to the requested mode
1068        if (!chipModeValid || chipModeId != finalChipMode) {
1069            mInOrder.verify(chipMock.chip).configureChip(finalChipMode);
1070        } else {
1071            mInOrder.verify(chipMock.chip, times(0)).configureChip(anyInt());
1072        }
1073
1074        // validate: create interface
1075        switch (ifaceTypeToCreate) {
1076            case IfaceType.STA:
1077                mInOrder.verify(chipMock.chip).createStaIface(
1078                        any(IWifiChip.createStaIfaceCallback.class));
1079                break;
1080            case IfaceType.AP:
1081                mInOrder.verify(chipMock.chip).createApIface(
1082                        any(IWifiChip.createApIfaceCallback.class));
1083                break;
1084            case IfaceType.P2P:
1085                mInOrder.verify(chipMock.chip).createP2pIface(
1086                        any(IWifiChip.createP2pIfaceCallback.class));
1087                break;
1088            case IfaceType.NAN:
1089                mInOrder.verify(chipMock.chip).createNanIface(
1090                        any(IWifiChip.createNanIfaceCallback.class));
1091                break;
1092        }
1093
1094        // verify: callbacks on deleted interfaces
1095        mTestLooper.dispatchAll();
1096        for (int i = 0; i < destroyedInterfacesDestroyedListeners.length; ++i) {
1097            verify(destroyedInterfacesDestroyedListeners[i]).onDestroyed();
1098        }
1099
1100        return iface;
1101    }
1102
1103    private int getType(IWifiIface iface) throws Exception {
1104        Mutable<Integer> typeResp = new Mutable<>();
1105        iface.getType((WifiStatus status, int type) -> {
1106            typeResp.value = type;
1107        });
1108        return typeResp.value;
1109    }
1110
1111    private String getName(IWifiIface iface) throws Exception {
1112        Mutable<String> nameResp = new Mutable<>();
1113        iface.getName((WifiStatus status, String name) -> {
1114            nameResp.value = name;
1115        });
1116        return nameResp.value;
1117    }
1118
1119    private WifiStatus getStatus(int code) {
1120        WifiStatus status = new WifiStatus();
1121        status.code = code;
1122        return status;
1123    }
1124
1125    private static class Mutable<E> {
1126        public E value;
1127
1128        Mutable() {
1129            value = null;
1130        }
1131
1132        Mutable(E value) {
1133            this.value = value;
1134        }
1135    }
1136
1137    // Answer objects
1138    private class GetChipIdsAnswer extends MockAnswerUtil.AnswerWithArguments {
1139        private WifiStatus mStatus;
1140        private ArrayList<Integer> mChipIds;
1141
1142        GetChipIdsAnswer(WifiStatus status, ArrayList<Integer> chipIds) {
1143            mStatus = status;
1144            mChipIds = chipIds;
1145        }
1146
1147        public void answer(IWifi.getChipIdsCallback cb) {
1148            cb.onValues(mStatus, mChipIds);
1149        }
1150    }
1151
1152    private class GetChipAnswer extends MockAnswerUtil.AnswerWithArguments {
1153        private WifiStatus mStatus;
1154        private IWifiChip mChip;
1155
1156        GetChipAnswer(WifiStatus status, IWifiChip chip) {
1157            mStatus = status;
1158            mChip = chip;
1159        }
1160
1161        public void answer(int chipId, IWifi.getChipCallback cb) {
1162            cb.onValues(mStatus, mChip);
1163        }
1164    }
1165
1166    private class GetAvailableModesAnswer extends MockAnswerUtil.AnswerWithArguments {
1167        private ChipMockBase mChipMockBase;
1168
1169        GetAvailableModesAnswer(ChipMockBase chipMockBase) {
1170            mChipMockBase = chipMockBase;
1171        }
1172
1173        public void answer(IWifiChip.getAvailableModesCallback cb) {
1174            cb.onValues(mStatusOk, mChipMockBase.availableModes);
1175        }
1176    }
1177
1178    private class GetModeAnswer extends MockAnswerUtil.AnswerWithArguments {
1179        private ChipMockBase mChipMockBase;
1180
1181        GetModeAnswer(ChipMockBase chipMockBase) {
1182            mChipMockBase = chipMockBase;
1183        }
1184
1185        public void answer(IWifiChip.getModeCallback cb) {
1186            cb.onValues(mChipMockBase.chipModeValid ? mStatusOk
1187                    : getStatus(WifiStatusCode.ERROR_NOT_AVAILABLE), mChipMockBase.chipModeId);
1188        }
1189    }
1190
1191    private class ConfigureChipAnswer extends MockAnswerUtil.AnswerWithArguments {
1192        private ChipMockBase mChipMockBase;
1193
1194        ConfigureChipAnswer(ChipMockBase chipMockBase) {
1195            mChipMockBase = chipMockBase;
1196        }
1197
1198        public WifiStatus answer(int chipMode) {
1199            mChipMockBase.chipModeId = chipMode;
1200            return mStatusOk;
1201        }
1202    }
1203
1204    private class GetXxxIfaceNamesAnswer extends MockAnswerUtil.AnswerWithArguments {
1205        private ChipMockBase mChipMockBase;
1206
1207        GetXxxIfaceNamesAnswer(ChipMockBase chipMockBase) {
1208            mChipMockBase = chipMockBase;
1209        }
1210
1211        public void answer(IWifiChip.getStaIfaceNamesCallback cb) {
1212            cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.STA));
1213        }
1214
1215        public void answer(IWifiChip.getApIfaceNamesCallback cb) {
1216            cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.AP));
1217        }
1218
1219        public void answer(IWifiChip.getP2pIfaceNamesCallback cb) {
1220            cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.P2P));
1221        }
1222
1223        public void answer(IWifiChip.getNanIfaceNamesCallback cb) {
1224            cb.onValues(mStatusOk, mChipMockBase.interfaceNames.get(IfaceType.NAN));
1225        }
1226    }
1227
1228    private class GetXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
1229        private ChipMockBase mChipMockBase;
1230
1231        GetXxxIfaceAnswer(ChipMockBase chipMockBase) {
1232            mChipMockBase = chipMockBase;
1233        }
1234
1235        public void answer(String name, IWifiChip.getStaIfaceCallback cb) {
1236            IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.STA).get(name);
1237            cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiStaIface) iface);
1238        }
1239
1240        public void answer(String name, IWifiChip.getApIfaceCallback cb) {
1241            IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.AP).get(name);
1242            cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiApIface) iface);
1243        }
1244
1245        public void answer(String name, IWifiChip.getP2pIfaceCallback cb) {
1246            IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.P2P).get(name);
1247            cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiP2pIface) iface);
1248        }
1249
1250        public void answer(String name, IWifiChip.getNanIfaceCallback cb) {
1251            IWifiIface iface = mChipMockBase.interfacesByName.get(IfaceType.NAN).get(name);
1252            cb.onValues(iface != null ? mStatusOk : mStatusFail, (IWifiNanIface) iface);
1253        }
1254    }
1255
1256    private class CreateXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
1257        private ChipMockBase mChipMockBase;
1258        private WifiStatus mStatus;
1259        private IWifiIface mWifiIface;
1260
1261        CreateXxxIfaceAnswer(ChipMockBase chipMockBase, WifiStatus status, IWifiIface wifiIface) {
1262            mChipMockBase = chipMockBase;
1263            mStatus = status;
1264            mWifiIface = wifiIface;
1265        }
1266
1267        private void addInterfaceInfo(int type) {
1268            if (mStatus.code == WifiStatusCode.SUCCESS) {
1269                try {
1270                    mChipMockBase.interfaceNames.get(type).add(getName(mWifiIface));
1271                    mChipMockBase.interfacesByName.get(type).put(getName(mWifiIface), mWifiIface);
1272                } catch (Exception e) {
1273                    // do nothing
1274                }
1275            }
1276        }
1277
1278        public void answer(IWifiChip.createStaIfaceCallback cb) {
1279            cb.onValues(mStatus, (IWifiStaIface) mWifiIface);
1280            addInterfaceInfo(IfaceType.STA);
1281        }
1282
1283        public void answer(IWifiChip.createApIfaceCallback cb) {
1284            cb.onValues(mStatus, (IWifiApIface) mWifiIface);
1285            addInterfaceInfo(IfaceType.AP);
1286        }
1287
1288        public void answer(IWifiChip.createP2pIfaceCallback cb) {
1289            cb.onValues(mStatus, (IWifiP2pIface) mWifiIface);
1290            addInterfaceInfo(IfaceType.P2P);
1291        }
1292
1293        public void answer(IWifiChip.createNanIfaceCallback cb) {
1294            cb.onValues(mStatus, (IWifiNanIface) mWifiIface);
1295            addInterfaceInfo(IfaceType.NAN);
1296        }
1297    }
1298
1299    private class RemoveXxxIfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
1300        private ChipMockBase mChipMockBase;
1301        private int mType;
1302
1303        RemoveXxxIfaceAnswer(ChipMockBase chipMockBase, int type) {
1304            mChipMockBase = chipMockBase;
1305            mType = type;
1306        }
1307
1308        private WifiStatus removeIface(int type, String ifname) {
1309            try {
1310                if (!mChipMockBase.interfaceNames.get(type).remove(ifname)) {
1311                    return mStatusFail;
1312                }
1313                if (mChipMockBase.interfacesByName.get(type).remove(ifname) == null) {
1314                    return mStatusFail;
1315                }
1316            } catch (Exception e) {
1317                return mStatusFail;
1318            }
1319            return mStatusOk;
1320        }
1321
1322        public WifiStatus answer(String ifname) {
1323            return removeIface(mType, ifname);
1324        }
1325    }
1326
1327    private class GetNameAnswer extends MockAnswerUtil.AnswerWithArguments {
1328        private String mName;
1329
1330        GetNameAnswer(String name) {
1331            mName = name;
1332        }
1333
1334        public void answer(IWifiIface.getNameCallback cb) {
1335            cb.onValues(mStatusOk, mName);
1336        }
1337    }
1338
1339    private class GetTypeAnswer extends MockAnswerUtil.AnswerWithArguments {
1340        private int mType;
1341
1342        GetTypeAnswer(int type) {
1343            mType = type;
1344        }
1345
1346        public void answer(IWifiIface.getTypeCallback cb) {
1347            cb.onValues(mStatusOk, mType);
1348        }
1349    }
1350
1351    // chip configuration
1352
1353    private class ChipMockBase {
1354        public IWifiChip chip;
1355        public int chipId;
1356        public boolean chipModeValid = false;
1357        public int chipModeId = -1000;
1358        public Map<Integer, ArrayList<String>> interfaceNames = new HashMap<>();
1359        public Map<Integer, Map<String, IWifiIface>> interfacesByName = new HashMap<>();
1360
1361        public ArrayList<IWifiChip.ChipMode> availableModes;
1362
1363        void initialize() throws Exception {
1364            chip = mock(IWifiChip.class);
1365
1366            interfaceNames.put(IfaceType.STA, new ArrayList<>());
1367            interfaceNames.put(IfaceType.AP, new ArrayList<>());
1368            interfaceNames.put(IfaceType.P2P, new ArrayList<>());
1369            interfaceNames.put(IfaceType.NAN, new ArrayList<>());
1370
1371            interfacesByName.put(IfaceType.STA, new HashMap<>());
1372            interfacesByName.put(IfaceType.AP, new HashMap<>());
1373            interfacesByName.put(IfaceType.P2P, new HashMap<>());
1374            interfacesByName.put(IfaceType.NAN, new HashMap<>());
1375
1376            when(chip.registerEventCallback(any(IWifiChipEventCallback.class))).thenReturn(
1377                    mStatusOk);
1378            when(chip.configureChip(anyInt())).thenAnswer(new ConfigureChipAnswer(this));
1379            doAnswer(new GetModeAnswer(this)).when(chip).getMode(
1380                    any(IWifiChip.getModeCallback.class));
1381            GetXxxIfaceNamesAnswer getXxxIfaceNamesAnswer = new GetXxxIfaceNamesAnswer(this);
1382            doAnswer(getXxxIfaceNamesAnswer).when(chip).getStaIfaceNames(
1383                    any(IWifiChip.getStaIfaceNamesCallback.class));
1384            doAnswer(getXxxIfaceNamesAnswer).when(chip).getApIfaceNames(
1385                    any(IWifiChip.getApIfaceNamesCallback.class));
1386            doAnswer(getXxxIfaceNamesAnswer).when(chip).getP2pIfaceNames(
1387                    any(IWifiChip.getP2pIfaceNamesCallback.class));
1388            doAnswer(getXxxIfaceNamesAnswer).when(chip).getNanIfaceNames(
1389                    any(IWifiChip.getNanIfaceNamesCallback.class));
1390            GetXxxIfaceAnswer getXxxIfaceAnswer = new GetXxxIfaceAnswer(this);
1391            doAnswer(getXxxIfaceAnswer).when(chip).getStaIface(anyString(),
1392                    any(IWifiChip.getStaIfaceCallback.class));
1393            doAnswer(getXxxIfaceAnswer).when(chip).getApIface(anyString(),
1394                    any(IWifiChip.getApIfaceCallback.class));
1395            doAnswer(getXxxIfaceAnswer).when(chip).getP2pIface(anyString(),
1396                    any(IWifiChip.getP2pIfaceCallback.class));
1397            doAnswer(getXxxIfaceAnswer).when(chip).getNanIface(anyString(),
1398                    any(IWifiChip.getNanIfaceCallback.class));
1399            doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.STA)).when(chip).removeStaIface(
1400                    anyString());
1401            doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.AP)).when(chip).removeApIface(
1402                    anyString());
1403            doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.P2P)).when(chip).removeP2pIface(
1404                    anyString());
1405            doAnswer(new RemoveXxxIfaceAnswer(this, IfaceType.NAN)).when(chip).removeNanIface(
1406                    anyString());
1407        }
1408    }
1409
1410    // emulate baseline/legacy config:
1411    // mode: STA + NAN || P2P
1412    // mode: NAN
1413    private class BaselineChip extends ChipMockBase {
1414        static final int STA_CHIP_MODE_ID = 0;
1415        static final int AP_CHIP_MODE_ID = 1;
1416
1417        void initialize() throws Exception {
1418            super.initialize();
1419
1420            // chip Id configuration
1421            ArrayList<Integer> chipIds;
1422            chipId = 10;
1423            chipIds = new ArrayList<>();
1424            chipIds.add(chipId);
1425            doAnswer(new GetChipIdsAnswer(mStatusOk, chipIds)).when(mWifiMock).getChipIds(
1426                    any(IWifi.getChipIdsCallback.class));
1427
1428            doAnswer(new GetChipAnswer(mStatusOk, chip)).when(mWifiMock).getChip(eq(10),
1429                    any(IWifi.getChipCallback.class));
1430
1431            // initialize dummy chip modes
1432            IWifiChip.ChipMode cm;
1433            IWifiChip.ChipIfaceCombination cic;
1434            IWifiChip.ChipIfaceCombinationLimit cicl;
1435
1436            //   Mode 0: 1xSTA + 1x{P2P,NAN}
1437            //   Mode 1: 1xAP
1438            availableModes = new ArrayList<>();
1439            cm = new IWifiChip.ChipMode();
1440            cm.id = STA_CHIP_MODE_ID;
1441
1442            cic = new IWifiChip.ChipIfaceCombination();
1443
1444            cicl = new IWifiChip.ChipIfaceCombinationLimit();
1445            cicl.maxIfaces = 1;
1446            cicl.types.add(IfaceType.STA);
1447            cic.limits.add(cicl);
1448
1449            cicl = new IWifiChip.ChipIfaceCombinationLimit();
1450            cicl.maxIfaces = 1;
1451            cicl.types.add(IfaceType.P2P);
1452            cicl.types.add(IfaceType.NAN);
1453            cic.limits.add(cicl);
1454            cm.availableCombinations.add(cic);
1455            availableModes.add(cm);
1456
1457            cm = new IWifiChip.ChipMode();
1458            cm.id = AP_CHIP_MODE_ID;
1459            cic = new IWifiChip.ChipIfaceCombination();
1460            cicl = new IWifiChip.ChipIfaceCombinationLimit();
1461            cicl.maxIfaces = 1;
1462            cicl.types.add(IfaceType.AP);
1463            cic.limits.add(cicl);
1464            cm.availableCombinations.add(cic);
1465            availableModes.add(cm);
1466
1467            doAnswer(new GetAvailableModesAnswer(this)).when(chip)
1468                    .getAvailableModes(any(IWifiChip.getAvailableModesCallback.class));
1469        }
1470    }
1471}
1472