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