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 */
16package com.android.server.wifi;
17
18import static org.junit.Assert.*;
19import static org.mockito.Matchers.any;
20import static org.mockito.Matchers.anyBoolean;
21import static org.mockito.Matchers.anyInt;
22import static org.mockito.Matchers.anyLong;
23import static org.mockito.Matchers.anyShort;
24import static org.mockito.Matchers.anyString;
25import static org.mockito.Matchers.eq;
26import static org.mockito.Mockito.*;
27
28import android.app.test.MockAnswerUtil;
29import android.content.Context;
30import android.hardware.wifi.supplicant.V1_0.ISupplicant;
31import android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
32import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
33import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
34import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.BssidChangeReason;
35import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
36import android.hardware.wifi.supplicant.V1_0.IfaceType;
37import android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
38import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
39import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
40import android.hidl.manager.V1_0.IServiceManager;
41import android.hidl.manager.V1_0.IServiceNotification;
42import android.net.IpConfiguration;
43import android.net.wifi.SupplicantState;
44import android.net.wifi.WifiConfiguration;
45import android.net.wifi.WifiManager;
46import android.net.wifi.WifiSsid;
47import android.os.IHwBinder;
48import android.os.RemoteException;
49import android.text.TextUtils;
50import android.util.SparseArray;
51
52import com.android.server.wifi.hotspot2.AnqpEvent;
53import com.android.server.wifi.hotspot2.IconEvent;
54import com.android.server.wifi.hotspot2.WnmData;
55import com.android.server.wifi.util.NativeUtil;
56
57import libcore.util.NonNull;
58
59import org.junit.Before;
60import org.junit.Test;
61import org.mockito.ArgumentCaptor;
62import org.mockito.InOrder;
63import org.mockito.Mock;
64import org.mockito.MockitoAnnotations;
65
66import java.nio.ByteBuffer;
67import java.nio.ByteOrder;
68import java.util.ArrayList;
69import java.util.Arrays;
70import java.util.HashMap;
71import java.util.Map;
72import java.util.Random;
73
74/**
75 * Unit tests for SupplicantStaIfaceHal
76 */
77public class SupplicantStaIfaceHalTest {
78    private static final String TAG = "SupplicantStaIfaceHalTest";
79    private static final Map<Integer, String> NETWORK_ID_TO_SSID = new HashMap<Integer, String>() {{
80            put(1, "\"ssid1\"");
81            put(2, "\"ssid2\"");
82            put(3, "\"ssid3\"");
83        }};
84    private static final int SUPPLICANT_NETWORK_ID = 2;
85    private static final String SUPPLICANT_SSID = NETWORK_ID_TO_SSID.get(SUPPLICANT_NETWORK_ID);
86    private static final int ROAM_NETWORK_ID = 4;
87    private static final String BSSID = "fa:45:23:23:12:12";
88    private static final String WLAN0_IFACE_NAME = "wlan0";
89    private static final String WLAN1_IFACE_NAME = "wlan1";
90    private static final String P2P_IFACE_NAME = "p2p0";
91    private static final String ICON_FILE_NAME  = "blahblah";
92    private static final int ICON_FILE_SIZE = 72;
93    private static final String HS20_URL = "http://blahblah";
94
95    private @Mock IServiceManager mServiceManagerMock;
96    private @Mock ISupplicant mISupplicantMock;
97    private android.hardware.wifi.supplicant.V1_1.ISupplicant mISupplicantMockV1_1;
98    private @Mock ISupplicantIface mISupplicantIfaceMock;
99    private @Mock ISupplicantStaIface mISupplicantStaIfaceMock;
100    private @Mock android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface
101            mISupplicantStaIfaceMockV1_1;
102    private @Mock Context mContext;
103    private @Mock WifiMonitor mWifiMonitor;
104    private @Mock SupplicantStaNetworkHal mSupplicantStaNetworkMock;
105    private @Mock WifiNative.SupplicantDeathEventHandler mSupplicantHalDeathHandler;
106    SupplicantStatus mStatusSuccess;
107    SupplicantStatus mStatusFailure;
108    ISupplicant.IfaceInfo mStaIface0;
109    ISupplicant.IfaceInfo mStaIface1;
110    ISupplicant.IfaceInfo mP2pIface;
111    ArrayList<ISupplicant.IfaceInfo> mIfaceInfoList;
112    ISupplicantStaIfaceCallback mISupplicantStaIfaceCallback;
113    android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback
114            mISupplicantStaIfaceCallbackV1_1;
115    private SupplicantStaIfaceHal mDut;
116    private ArgumentCaptor<IHwBinder.DeathRecipient> mServiceManagerDeathCaptor =
117            ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
118    private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantDeathCaptor =
119            ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
120    private ArgumentCaptor<IHwBinder.DeathRecipient> mSupplicantStaIfaceDeathCaptor =
121            ArgumentCaptor.forClass(IHwBinder.DeathRecipient.class);
122    private ArgumentCaptor<IServiceNotification.Stub> mServiceNotificationCaptor =
123            ArgumentCaptor.forClass(IServiceNotification.Stub.class);
124    private InOrder mInOrder;
125
126    private class SupplicantStaIfaceHalSpy extends SupplicantStaIfaceHal {
127        SupplicantStaIfaceHalSpy(Context context, WifiMonitor monitor) {
128            super(context, monitor);
129        }
130
131        @Override
132        protected IServiceManager getServiceManagerMockable() throws RemoteException {
133            return mServiceManagerMock;
134        }
135
136        @Override
137        protected ISupplicant getSupplicantMockable() throws RemoteException {
138            return mISupplicantMock;
139        }
140
141        @Override
142        protected android.hardware.wifi.supplicant.V1_1.ISupplicant getSupplicantMockableV1_1()
143                throws RemoteException {
144            return mISupplicantMockV1_1;
145        }
146
147        @Override
148        protected ISupplicantStaIface getStaIfaceMockable(ISupplicantIface iface) {
149            return mISupplicantStaIfaceMock;
150        }
151
152        @Override
153        protected android.hardware.wifi.supplicant.V1_1.ISupplicantStaIface
154                getStaIfaceMockableV1_1(ISupplicantIface iface) {
155            return mISupplicantStaIfaceMockV1_1;
156        }
157
158        @Override
159        protected SupplicantStaNetworkHal getStaNetworkMockable(
160                @NonNull String ifaceName,
161                ISupplicantStaNetwork iSupplicantStaNetwork) {
162            return mSupplicantStaNetworkMock;
163        }
164    }
165
166    @Before
167    public void setUp() throws Exception {
168        MockitoAnnotations.initMocks(this);
169        mStatusSuccess = createSupplicantStatus(SupplicantStatusCode.SUCCESS);
170        mStatusFailure = createSupplicantStatus(SupplicantStatusCode.FAILURE_UNKNOWN);
171        mStaIface0 = createIfaceInfo(IfaceType.STA, WLAN0_IFACE_NAME);
172        mStaIface1 = createIfaceInfo(IfaceType.STA, WLAN1_IFACE_NAME);
173        mP2pIface = createIfaceInfo(IfaceType.P2P, P2P_IFACE_NAME);
174
175        mIfaceInfoList = new ArrayList<>();
176        mIfaceInfoList.add(mStaIface0);
177        mIfaceInfoList.add(mStaIface1);
178        mIfaceInfoList.add(mP2pIface);
179
180        when(mServiceManagerMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
181                anyLong())).thenReturn(true);
182        when(mServiceManagerMock.registerForNotifications(anyString(), anyString(),
183                any(IServiceNotification.Stub.class))).thenReturn(true);
184        when(mISupplicantMock.linkToDeath(any(IHwBinder.DeathRecipient.class),
185                anyLong())).thenReturn(true);
186        mDut = new SupplicantStaIfaceHalSpy(mContext, mWifiMonitor);
187    }
188
189    /**
190     * Sunny day scenario for SupplicantStaIfaceHal initialization
191     * Asserts successful initialization
192     */
193    @Test
194    public void testInitialize_success() throws Exception {
195        executeAndValidateInitializationSequence(false, false, false, false);
196    }
197
198    /**
199     * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called
200     * Ensures initialization fails.
201     */
202    @Test
203    public void testInitialize_remoteExceptionFailure() throws Exception {
204        executeAndValidateInitializationSequence(true, false, false, false);
205    }
206
207    /**
208     * Tests the initialization flow, with listInterfaces returning 0 interfaces.
209     * Ensures failure
210     */
211    @Test
212    public void testInitialize_zeroInterfacesFailure() throws Exception {
213        executeAndValidateInitializationSequence(false, true, false, false);
214    }
215
216    /**
217     * Tests the initialization flow, with a null interface being returned by getInterface.
218     * Ensures initialization fails.
219     */
220    @Test
221    public void testInitialize_nullInterfaceFailure() throws Exception {
222        executeAndValidateInitializationSequence(false, false, true, false);
223    }
224
225    /**
226     * Tests the initialization flow, with a callback registration failure.
227     * Ensures initialization fails.
228     */
229    @Test
230    public void testInitialize_callbackRegistrationFailure() throws Exception {
231        executeAndValidateInitializationSequence(false, false, false, true);
232    }
233
234    /**
235     * Sunny day scenario for SupplicantStaIfaceHal initialization
236     * Asserts successful initialization
237     */
238    @Test
239    public void testInitialize_successV1_1() throws Exception {
240        mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class);
241        executeAndValidateInitializationSequenceV1_1(false, false);
242    }
243
244    /**
245     * Tests the initialization flow, with a RemoteException occurring when 'getInterface' is called
246     * Ensures initialization fails.
247     */
248    @Test
249    public void testInitialize_remoteExceptionFailureV1_1() throws Exception {
250        mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class);
251        executeAndValidateInitializationSequenceV1_1(true, false);
252    }
253
254    /**
255     * Tests the initialization flow, with a null interface being returned by getInterface.
256     * Ensures initialization fails.
257     */
258    @Test
259    public void testInitialize_nullInterfaceFailureV1_1() throws Exception {
260        mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class);
261        executeAndValidateInitializationSequenceV1_1(false, true);
262    }
263
264    /**
265     * Ensures that we do not allow operations on an interface until it's setup.
266     */
267    @Test
268    public void testEnsureOperationFailsUntilSetupInterfaces() throws Exception {
269        executeAndValidateInitializationSequence(false, false, false, false);
270
271        // Ensure that the cancel wps operation is failed because wlan1 interface is not yet setup.
272        assertFalse(mDut.cancelWps(WLAN1_IFACE_NAME));
273        verify(mISupplicantStaIfaceMock, never()).cancelWps();
274
275        // Now setup the wlan1 interface and Ensure that the cancel wps operation is successful.
276        assertTrue(mDut.setupIface(WLAN1_IFACE_NAME));
277        when(mISupplicantStaIfaceMock.cancelWps()).thenReturn(mStatusSuccess);
278        assertTrue(mDut.cancelWps(WLAN1_IFACE_NAME));
279        verify(mISupplicantStaIfaceMock).cancelWps();
280    }
281
282    /**
283     * Ensures that reject addition of an existing iface.
284     */
285    @Test
286    public void testDuplicateSetupIfaceV1_1_Fails() throws Exception {
287        mISupplicantMockV1_1 = mock(android.hardware.wifi.supplicant.V1_1.ISupplicant.class);
288        executeAndValidateInitializationSequenceV1_1(false, false);
289
290        // Trying setting up the wlan0 interface again & ensure it fails.
291        assertFalse(mDut.setupIface(WLAN0_IFACE_NAME));
292        verifyNoMoreInteractions(mISupplicantMockV1_1);
293    }
294
295    /**
296     * Sunny day scenario for SupplicantStaIfaceHal interface teardown.
297     */
298    @Test
299    public void testTeardownInterface() throws Exception {
300        testInitialize_success();
301        assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME));
302
303        // Ensure that the cancel wps operation is failed because there are no interfaces setup.
304        assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME));
305        verify(mISupplicantStaIfaceMock, never()).cancelWps();
306    }
307
308    /**
309     * Sunny day scenario for SupplicantStaIfaceHal interface teardown.
310     */
311    @Test
312    public void testTeardownInterfaceV1_1() throws Exception {
313        testInitialize_successV1_1();
314
315        when(mISupplicantMockV1_1.removeInterface(any())).thenReturn(mStatusSuccess);
316        assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME));
317        verify(mISupplicantMockV1_1).removeInterface(any());
318
319        // Ensure that the cancel wps operation is failed because there are no interfaces setup.
320        assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME));
321        verify(mISupplicantStaIfaceMock, never()).cancelWps();
322    }
323
324    /**
325     * Ensures that we reject removal of an invalid iface.
326     */
327    @Test
328    public void testInvalidTeardownInterfaceV1_1_Fails() throws Exception {
329        assertFalse(mDut.teardownIface(WLAN0_IFACE_NAME));
330        verifyNoMoreInteractions(mISupplicantMock);
331    }
332
333    /**
334     * Sunny day scenario for SupplicantStaIfaceHal initialization
335     * Asserts successful initialization of second interface
336     */
337    @Test
338    public void testSetupTwoInterfaces() throws Exception {
339        executeAndValidateInitializationSequence(false, false, false, false);
340        assertTrue(mDut.setupIface(WLAN1_IFACE_NAME));
341    }
342
343    /**
344     * Sunny day scenario for SupplicantStaIfaceHal interface teardown.
345     * Asserts successful initialization of second interface
346     */
347    @Test
348    public void testTeardownTwoInterfaces() throws Exception {
349        testSetupTwoInterfaces();
350        assertTrue(mDut.teardownIface(WLAN0_IFACE_NAME));
351        assertTrue(mDut.teardownIface(WLAN1_IFACE_NAME));
352
353        // Ensure that the cancel wps operation is failed because there are no interfaces setup.
354        assertFalse(mDut.cancelWps(WLAN0_IFACE_NAME));
355        verify(mISupplicantStaIfaceMock, never()).cancelWps();
356    }
357
358
359    /**
360     * Tests the loading of networks using {@link SupplicantStaNetworkHal}.
361     * Fills up only the SSID field of configs and uses it as a configKey as well.
362     */
363    @Test
364    public void testLoadNetworks() throws Exception {
365        executeAndValidateInitializationSequence();
366        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
367            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
368                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
369            }
370        }).when(mISupplicantStaIfaceMock)
371                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
372        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
373            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
374                // Reset the |mSupplicantStaNetwork| mock for each network.
375                doAnswer(new MockAnswerUtil.AnswerWithArguments() {
376                    public boolean answer(
377                            WifiConfiguration config, Map<String, String> networkExtra) {
378                        config.SSID = NETWORK_ID_TO_SSID.get(networkId);
379                        config.networkId = networkId;
380                        networkExtra.put(
381                                SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY, config.SSID);
382                        return true;
383                    }
384                }).when(mSupplicantStaNetworkMock)
385                        .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class));
386                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
387                return;
388            }
389        }).when(mISupplicantStaIfaceMock)
390                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
391
392        Map<String, WifiConfiguration> configs = new HashMap<>();
393        SparseArray<Map<String, String>> extras = new SparseArray<>();
394        assertTrue(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
395
396        assertEquals(3, configs.size());
397        assertEquals(3, extras.size());
398        for (Map.Entry<Integer, String> network : NETWORK_ID_TO_SSID.entrySet()) {
399            WifiConfiguration config = configs.get(network.getValue());
400            assertTrue(config != null);
401            assertEquals(network.getKey(), Integer.valueOf(config.networkId));
402            assertEquals(network.getValue(), config.SSID);
403            assertEquals(IpConfiguration.IpAssignment.DHCP, config.getIpAssignment());
404            assertEquals(IpConfiguration.ProxySettings.NONE, config.getProxySettings());
405        }
406    }
407
408    /**
409     * Tests the loading of networks using {@link SupplicantStaNetworkHal} removes any networks
410     * with duplicate config key.
411     * Fills up only the SSID field of configs and uses it as a configKey as well.
412     */
413    @Test
414    public void testLoadNetworksRemovesDuplicates() throws Exception {
415        // Network ID which will have the same config key as the previous one.
416        final int duplicateNetworkId = 2;
417        final int toRemoveNetworkId = duplicateNetworkId - 1;
418        executeAndValidateInitializationSequence();
419        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
420            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
421                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
422            }
423        }).when(mISupplicantStaIfaceMock)
424                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
425        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
426            public SupplicantStatus answer(int id) {
427                return mStatusSuccess;
428            }
429        }).when(mISupplicantStaIfaceMock).removeNetwork(eq(toRemoveNetworkId));
430        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
431            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
432                // Reset the |mSupplicantStaNetwork| mock for each network.
433                doAnswer(new MockAnswerUtil.AnswerWithArguments() {
434                    public boolean answer(
435                            WifiConfiguration config, Map<String, String> networkExtra) {
436                        config.SSID = NETWORK_ID_TO_SSID.get(networkId);
437                        config.networkId = networkId;
438                        // Duplicate network gets the same config key as the to removed one.
439                        if (networkId == duplicateNetworkId) {
440                            networkExtra.put(
441                                    SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY,
442                                    NETWORK_ID_TO_SSID.get(toRemoveNetworkId));
443                        } else {
444                            networkExtra.put(
445                                    SupplicantStaNetworkHal.ID_STRING_KEY_CONFIG_KEY,
446                                    NETWORK_ID_TO_SSID.get(networkId));
447                        }
448                        return true;
449                    }
450                }).when(mSupplicantStaNetworkMock)
451                        .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class));
452                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
453                return;
454            }
455        }).when(mISupplicantStaIfaceMock)
456                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
457
458        Map<String, WifiConfiguration> configs = new HashMap<>();
459        SparseArray<Map<String, String>> extras = new SparseArray<>();
460        assertTrue(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
461
462        assertEquals(2, configs.size());
463        assertEquals(2, extras.size());
464        for (Map.Entry<Integer, String> network : NETWORK_ID_TO_SSID.entrySet()) {
465            if (network.getKey() == toRemoveNetworkId) {
466                continue;
467            }
468            WifiConfiguration config;
469            // Duplicate network gets the same config key as the to removed one. So, use that to
470            // lookup the map.
471            if (network.getKey() == duplicateNetworkId) {
472                config = configs.get(NETWORK_ID_TO_SSID.get(toRemoveNetworkId));
473            } else {
474                config = configs.get(network.getValue());
475            }
476            assertTrue(config != null);
477            assertEquals(network.getKey(), Integer.valueOf(config.networkId));
478            assertEquals(network.getValue(), config.SSID);
479            assertEquals(IpConfiguration.IpAssignment.DHCP, config.getIpAssignment());
480            assertEquals(IpConfiguration.ProxySettings.NONE, config.getProxySettings());
481        }
482    }
483
484    /**
485     * Tests the failure to load networks because of listNetworks failure.
486     */
487    @Test
488    public void testLoadNetworksFailedDueToListNetworks() throws Exception {
489        executeAndValidateInitializationSequence();
490        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
491            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
492                cb.onValues(mStatusFailure, null);
493            }
494        }).when(mISupplicantStaIfaceMock)
495                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
496
497        Map<String, WifiConfiguration> configs = new HashMap<>();
498        SparseArray<Map<String, String>> extras = new SparseArray<>();
499        assertFalse(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
500    }
501
502    /**
503     * Tests the failure to load networks because of getNetwork failure.
504     */
505    @Test
506    public void testLoadNetworksFailedDueToGetNetwork() throws Exception {
507        executeAndValidateInitializationSequence();
508        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
509            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
510                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
511            }
512        }).when(mISupplicantStaIfaceMock)
513                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
514        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
515            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
516                cb.onValues(mStatusFailure, mock(ISupplicantStaNetwork.class));
517                return;
518            }
519        }).when(mISupplicantStaIfaceMock)
520                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
521
522        Map<String, WifiConfiguration> configs = new HashMap<>();
523        SparseArray<Map<String, String>> extras = new SparseArray<>();
524        assertFalse(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
525    }
526
527    /**
528     * Tests the failure to load networks because of loadWifiConfiguration failure.
529     */
530    @Test
531    public void testLoadNetworksFailedDueToLoadWifiConfiguration() throws Exception {
532        executeAndValidateInitializationSequence();
533        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
534            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
535                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
536            }
537        }).when(mISupplicantStaIfaceMock)
538                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
539        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
540            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
541                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
542                return;
543            }
544        }).when(mISupplicantStaIfaceMock)
545                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
546        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
547            public boolean answer(WifiConfiguration config, Map<String, String> networkExtra) {
548                return false;
549            }
550        }).when(mSupplicantStaNetworkMock)
551                .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class));
552
553        Map<String, WifiConfiguration> configs = new HashMap<>();
554        SparseArray<Map<String, String>> extras = new SparseArray<>();
555        assertTrue(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
556        assertTrue(configs.isEmpty());
557    }
558
559    /**
560     * Tests the failure to load networks because of loadWifiConfiguration exception.
561     */
562    @Test
563    public void testLoadNetworksFailedDueToExceptionInLoadWifiConfiguration() throws Exception {
564        executeAndValidateInitializationSequence();
565        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
566            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
567                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
568            }
569        }).when(mISupplicantStaIfaceMock)
570                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
571        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
572            public void answer(final int networkId, ISupplicantStaIface.getNetworkCallback cb) {
573                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
574                return;
575            }
576        }).when(mISupplicantStaIfaceMock)
577                .getNetwork(anyInt(), any(ISupplicantStaIface.getNetworkCallback.class));
578        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
579            public boolean answer(WifiConfiguration config, Map<String, String> networkExtra)
580                    throws Exception {
581                throw new IllegalArgumentException();
582            }
583        }).when(mSupplicantStaNetworkMock)
584                .loadWifiConfiguration(any(WifiConfiguration.class), any(Map.class));
585
586        Map<String, WifiConfiguration> configs = new HashMap<>();
587        SparseArray<Map<String, String>> extras = new SparseArray<>();
588        assertTrue(mDut.loadNetworks(WLAN0_IFACE_NAME, configs, extras));
589        assertTrue(configs.isEmpty());
590    }
591
592    /**
593     * Tests connection to a specified network with empty existing network.
594     */
595    @Test
596    public void testConnectWithEmptyExistingNetwork() throws Exception {
597        executeAndValidateInitializationSequence();
598        executeAndValidateConnectSequence(0, false);
599    }
600
601    @Test
602    public void testConnectToNetworkWithDifferentConfigReplacesNetworkInSupplicant()
603            throws Exception {
604        executeAndValidateInitializationSequence();
605        WifiConfiguration config = executeAndValidateConnectSequence(
606                SUPPLICANT_NETWORK_ID, false);
607        // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection.
608        reset(mISupplicantStaIfaceMock);
609        setupMocksForConnectSequence(true /*haveExistingNetwork*/);
610        // Make this network different by changing SSID.
611        config.SSID = "AnDifferentSSID";
612        assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config));
613        verify(mISupplicantStaIfaceMock).removeNetwork(SUPPLICANT_NETWORK_ID);
614        verify(mISupplicantStaIfaceMock)
615                .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class));
616    }
617
618    @Test
619    public void connectToNetworkWithSameNetworkDoesNotRemoveNetworkFromSupplicant()
620            throws Exception {
621        executeAndValidateInitializationSequence();
622        WifiConfiguration config = executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false);
623        // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection.
624        reset(mISupplicantStaIfaceMock);
625        setupMocksForConnectSequence(true /*haveExistingNetwork*/);
626        assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config));
627        verify(mISupplicantStaIfaceMock, never()).removeNetwork(anyInt());
628        verify(mISupplicantStaIfaceMock, never())
629                .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class));
630    }
631
632    @Test
633    public void connectToNetworkWithSameNetworkButDifferentBssidUpdatesNetworkFromSupplicant()
634            throws Exception {
635        executeAndValidateInitializationSequence();
636        WifiConfiguration config = executeAndValidateConnectSequence(SUPPLICANT_NETWORK_ID, false);
637        String testBssid = "11:22:33:44:55:66";
638        when(mSupplicantStaNetworkMock.setBssid(eq(testBssid))).thenReturn(true);
639
640        // Reset mocks for mISupplicantStaIfaceMock because we finished the first connection.
641        reset(mISupplicantStaIfaceMock);
642        setupMocksForConnectSequence(true /*haveExistingNetwork*/);
643        // Change the BSSID and connect to the same network.
644        assertFalse(TextUtils.equals(
645                testBssid, config.getNetworkSelectionStatus().getNetworkSelectionBSSID()));
646        config.getNetworkSelectionStatus().setNetworkSelectionBSSID(testBssid);
647        assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config));
648        verify(mSupplicantStaNetworkMock).setBssid(eq(testBssid));
649        verify(mISupplicantStaIfaceMock, never()).removeNetwork(anyInt());
650        verify(mISupplicantStaIfaceMock, never())
651                .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class));
652    }
653
654    /**
655     * Tests connection to a specified network failure due to network add.
656     */
657    @Test
658    public void testConnectFailureDueToNetworkAddFailure() throws Exception {
659        executeAndValidateInitializationSequence();
660        setupMocksForConnectSequence(false);
661        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
662            public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException {
663                cb.onValues(mStatusFailure, mock(ISupplicantStaNetwork.class));
664                return;
665            }
666        }).when(mISupplicantStaIfaceMock).addNetwork(
667                any(ISupplicantStaIface.addNetworkCallback.class));
668
669        assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration()));
670    }
671
672    /**
673     * Tests connection to a specified network failure due to network save.
674     */
675    @Test
676    public void testConnectFailureDueToNetworkSaveFailure() throws Exception {
677        executeAndValidateInitializationSequence();
678        setupMocksForConnectSequence(true);
679
680        when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class)))
681                .thenReturn(false);
682
683        assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration()));
684        // We should have removed the existing network once before connection and once more
685        // on failure to save network configuration.
686        verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt());
687    }
688
689    /**
690     * Tests connection to a specified network failure due to exception in network save.
691     */
692    @Test
693    public void testConnectFailureDueToNetworkSaveException() throws Exception {
694        executeAndValidateInitializationSequence();
695        setupMocksForConnectSequence(true);
696
697        doThrow(new IllegalArgumentException("Some error!!!"))
698                .when(mSupplicantStaNetworkMock).saveWifiConfiguration(
699                        any(WifiConfiguration.class));
700
701        assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration()));
702        // We should have removed the existing network once before connection and once more
703        // on failure to save network configuration.
704        verify(mISupplicantStaIfaceMock, times(2)).removeNetwork(anyInt());
705    }
706
707    /**
708     * Tests connection to a specified network failure due to network select.
709     */
710    @Test
711    public void testConnectFailureDueToNetworkSelectFailure() throws Exception {
712        executeAndValidateInitializationSequence();
713        setupMocksForConnectSequence(false);
714
715        when(mSupplicantStaNetworkMock.select()).thenReturn(false);
716
717        assertFalse(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration()));
718    }
719
720    /**
721     * Tests roaming to the same network as the currently connected one.
722     */
723    @Test
724    public void testRoamToSameNetwork() throws Exception {
725        executeAndValidateInitializationSequence();
726        executeAndValidateRoamSequence(true);
727        assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, createTestWifiConfiguration()));
728    }
729
730    /**
731     * Tests roaming to a different network.
732     */
733    @Test
734    public void testRoamToDifferentNetwork() throws Exception {
735        executeAndValidateInitializationSequence();
736        executeAndValidateRoamSequence(false);
737    }
738
739    /**
740     * Tests roaming failure because of unable to set bssid.
741     */
742    @Test
743    public void testRoamFailureDueToBssidSet() throws Exception {
744        executeAndValidateInitializationSequence();
745        int connectedNetworkId = 5;
746        executeAndValidateConnectSequence(connectedNetworkId, false);
747        when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(false);
748
749        WifiConfiguration roamingConfig = new WifiConfiguration();
750        roamingConfig.networkId = connectedNetworkId;
751        roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed");
752        assertFalse(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig));
753    }
754
755    /**
756     * Tests removal of all configured networks from wpa_supplicant.
757     */
758    @Test
759    public void testRemoveAllNetworks() throws Exception {
760        executeAndValidateInitializationSequence();
761        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
762            public void answer(ISupplicantStaIface.listNetworksCallback cb) {
763                cb.onValues(mStatusSuccess, new ArrayList<>(NETWORK_ID_TO_SSID.keySet()));
764            }
765        }).when(mISupplicantStaIfaceMock)
766                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
767        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
768            public SupplicantStatus answer(int id) {
769                assertTrue(NETWORK_ID_TO_SSID.containsKey(id));
770                return mStatusSuccess;
771            }
772        }).when(mISupplicantStaIfaceMock).removeNetwork(anyInt());
773
774        assertTrue(mDut.removeAllNetworks(WLAN0_IFACE_NAME));
775        verify(mISupplicantStaIfaceMock, times(NETWORK_ID_TO_SSID.size())).removeNetwork(anyInt());
776    }
777
778    /**
779     * Remove all networks while connected, verify that the current network info is resetted.
780     */
781    @Test
782    public void testRemoveAllNetworksWhileConnected() throws Exception {
783        String testBssid = "11:22:33:44:55:66";
784        when(mSupplicantStaNetworkMock.setBssid(eq(testBssid))).thenReturn(true);
785
786        executeAndValidateInitializationSequence();
787
788        // Connect to a network and verify current network is set.
789        executeAndValidateConnectSequence(4, false);
790        assertTrue(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, testBssid));
791        verify(mSupplicantStaNetworkMock).setBssid(eq(testBssid));
792        reset(mSupplicantStaNetworkMock);
793
794        // Remove all networks and verify current network info is resetted.
795        assertTrue(mDut.removeAllNetworks(WLAN0_IFACE_NAME));
796        assertFalse(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, testBssid));
797        verify(mSupplicantStaNetworkMock, never()).setBssid(eq(testBssid));
798    }
799
800    /**
801     * Tests roaming failure because of unable to reassociate.
802     */
803    @Test
804    public void testRoamFailureDueToReassociate() throws Exception {
805        executeAndValidateInitializationSequence();
806        int connectedNetworkId = 5;
807        executeAndValidateConnectSequence(connectedNetworkId, false);
808
809        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
810            public SupplicantStatus answer() throws RemoteException {
811                return mStatusFailure;
812            }
813        }).when(mISupplicantStaIfaceMock).reassociate();
814        when(mSupplicantStaNetworkMock.setBssid(anyString())).thenReturn(true);
815
816        WifiConfiguration roamingConfig = new WifiConfiguration();
817        roamingConfig.networkId = connectedNetworkId;
818        roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID("45:34:23:23:ab:ed");
819        assertFalse(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig));
820    }
821
822    /**
823     * Tests the retrieval of WPS NFC token.
824     */
825    @Test
826    public void testGetCurrentNetworkWpsNfcConfigurationToken() throws Exception {
827        String token = "45adbc1";
828        when(mSupplicantStaNetworkMock.getWpsNfcConfigurationToken()).thenReturn(token);
829
830        executeAndValidateInitializationSequence();
831        // Return null when not connected to the network.
832        assertTrue(mDut.getCurrentNetworkWpsNfcConfigurationToken(WLAN0_IFACE_NAME) == null);
833        verify(mSupplicantStaNetworkMock, never()).getWpsNfcConfigurationToken();
834        executeAndValidateConnectSequence(4, false);
835        assertEquals(token, mDut.getCurrentNetworkWpsNfcConfigurationToken(WLAN0_IFACE_NAME));
836        verify(mSupplicantStaNetworkMock).getWpsNfcConfigurationToken();
837    }
838
839    /**
840     * Tests the setting of BSSID.
841     */
842    @Test
843    public void testSetCurrentNetworkBssid() throws Exception {
844        String bssidStr = "34:34:12:12:12:90";
845        when(mSupplicantStaNetworkMock.setBssid(eq(bssidStr))).thenReturn(true);
846
847        executeAndValidateInitializationSequence();
848        // Fail when not connected to a network.
849        assertFalse(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, bssidStr));
850        verify(mSupplicantStaNetworkMock, never()).setBssid(eq(bssidStr));
851        executeAndValidateConnectSequence(4, false);
852        assertTrue(mDut.setCurrentNetworkBssid(WLAN0_IFACE_NAME, bssidStr));
853        verify(mSupplicantStaNetworkMock).setBssid(eq(bssidStr));
854    }
855
856    /**
857     * Tests the sending identity response for the current network.
858     */
859    @Test
860    public void testSetCurrentNetworkEapIdentityResponse() throws Exception {
861        String identity = "blah@blah.com";
862        String encryptedIdentity = "blah2@blah.com";
863        when(mSupplicantStaNetworkMock.sendNetworkEapIdentityResponse(eq(identity),
864                eq(encryptedIdentity)))
865                .thenReturn(true);
866
867        executeAndValidateInitializationSequence();
868        // Fail when not connected to a network.
869        assertFalse(mDut.sendCurrentNetworkEapIdentityResponse(WLAN0_IFACE_NAME, identity,
870                encryptedIdentity));
871        verify(mSupplicantStaNetworkMock, never()).sendNetworkEapIdentityResponse(eq(identity),
872                eq(encryptedIdentity));
873        executeAndValidateConnectSequence(4, false);
874        assertTrue(mDut.sendCurrentNetworkEapIdentityResponse(WLAN0_IFACE_NAME, identity,
875                encryptedIdentity));
876        verify(mSupplicantStaNetworkMock).sendNetworkEapIdentityResponse(eq(identity),
877                eq(encryptedIdentity));
878    }
879
880    /**
881     * Tests the getting of anonymous identity for the current network.
882     */
883    @Test
884    public void testGetCurrentNetworkEapAnonymousIdentity() throws Exception {
885        String anonymousIdentity = "aaa@bbb.ccc";
886        when(mSupplicantStaNetworkMock.fetchEapAnonymousIdentity())
887                .thenReturn(anonymousIdentity);
888        executeAndValidateInitializationSequence();
889
890        // Return null when not connected to the network.
891        assertEquals(null, mDut.getCurrentNetworkEapAnonymousIdentity(WLAN0_IFACE_NAME));
892        executeAndValidateConnectSequence(4, false);
893        // Return anonymous identity for the current network.
894        assertEquals(
895                anonymousIdentity, mDut.getCurrentNetworkEapAnonymousIdentity(WLAN0_IFACE_NAME));
896    }
897
898    /**
899     * Tests the sending gsm auth response for the current network.
900     */
901    @Test
902    public void testSetCurrentNetworkEapSimGsmAuthResponse() throws Exception {
903        String params = "test";
904        when(mSupplicantStaNetworkMock.sendNetworkEapSimGsmAuthResponse(eq(params)))
905                .thenReturn(true);
906
907        executeAndValidateInitializationSequence();
908        // Fail when not connected to a network.
909        assertFalse(mDut.sendCurrentNetworkEapSimGsmAuthResponse(WLAN0_IFACE_NAME, params));
910        verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimGsmAuthResponse(eq(params));
911        executeAndValidateConnectSequence(4, false);
912        assertTrue(mDut.sendCurrentNetworkEapSimGsmAuthResponse(WLAN0_IFACE_NAME, params));
913        verify(mSupplicantStaNetworkMock).sendNetworkEapSimGsmAuthResponse(eq(params));
914    }
915
916    /**
917     * Tests the sending umts auth response for the current network.
918     */
919    @Test
920    public void testSetCurrentNetworkEapSimUmtsAuthResponse() throws Exception {
921        String params = "test";
922        when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAuthResponse(eq(params)))
923                .thenReturn(true);
924
925        executeAndValidateInitializationSequence();
926        // Fail when not connected to a network.
927        assertFalse(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(WLAN0_IFACE_NAME, params));
928        verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAuthResponse(eq(params));
929        executeAndValidateConnectSequence(4, false);
930        assertTrue(mDut.sendCurrentNetworkEapSimUmtsAuthResponse(WLAN0_IFACE_NAME, params));
931        verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAuthResponse(eq(params));
932    }
933
934    /**
935     * Tests the sending umts auts response for the current network.
936     */
937    @Test
938    public void testSetCurrentNetworkEapSimUmtsAutsResponse() throws Exception {
939        String params = "test";
940        when(mSupplicantStaNetworkMock.sendNetworkEapSimUmtsAutsResponse(eq(params)))
941                .thenReturn(true);
942
943        executeAndValidateInitializationSequence();
944        // Fail when not connected to a network.
945        assertFalse(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(WLAN0_IFACE_NAME, params));
946        verify(mSupplicantStaNetworkMock, never()).sendNetworkEapSimUmtsAutsResponse(eq(params));
947        executeAndValidateConnectSequence(4, false);
948        assertTrue(mDut.sendCurrentNetworkEapSimUmtsAutsResponse(WLAN0_IFACE_NAME, params));
949        verify(mSupplicantStaNetworkMock).sendNetworkEapSimUmtsAutsResponse(eq(params));
950    }
951
952    /**
953     * Tests the setting of WPS device type.
954     */
955    @Test
956    public void testSetWpsDeviceType() throws Exception {
957        String validDeviceTypeStr = "10-0050F204-5";
958        byte[] expectedDeviceType = { 0x0, 0xa, 0x0, 0x50, (byte) 0xf2, 0x04, 0x0, 0x05};
959        String invalidDeviceType1Str = "10-02050F204-5";
960        String invalidDeviceType2Str = "10-0050F204-534";
961        when(mISupplicantStaIfaceMock.setWpsDeviceType(any(byte[].class)))
962                .thenReturn(mStatusSuccess);
963
964        executeAndValidateInitializationSequence();
965
966        // This should work.
967        assertTrue(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, validDeviceTypeStr));
968        verify(mISupplicantStaIfaceMock).setWpsDeviceType(eq(expectedDeviceType));
969
970        // This should not work
971        assertFalse(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, invalidDeviceType1Str));
972        // This should not work
973        assertFalse(mDut.setWpsDeviceType(WLAN0_IFACE_NAME, invalidDeviceType2Str));
974    }
975
976    /**
977     * Tests the setting of WPS config methods.
978     */
979    @Test
980    public void testSetWpsConfigMethods() throws Exception {
981        String validConfigMethodsStr = "physical_display virtual_push_button";
982        Short expectedConfigMethods =
983                WpsConfigMethods.PHY_DISPLAY | WpsConfigMethods.VIRT_PUSHBUTTON;
984        String invalidConfigMethodsStr = "physical_display virtual_push_button test";
985        when(mISupplicantStaIfaceMock.setWpsConfigMethods(anyShort())).thenReturn(mStatusSuccess);
986
987        executeAndValidateInitializationSequence();
988
989        // This should work.
990        assertTrue(mDut.setWpsConfigMethods(WLAN0_IFACE_NAME, validConfigMethodsStr));
991        verify(mISupplicantStaIfaceMock).setWpsConfigMethods(eq(expectedConfigMethods));
992
993        // This should throw an illegal argument exception.
994        try {
995            assertFalse(mDut.setWpsConfigMethods(WLAN0_IFACE_NAME, invalidConfigMethodsStr));
996        } catch (IllegalArgumentException e) {
997            return;
998        }
999        assertTrue(false);
1000    }
1001
1002    /**
1003     * Tests the handling of ANQP done callback.
1004     * Note: Since the ANQP element parsing methods are static, this can only test the negative test
1005     * where all the parsing fails because the data is empty. It'll be non-trivial and unnecessary
1006     * to test out the parsing logic here.
1007     */
1008    @Test
1009    public void testAnqpDoneCallback() throws Exception {
1010        executeAndValidateInitializationSequence();
1011        assertNotNull(mISupplicantStaIfaceCallback);
1012        byte[] bssid = NativeUtil.macAddressToByteArray(BSSID);
1013        mISupplicantStaIfaceCallback.onAnqpQueryDone(
1014                bssid, new ISupplicantStaIfaceCallback.AnqpData(),
1015                new ISupplicantStaIfaceCallback.Hs20AnqpData());
1016
1017        ArgumentCaptor<AnqpEvent> anqpEventCaptor = ArgumentCaptor.forClass(AnqpEvent.class);
1018        verify(mWifiMonitor).broadcastAnqpDoneEvent(
1019                eq(WLAN0_IFACE_NAME), anqpEventCaptor.capture());
1020        assertEquals(
1021                ByteBufferReader.readInteger(
1022                        ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length),
1023                anqpEventCaptor.getValue().getBssid());
1024    }
1025
1026    /**
1027     * Tests the handling of Icon done callback.
1028     */
1029    @Test
1030    public void testIconDoneCallback() throws Exception {
1031        executeAndValidateInitializationSequence();
1032        assertNotNull(mISupplicantStaIfaceCallback);
1033
1034        byte[] bssid = NativeUtil.macAddressToByteArray(BSSID);
1035        byte[] iconData = new byte[ICON_FILE_SIZE];
1036        new Random().nextBytes(iconData);
1037        mISupplicantStaIfaceCallback.onHs20IconQueryDone(
1038                bssid, ICON_FILE_NAME, NativeUtil.byteArrayToArrayList(iconData));
1039
1040        ArgumentCaptor<IconEvent> iconEventCaptor = ArgumentCaptor.forClass(IconEvent.class);
1041        verify(mWifiMonitor).broadcastIconDoneEvent(
1042                eq(WLAN0_IFACE_NAME), iconEventCaptor.capture());
1043        assertEquals(
1044                ByteBufferReader.readInteger(
1045                        ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length),
1046                iconEventCaptor.getValue().getBSSID());
1047        assertEquals(ICON_FILE_NAME, iconEventCaptor.getValue().getFileName());
1048        assertArrayEquals(iconData, iconEventCaptor.getValue().getData());
1049    }
1050
1051    /**
1052     * Tests the handling of HS20 subscription remediation callback.
1053     */
1054    @Test
1055    public void testHs20SubscriptionRemediationCallback() throws Exception {
1056        executeAndValidateInitializationSequence();
1057        assertNotNull(mISupplicantStaIfaceCallback);
1058
1059        byte[] bssid = NativeUtil.macAddressToByteArray(BSSID);
1060        byte osuMethod = ISupplicantStaIfaceCallback.OsuMethod.OMA_DM;
1061        mISupplicantStaIfaceCallback.onHs20SubscriptionRemediation(
1062                bssid, osuMethod, HS20_URL);
1063
1064        ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class);
1065        verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN0_IFACE_NAME), wnmDataCaptor.capture());
1066        assertEquals(
1067                ByteBufferReader.readInteger(
1068                        ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length),
1069                wnmDataCaptor.getValue().getBssid());
1070        assertEquals(osuMethod, wnmDataCaptor.getValue().getMethod());
1071        assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl());
1072    }
1073
1074    /**
1075     * Tests the handling of HS20 deauth imminent callback.
1076     */
1077    @Test
1078    public void testHs20DeauthImminentCallbackWithEssReasonCode() throws Exception {
1079        executeAndValidateHs20DeauthImminentCallback(true);
1080    }
1081
1082    /**
1083     * Tests the handling of HS20 deauth imminent callback.
1084     */
1085    @Test
1086    public void testHs20DeauthImminentCallbackWithNonEssReasonCode() throws Exception {
1087        executeAndValidateHs20DeauthImminentCallback(false);
1088
1089    }
1090
1091    /**
1092     * Tests the handling of state change notification without any configured network.
1093     */
1094    @Test
1095    public void testStateChangeCallbackWithNoConfiguredNetwork() throws Exception {
1096        executeAndValidateInitializationSequence();
1097        assertNotNull(mISupplicantStaIfaceCallback);
1098
1099        mISupplicantStaIfaceCallback.onStateChanged(
1100                ISupplicantStaIfaceCallback.State.INACTIVE,
1101                NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
1102                NativeUtil.decodeSsid(SUPPLICANT_SSID));
1103
1104        // Can't compare WifiSsid instances because they lack an equals.
1105        verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
1106                eq(WLAN0_IFACE_NAME), eq(WifiConfiguration.INVALID_NETWORK_ID),
1107                any(WifiSsid.class), eq(BSSID), eq(SupplicantState.INACTIVE));
1108    }
1109
1110    /**
1111     * Tests the handling of state change notification to associated after configuring a network.
1112     */
1113    @Test
1114    public void testStateChangeToAssociatedCallback() throws Exception {
1115        executeAndValidateInitializationSequence();
1116        int frameworkNetworkId = 6;
1117        executeAndValidateConnectSequence(frameworkNetworkId, false);
1118        assertNotNull(mISupplicantStaIfaceCallback);
1119
1120        mISupplicantStaIfaceCallback.onStateChanged(
1121                ISupplicantStaIfaceCallback.State.ASSOCIATED,
1122                NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
1123                NativeUtil.decodeSsid(SUPPLICANT_SSID));
1124
1125        verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
1126                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
1127                any(WifiSsid.class), eq(BSSID), eq(SupplicantState.ASSOCIATED));
1128    }
1129
1130    /**
1131     * Tests the handling of state change notification to completed after configuring a network.
1132     */
1133    @Test
1134    public void testStateChangeToCompletedCallback() throws Exception {
1135        InOrder wifiMonitorInOrder = inOrder(mWifiMonitor);
1136        executeAndValidateInitializationSequence();
1137        int frameworkNetworkId = 6;
1138        executeAndValidateConnectSequence(frameworkNetworkId, false);
1139        assertNotNull(mISupplicantStaIfaceCallback);
1140
1141        mISupplicantStaIfaceCallback.onStateChanged(
1142                ISupplicantStaIfaceCallback.State.COMPLETED,
1143                NativeUtil.macAddressToByteArray(BSSID), SUPPLICANT_NETWORK_ID,
1144                NativeUtil.decodeSsid(SUPPLICANT_SSID));
1145
1146        wifiMonitorInOrder.verify(mWifiMonitor).broadcastNetworkConnectionEvent(
1147                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId), eq(BSSID));
1148        wifiMonitorInOrder.verify(mWifiMonitor).broadcastSupplicantStateChangeEvent(
1149                eq(WLAN0_IFACE_NAME), eq(frameworkNetworkId),
1150                any(WifiSsid.class), eq(BSSID), eq(SupplicantState.COMPLETED));
1151    }
1152
1153    /**
1154     * Tests the handling of network disconnected notification.
1155     */
1156    @Test
1157    public void testDisconnectedCallback() throws Exception {
1158        executeAndValidateInitializationSequence();
1159        assertNotNull(mISupplicantStaIfaceCallback);
1160
1161        int reasonCode = 5;
1162        mISupplicantStaIfaceCallback.onDisconnected(
1163                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
1164        verify(mWifiMonitor).broadcastNetworkDisconnectionEvent(
1165                eq(WLAN0_IFACE_NAME), eq(1), eq(reasonCode), eq(BSSID));
1166
1167        mISupplicantStaIfaceCallback.onDisconnected(
1168                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
1169        verify(mWifiMonitor).broadcastNetworkDisconnectionEvent(
1170                eq(WLAN0_IFACE_NAME), eq(0), eq(reasonCode), eq(BSSID));
1171    }
1172
1173    /**
1174     * Tests the handling of incorrect network passwords.
1175     */
1176    @Test
1177    public void testAuthFailurePassword() throws Exception {
1178        executeAndValidateInitializationSequence();
1179        assertNotNull(mISupplicantStaIfaceCallback);
1180
1181        int reasonCode = 3;
1182        mISupplicantStaIfaceCallback.onDisconnected(
1183                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
1184        verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt());
1185
1186        mISupplicantStaIfaceCallback.onDisconnected(
1187                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
1188        verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(), anyInt());
1189
1190        mISupplicantStaIfaceCallback.onStateChanged(
1191                ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE,
1192                NativeUtil.macAddressToByteArray(BSSID),
1193                SUPPLICANT_NETWORK_ID,
1194                NativeUtil.decodeSsid(SUPPLICANT_SSID));
1195        mISupplicantStaIfaceCallback.onDisconnected(
1196                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
1197        mISupplicantStaIfaceCallback.onDisconnected(
1198                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
1199
1200        verify(mWifiMonitor, times(2)).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME),
1201                eq(WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD), eq(-1));
1202    }
1203
1204     /**
1205      * Tests the handling of incorrect network passwords, edge case.
1206      *
1207      * If the disconnect reason is "IE in 4way differs", do not call it a password mismatch.
1208      */
1209    @Test
1210    public void testIeDiffers() throws Exception {
1211        executeAndValidateInitializationSequence();
1212        assertNotNull(mISupplicantStaIfaceCallback);
1213
1214        int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IE_IN_4WAY_DIFFERS;
1215
1216        mISupplicantStaIfaceCallback.onStateChanged(
1217                ISupplicantStaIfaceCallback.State.FOURWAY_HANDSHAKE,
1218                NativeUtil.macAddressToByteArray(BSSID),
1219                SUPPLICANT_NETWORK_ID,
1220                NativeUtil.decodeSsid(SUPPLICANT_SSID));
1221        mISupplicantStaIfaceCallback.onDisconnected(
1222                NativeUtil.macAddressToByteArray(BSSID), true, reasonCode);
1223        verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(),
1224                anyInt());
1225    }
1226
1227    /**
1228     * Tests the handling of eap failure during disconnect.
1229     */
1230    @Test
1231    public void testEapFailure() throws Exception {
1232        executeAndValidateInitializationSequence();
1233        assertNotNull(mISupplicantStaIfaceCallback);
1234
1235        int reasonCode = ISupplicantStaIfaceCallback.ReasonCode.IEEE_802_1X_AUTH_FAILED;
1236        mISupplicantStaIfaceCallback.onDisconnected(
1237                NativeUtil.macAddressToByteArray(BSSID), false, reasonCode);
1238        verify(mWifiMonitor, times(0)).broadcastAuthenticationFailureEvent(any(), anyInt(),
1239                anyInt());
1240    }
1241
1242    /**
1243     * Tests the handling of association rejection notification.
1244     */
1245    @Test
1246    public void testAssociationRejectionCallback() throws Exception {
1247        executeAndValidateInitializationSequence();
1248        assertNotNull(mISupplicantStaIfaceCallback);
1249
1250        int statusCode = 7;
1251        mISupplicantStaIfaceCallback.onAssociationRejected(
1252                NativeUtil.macAddressToByteArray(BSSID), statusCode, false);
1253        verify(mWifiMonitor).broadcastAssociationRejectionEvent(
1254                eq(WLAN0_IFACE_NAME), eq(statusCode), eq(false), eq(BSSID));
1255    }
1256
1257    /**
1258     * Tests the handling of authentification timeout notification.
1259     */
1260    @Test
1261    public void testAuthenticationTimeoutCallback() throws Exception {
1262        executeAndValidateInitializationSequence();
1263        assertNotNull(mISupplicantStaIfaceCallback);
1264
1265        mISupplicantStaIfaceCallback.onAuthenticationTimeout(
1266                NativeUtil.macAddressToByteArray(BSSID));
1267        verify(mWifiMonitor).broadcastAuthenticationFailureEvent(eq(WLAN0_IFACE_NAME),
1268                eq(WifiManager.ERROR_AUTH_FAILURE_TIMEOUT), eq(-1));
1269    }
1270
1271    /**
1272     * Tests the handling of bssid change notification.
1273     */
1274    @Test
1275    public void testBssidChangedCallback() throws Exception {
1276        executeAndValidateInitializationSequence();
1277        assertNotNull(mISupplicantStaIfaceCallback);
1278
1279        mISupplicantStaIfaceCallback.onBssidChanged(
1280                BssidChangeReason.ASSOC_START, NativeUtil.macAddressToByteArray(BSSID));
1281        verify(mWifiMonitor).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID));
1282        verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent(
1283                eq(WLAN0_IFACE_NAME), eq(BSSID));
1284
1285        reset(mWifiMonitor);
1286        mISupplicantStaIfaceCallback.onBssidChanged(
1287                BssidChangeReason.ASSOC_COMPLETE, NativeUtil.macAddressToByteArray(BSSID));
1288        verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID));
1289        verify(mWifiMonitor).broadcastAssociatedBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID));
1290
1291        reset(mWifiMonitor);
1292        mISupplicantStaIfaceCallback.onBssidChanged(
1293                BssidChangeReason.DISASSOC, NativeUtil.macAddressToByteArray(BSSID));
1294        verify(mWifiMonitor, never()).broadcastTargetBssidEvent(eq(WLAN0_IFACE_NAME), eq(BSSID));
1295        verify(mWifiMonitor, never()).broadcastAssociatedBssidEvent(
1296                eq(WLAN0_IFACE_NAME), eq(BSSID));
1297    }
1298
1299    /**
1300     * Tests the handling of EAP failure notification.
1301     */
1302    @Test
1303    public void testEapFailureCallback() throws Exception {
1304        int eapFailureCode = WifiNative.EAP_SIM_VENDOR_SPECIFIC_CERT_EXPIRED;
1305        testInitialize_successV1_1();
1306        assertNotNull(mISupplicantStaIfaceCallbackV1_1);
1307
1308        mISupplicantStaIfaceCallbackV1_1.onEapFailure_1_1(eapFailureCode);
1309        verify(mWifiMonitor).broadcastAuthenticationFailureEvent(
1310                eq(WLAN0_IFACE_NAME), eq(WifiManager.ERROR_AUTH_FAILURE_EAP_FAILURE),
1311                eq(eapFailureCode));
1312    }
1313
1314    /**
1315     * Tests the handling of Wps success notification.
1316     */
1317    @Test
1318    public void testWpsSuccessCallback() throws Exception {
1319        executeAndValidateInitializationSequence();
1320        assertNotNull(mISupplicantStaIfaceCallback);
1321
1322        mISupplicantStaIfaceCallback.onWpsEventSuccess();
1323        verify(mWifiMonitor).broadcastWpsSuccessEvent(eq(WLAN0_IFACE_NAME));
1324    }
1325
1326    /**
1327     * Tests the handling of Wps fail notification.
1328     */
1329    @Test
1330    public void testWpsFailureCallback() throws Exception {
1331        executeAndValidateInitializationSequence();
1332        assertNotNull(mISupplicantStaIfaceCallback);
1333
1334        short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MULTIPLE_PBC_DETECTED;
1335        short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.SECURITY_WEP_PROHIBITED;
1336        mISupplicantStaIfaceCallback.onWpsEventFail(
1337                NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd);
1338        verify(mWifiMonitor).broadcastWpsFailEvent(eq(WLAN0_IFACE_NAME),
1339                eq((int) cfgError), eq((int) errorInd));
1340    }
1341
1342    /**
1343     * Tests the handling of Wps fail notification.
1344     */
1345    @Test
1346    public void testWpsTimeoutCallback() throws Exception {
1347        executeAndValidateInitializationSequence();
1348        assertNotNull(mISupplicantStaIfaceCallback);
1349
1350        short cfgError = ISupplicantStaIfaceCallback.WpsConfigError.MSG_TIMEOUT;
1351        short errorInd = ISupplicantStaIfaceCallback.WpsErrorIndication.NO_ERROR;
1352        mISupplicantStaIfaceCallback.onWpsEventFail(
1353                NativeUtil.macAddressToByteArray(BSSID), cfgError, errorInd);
1354        verify(mWifiMonitor).broadcastWpsTimeoutEvent(eq(WLAN0_IFACE_NAME));
1355    }
1356
1357    /**
1358     * Tests the handling of Wps pbc overlap notification.
1359     */
1360    @Test
1361    public void testWpsPbcOverlapCallback() throws Exception {
1362        executeAndValidateInitializationSequence();
1363        assertNotNull(mISupplicantStaIfaceCallback);
1364
1365        mISupplicantStaIfaceCallback.onWpsEventPbcOverlap();
1366        verify(mWifiMonitor).broadcastWpsOverlapEvent(eq(WLAN0_IFACE_NAME));
1367    }
1368
1369    /**
1370     * Tests the handling of service manager death notification.
1371     */
1372    @Test
1373    public void testServiceManagerDeathCallback() throws Exception {
1374        executeAndValidateInitializationSequence();
1375        assertNotNull(mServiceManagerDeathCaptor.getValue());
1376        assertTrue(mDut.isInitializationComplete());
1377        assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler));
1378
1379        mServiceManagerDeathCaptor.getValue().serviceDied(5L);
1380
1381        assertFalse(mDut.isInitializationComplete());
1382        verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN0_IFACE_NAME));
1383        verify(mSupplicantHalDeathHandler).onDeath();
1384    }
1385
1386    /**
1387     * Tests the handling of supplicant death notification.
1388     */
1389    @Test
1390    public void testSupplicantDeathCallback() throws Exception {
1391        executeAndValidateInitializationSequence();
1392        assertNotNull(mSupplicantDeathCaptor.getValue());
1393        assertTrue(mDut.isInitializationComplete());
1394        assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler));
1395
1396        mSupplicantDeathCaptor.getValue().serviceDied(5L);
1397
1398        assertFalse(mDut.isInitializationComplete());
1399        verify(mWifiMonitor).broadcastSupplicantDisconnectionEvent(eq(WLAN0_IFACE_NAME));
1400        verify(mSupplicantHalDeathHandler).onDeath();
1401    }
1402
1403    /**
1404     * When wpa_supplicant is dead, we could end up getting a remote exception on a hwbinder call
1405     * and then the death notification.
1406     */
1407    @Test
1408    public void testHandleRemoteExceptonAndDeathNotification() throws Exception {
1409        executeAndValidateInitializationSequence();
1410        assertTrue(mDut.registerDeathHandler(mSupplicantHalDeathHandler));
1411        assertTrue(mDut.isInitializationComplete());
1412
1413        // Throw remote exception on hwbinder call.
1414        when(mISupplicantStaIfaceMock.setPowerSave(anyBoolean()))
1415                .thenThrow(new RemoteException());
1416        assertFalse(mDut.setPowerSave(WLAN0_IFACE_NAME, true));
1417        verify(mISupplicantStaIfaceMock).setPowerSave(true);
1418
1419        // Check that remote exception cleared all internal state.
1420        assertFalse(mDut.isInitializationComplete());
1421
1422        // Ensure that futher calls fail because the remote exception clears any state.
1423        assertFalse(mDut.setPowerSave(WLAN0_IFACE_NAME, true));
1424        //.. No call to ISupplicantStaIface object
1425
1426        // Now trigger a death notification and ensure it's handled.
1427        assertNotNull(mSupplicantDeathCaptor.getValue());
1428        mSupplicantDeathCaptor.getValue().serviceDied(5L);
1429
1430        // External death notification fires only once!
1431        verify(mSupplicantHalDeathHandler).onDeath();
1432    }
1433
1434    /**
1435     * Tests the setting of log level.
1436     */
1437    @Test
1438    public void testSetLogLevel() throws Exception {
1439        when(mISupplicantMock.setDebugParams(anyInt(), anyBoolean(), anyBoolean()))
1440                .thenReturn(mStatusSuccess);
1441
1442        // Fail before initialization is performed.
1443        assertFalse(mDut.setLogLevel(true));
1444
1445        executeAndValidateInitializationSequence();
1446
1447        // This should work.
1448        assertTrue(mDut.setLogLevel(true));
1449        verify(mISupplicantMock)
1450                .setDebugParams(eq(ISupplicant.DebugLevel.DEBUG), eq(false), eq(false));
1451    }
1452
1453    /**
1454     * Tests the setting of concurrency priority.
1455     */
1456    @Test
1457    public void testConcurrencyPriority() throws Exception {
1458        when(mISupplicantMock.setConcurrencyPriority(anyInt())).thenReturn(mStatusSuccess);
1459
1460        // Fail before initialization is performed.
1461        assertFalse(mDut.setConcurrencyPriority(false));
1462
1463        executeAndValidateInitializationSequence();
1464
1465        // This should work.
1466        assertTrue(mDut.setConcurrencyPriority(false));
1467        verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.P2P));
1468        assertTrue(mDut.setConcurrencyPriority(true));
1469        verify(mISupplicantMock).setConcurrencyPriority(eq(IfaceType.STA));
1470    }
1471
1472    /**
1473     * Tests the start of wps registrar.
1474     */
1475    @Test
1476    public void testStartWpsRegistrar() throws Exception {
1477        when(mISupplicantStaIfaceMock.startWpsRegistrar(any(byte[].class), anyString()))
1478                .thenReturn(mStatusSuccess);
1479
1480        // Fail before initialization is performed.
1481        assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, null, null));
1482
1483        executeAndValidateInitializationSequence();
1484
1485        assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, null, null));
1486        verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString());
1487
1488        assertFalse(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, new String(), "452233"));
1489        verify(mISupplicantStaIfaceMock, never()).startWpsRegistrar(any(byte[].class), anyString());
1490
1491        assertTrue(mDut.startWpsRegistrar(WLAN0_IFACE_NAME, "45:23:12:12:12:98", "562535"));
1492        verify(mISupplicantStaIfaceMock).startWpsRegistrar(any(byte[].class), anyString());
1493    }
1494
1495    /**
1496     * Tests the start of wps PBC.
1497     */
1498    @Test
1499    public void testStartWpsPbc() throws Exception {
1500        when(mISupplicantStaIfaceMock.startWpsPbc(any(byte[].class))).thenReturn(mStatusSuccess);
1501        String bssid = "45:23:12:12:12:98";
1502        byte[] bssidBytes = {0x45, 0x23, 0x12, 0x12, 0x12, (byte) 0x98};
1503        byte[] anyBssidBytes = {0, 0, 0, 0, 0, 0};
1504
1505        // Fail before initialization is performed.
1506        assertFalse(mDut.startWpsPbc(WLAN0_IFACE_NAME, bssid));
1507        verify(mISupplicantStaIfaceMock, never()).startWpsPbc(any(byte[].class));
1508
1509        executeAndValidateInitializationSequence();
1510
1511        assertTrue(mDut.startWpsPbc(WLAN0_IFACE_NAME, bssid));
1512        verify(mISupplicantStaIfaceMock).startWpsPbc(eq(bssidBytes));
1513
1514        assertTrue(mDut.startWpsPbc(WLAN0_IFACE_NAME, null));
1515        verify(mISupplicantStaIfaceMock).startWpsPbc(eq(anyBssidBytes));
1516    }
1517
1518    private WifiConfiguration createTestWifiConfiguration() {
1519        WifiConfiguration config = new WifiConfiguration();
1520        config.networkId = SUPPLICANT_NETWORK_ID;
1521        return config;
1522    }
1523
1524    private void executeAndValidateHs20DeauthImminentCallback(boolean isEss) throws Exception {
1525        executeAndValidateInitializationSequence();
1526        assertNotNull(mISupplicantStaIfaceCallback);
1527
1528        byte[] bssid = NativeUtil.macAddressToByteArray(BSSID);
1529        int reasonCode = isEss ? WnmData.ESS : WnmData.ESS + 1;
1530        int reauthDelay = 5;
1531        mISupplicantStaIfaceCallback.onHs20DeauthImminentNotice(
1532                bssid, reasonCode, reauthDelay, HS20_URL);
1533
1534        ArgumentCaptor<WnmData> wnmDataCaptor = ArgumentCaptor.forClass(WnmData.class);
1535        verify(mWifiMonitor).broadcastWnmEvent(eq(WLAN0_IFACE_NAME), wnmDataCaptor.capture());
1536        assertEquals(
1537                ByteBufferReader.readInteger(
1538                        ByteBuffer.wrap(bssid), ByteOrder.BIG_ENDIAN, bssid.length),
1539                wnmDataCaptor.getValue().getBssid());
1540        assertEquals(isEss, wnmDataCaptor.getValue().isEss());
1541        assertEquals(reauthDelay, wnmDataCaptor.getValue().getDelay());
1542        assertEquals(HS20_URL, wnmDataCaptor.getValue().getUrl());
1543    }
1544
1545    private void executeAndValidateInitializationSequence() throws  Exception {
1546        executeAndValidateInitializationSequence(false, false, false, false);
1547    }
1548
1549    /**
1550     * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the
1551     * expected result. Verifies if ISupplicantStaIface manager is initialized or reset.
1552     * Each of the arguments will cause a different failure mode when set true.
1553     */
1554    private void executeAndValidateInitializationSequence(boolean causeRemoteException,
1555                                                          boolean getZeroInterfaces,
1556                                                          boolean getNullInterface,
1557                                                          boolean causeCallbackRegFailure)
1558            throws Exception {
1559        boolean shouldSucceed =
1560                !causeRemoteException && !getZeroInterfaces && !getNullInterface
1561                        && !causeCallbackRegFailure;
1562        // Setup callback mock answers
1563        ArrayList<ISupplicant.IfaceInfo> interfaces;
1564        if (getZeroInterfaces) {
1565            interfaces = new ArrayList<>();
1566        } else {
1567            interfaces = mIfaceInfoList;
1568        }
1569        doAnswer(new GetListInterfacesAnswer(interfaces)).when(mISupplicantMock)
1570                .listInterfaces(any(ISupplicant.listInterfacesCallback.class));
1571        if (causeRemoteException) {
1572            doThrow(new RemoteException("Some error!!!"))
1573                    .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class),
1574                    any(ISupplicant.getInterfaceCallback.class));
1575        } else {
1576            doAnswer(new GetGetInterfaceAnswer(getNullInterface))
1577                    .when(mISupplicantMock).getInterface(any(ISupplicant.IfaceInfo.class),
1578                    any(ISupplicant.getInterfaceCallback.class));
1579        }
1580        /** Callback registeration */
1581        if (causeCallbackRegFailure) {
1582            doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1583                public SupplicantStatus answer(ISupplicantStaIfaceCallback cb)
1584                        throws RemoteException {
1585                    return mStatusFailure;
1586                }
1587            }).when(mISupplicantStaIfaceMock)
1588                    .registerCallback(any(ISupplicantStaIfaceCallback.class));
1589        } else {
1590            doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1591                public SupplicantStatus answer(ISupplicantStaIfaceCallback cb)
1592                        throws RemoteException {
1593                    mISupplicantStaIfaceCallback = cb;
1594                    return mStatusSuccess;
1595                }
1596            }).when(mISupplicantStaIfaceMock)
1597                    .registerCallback(any(ISupplicantStaIfaceCallback.class));
1598        }
1599
1600        mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantStaIfaceMock,
1601                mWifiMonitor);
1602        // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications
1603        assertTrue(mDut.initialize());
1604        // verify: service manager initialization sequence
1605        mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
1606                anyLong());
1607        mInOrder.verify(mServiceManagerMock).registerForNotifications(
1608                eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
1609        // act: cause the onRegistration(...) callback to execute
1610        mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true);
1611
1612        assertTrue(mDut.isInitializationComplete());
1613        assertTrue(mDut.setupIface(WLAN0_IFACE_NAME) == shouldSucceed);
1614        mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(),
1615                anyLong());
1616        // verify: listInterfaces is called
1617        mInOrder.verify(mISupplicantMock).listInterfaces(
1618                any(ISupplicant.listInterfacesCallback.class));
1619        if (!getZeroInterfaces) {
1620            mInOrder.verify(mISupplicantMock)
1621                    .getInterface(any(ISupplicant.IfaceInfo.class),
1622                            any(ISupplicant.getInterfaceCallback.class));
1623        }
1624        if (!causeRemoteException && !getZeroInterfaces && !getNullInterface) {
1625            mInOrder.verify(mISupplicantStaIfaceMock)
1626                    .registerCallback(any(ISupplicantStaIfaceCallback.class));
1627        }
1628    }
1629
1630    /**
1631     * Calls.initialize(), mocking various call back answers and verifying flow, asserting for the
1632     * expected result. Verifies if ISupplicantStaIface manager is initialized or reset.
1633     * Each of the arguments will cause a different failure mode when set true.
1634     */
1635    private void executeAndValidateInitializationSequenceV1_1(boolean causeRemoteException,
1636                                                               boolean getNullInterface)
1637            throws Exception {
1638        boolean shouldSucceed = !causeRemoteException && !getNullInterface;
1639        // Setup callback mock answers
1640        if (causeRemoteException) {
1641            doThrow(new RemoteException("Some error!!!"))
1642                    .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class),
1643                    any(android.hardware.wifi.supplicant.V1_1.ISupplicant
1644                            .addInterfaceCallback.class));
1645        } else {
1646            doAnswer(new GetAddInterfaceAnswer(getNullInterface))
1647                    .when(mISupplicantMockV1_1).addInterface(any(ISupplicant.IfaceInfo.class),
1648                    any(android.hardware.wifi.supplicant.V1_1.ISupplicant
1649                            .addInterfaceCallback.class));
1650        }
1651        /** Callback registeration */
1652        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1653            public SupplicantStatus answer(
1654                    android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback cb)
1655                    throws RemoteException {
1656                mISupplicantStaIfaceCallbackV1_1 = cb;
1657                return mStatusSuccess;
1658            }
1659        }).when(mISupplicantStaIfaceMockV1_1)
1660                .registerCallback_1_1(
1661                any(android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback.class));
1662
1663        mInOrder = inOrder(mServiceManagerMock, mISupplicantMock, mISupplicantMockV1_1,
1664                mISupplicantStaIfaceMockV1_1, mWifiMonitor);
1665        // Initialize SupplicantStaIfaceHal, should call serviceManager.registerForNotifications
1666        assertTrue(mDut.initialize());
1667        // verify: service manager initialization sequence
1668        mInOrder.verify(mServiceManagerMock).linkToDeath(mServiceManagerDeathCaptor.capture(),
1669                anyLong());
1670        mInOrder.verify(mServiceManagerMock).registerForNotifications(
1671                eq(ISupplicant.kInterfaceName), eq(""), mServiceNotificationCaptor.capture());
1672        // act: cause the onRegistration(...) callback to execute
1673        mServiceNotificationCaptor.getValue().onRegistration(ISupplicant.kInterfaceName, "", true);
1674
1675        assertTrue(mDut.isInitializationComplete());
1676        assertTrue(mDut.setupIface(WLAN0_IFACE_NAME) == shouldSucceed);
1677        mInOrder.verify(mISupplicantMock).linkToDeath(mSupplicantDeathCaptor.capture(),
1678                anyLong());
1679        // verify: addInterface is called
1680        mInOrder.verify(mISupplicantMockV1_1)
1681                .addInterface(any(ISupplicant.IfaceInfo.class),
1682                        any(android.hardware.wifi.supplicant.V1_1.ISupplicant
1683                                .addInterfaceCallback.class));
1684        if (!causeRemoteException && !getNullInterface) {
1685            mInOrder.verify(mISupplicantStaIfaceMockV1_1)
1686                    .registerCallback_1_1(
1687                    any(android.hardware.wifi.supplicant.V1_1.ISupplicantStaIfaceCallback.class));
1688        }
1689
1690        // Ensure we don't try to use the listInterfaces method from 1.0 version.
1691        verify(mISupplicantMock, never()).listInterfaces(
1692                any(ISupplicant.listInterfacesCallback.class));
1693        verify(mISupplicantMock, never()).getInterface(any(ISupplicant.IfaceInfo.class),
1694                        any(ISupplicant.getInterfaceCallback.class));
1695    }
1696
1697    private SupplicantStatus createSupplicantStatus(int code) {
1698        SupplicantStatus status = new SupplicantStatus();
1699        status.code = code;
1700        return status;
1701    }
1702
1703    /**
1704     * Create an IfaceInfo with given type and name
1705     */
1706    private ISupplicant.IfaceInfo createIfaceInfo(int type, String name) {
1707        ISupplicant.IfaceInfo info = new ISupplicant.IfaceInfo();
1708        info.type = type;
1709        info.name = name;
1710        return info;
1711    }
1712
1713    private class GetListInterfacesAnswer extends MockAnswerUtil.AnswerWithArguments {
1714        private ArrayList<ISupplicant.IfaceInfo> mInterfaceList;
1715
1716        GetListInterfacesAnswer(ArrayList<ISupplicant.IfaceInfo> ifaces) {
1717            mInterfaceList = ifaces;
1718        }
1719
1720        public void answer(ISupplicant.listInterfacesCallback cb) {
1721            cb.onValues(mStatusSuccess, mInterfaceList);
1722        }
1723    }
1724
1725    private class GetGetInterfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
1726        boolean mGetNullInterface;
1727
1728        GetGetInterfaceAnswer(boolean getNullInterface) {
1729            mGetNullInterface = getNullInterface;
1730        }
1731
1732        public void answer(ISupplicant.IfaceInfo iface, ISupplicant.getInterfaceCallback cb) {
1733            if (mGetNullInterface) {
1734                cb.onValues(mStatusSuccess, null);
1735            } else {
1736                cb.onValues(mStatusSuccess, mISupplicantIfaceMock);
1737            }
1738        }
1739    }
1740
1741    private class GetAddInterfaceAnswer extends MockAnswerUtil.AnswerWithArguments {
1742        boolean mGetNullInterface;
1743
1744        GetAddInterfaceAnswer(boolean getNullInterface) {
1745            mGetNullInterface = getNullInterface;
1746        }
1747
1748        public void answer(ISupplicant.IfaceInfo iface,
1749                           android.hardware.wifi.supplicant.V1_1.ISupplicant
1750                                   .addInterfaceCallback cb) {
1751            if (mGetNullInterface) {
1752                cb.onValues(mStatusSuccess, null);
1753            } else {
1754                cb.onValues(mStatusSuccess, mISupplicantIfaceMock);
1755            }
1756        }
1757    }
1758
1759    /**
1760     * Setup mocks for connect sequence.
1761     */
1762    private void setupMocksForConnectSequence(final boolean haveExistingNetwork) throws Exception {
1763        final int existingNetworkId = SUPPLICANT_NETWORK_ID;
1764        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1765            public SupplicantStatus answer() throws RemoteException {
1766                return mStatusSuccess;
1767            }
1768        }).when(mISupplicantStaIfaceMock).disconnect();
1769        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1770            public void answer(ISupplicantStaIface.listNetworksCallback cb) throws RemoteException {
1771                if (haveExistingNetwork) {
1772                    cb.onValues(mStatusSuccess, new ArrayList<>(Arrays.asList(existingNetworkId)));
1773                } else {
1774                    cb.onValues(mStatusSuccess, new ArrayList<>());
1775                }
1776            }
1777        }).when(mISupplicantStaIfaceMock)
1778                .listNetworks(any(ISupplicantStaIface.listNetworksCallback.class));
1779        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1780            public SupplicantStatus answer(int id) throws RemoteException {
1781                return mStatusSuccess;
1782            }
1783        }).when(mISupplicantStaIfaceMock).removeNetwork(eq(existingNetworkId));
1784        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1785            public void answer(ISupplicantStaIface.addNetworkCallback cb) throws RemoteException {
1786                cb.onValues(mStatusSuccess, mock(ISupplicantStaNetwork.class));
1787                return;
1788            }
1789        }).when(mISupplicantStaIfaceMock).addNetwork(
1790                any(ISupplicantStaIface.addNetworkCallback.class));
1791        when(mSupplicantStaNetworkMock.saveWifiConfiguration(any(WifiConfiguration.class)))
1792                .thenReturn(true);
1793        when(mSupplicantStaNetworkMock.select()).thenReturn(true);
1794    }
1795
1796    /**
1797     * Helper function to validate the connect sequence.
1798     */
1799    private void validateConnectSequence(
1800            final boolean haveExistingNetwork, int numNetworkAdditions) throws Exception {
1801        if (haveExistingNetwork) {
1802            verify(mISupplicantStaIfaceMock).removeNetwork(anyInt());
1803        }
1804        verify(mISupplicantStaIfaceMock, times(numNetworkAdditions))
1805                .addNetwork(any(ISupplicantStaIface.addNetworkCallback.class));
1806        verify(mSupplicantStaNetworkMock, times(numNetworkAdditions))
1807                .saveWifiConfiguration(any(WifiConfiguration.class));
1808        verify(mSupplicantStaNetworkMock, times(numNetworkAdditions)).select();
1809    }
1810
1811    /**
1812     * Helper function to execute all the actions to perform connection to the network.
1813     *
1814     * @param newFrameworkNetworkId Framework Network Id of the new network to connect.
1815     * @param haveExistingNetwork Removes the existing network.
1816     * @return the WifiConfiguration object of the new network to connect.
1817     */
1818    private WifiConfiguration executeAndValidateConnectSequence(
1819            final int newFrameworkNetworkId, final boolean haveExistingNetwork) throws Exception {
1820        setupMocksForConnectSequence(haveExistingNetwork);
1821        WifiConfiguration config = new WifiConfiguration();
1822        config.networkId = newFrameworkNetworkId;
1823        assertTrue(mDut.connectToNetwork(WLAN0_IFACE_NAME, config));
1824        validateConnectSequence(haveExistingNetwork, 1);
1825        return config;
1826    }
1827
1828    /**
1829     * Setup mocks for roam sequence.
1830     */
1831    private void setupMocksForRoamSequence(String roamBssid) throws Exception {
1832        doAnswer(new MockAnswerUtil.AnswerWithArguments() {
1833            public SupplicantStatus answer() throws RemoteException {
1834                return mStatusSuccess;
1835            }
1836        }).when(mISupplicantStaIfaceMock).reassociate();
1837        when(mSupplicantStaNetworkMock.setBssid(eq(roamBssid))).thenReturn(true);
1838    }
1839
1840    /**
1841     * Helper function to execute all the actions to perform roaming to the network.
1842     *
1843     * @param sameNetwork Roam to the same network or not.
1844     */
1845    private void executeAndValidateRoamSequence(boolean sameNetwork) throws Exception {
1846        int connectedNetworkId = ROAM_NETWORK_ID;
1847        String roamBssid = BSSID;
1848        int roamNetworkId;
1849        if (sameNetwork) {
1850            roamNetworkId = connectedNetworkId;
1851        } else {
1852            roamNetworkId = connectedNetworkId + 1;
1853        }
1854        executeAndValidateConnectSequence(connectedNetworkId, false);
1855        setupMocksForRoamSequence(roamBssid);
1856
1857        WifiConfiguration roamingConfig = new WifiConfiguration();
1858        roamingConfig.networkId = roamNetworkId;
1859        roamingConfig.getNetworkSelectionStatus().setNetworkSelectionBSSID(roamBssid);
1860        assertTrue(mDut.roamToNetwork(WLAN0_IFACE_NAME, roamingConfig));
1861
1862        if (!sameNetwork) {
1863            validateConnectSequence(false, 2);
1864            verify(mSupplicantStaNetworkMock, never()).setBssid(anyString());
1865            verify(mISupplicantStaIfaceMock, never()).reassociate();
1866        } else {
1867            verify(mSupplicantStaNetworkMock).setBssid(eq(roamBssid));
1868            verify(mISupplicantStaIfaceMock).reassociate();
1869        }
1870    }
1871}
1872