Home | History | Annotate | Download | only in wifi
      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 package com.android.server.wifi;
     17 
     18 import static org.junit.Assert.*;
     19 import static org.mockito.Matchers.any;
     20 import static org.mockito.Matchers.anyBoolean;
     21 import static org.mockito.Matchers.anyInt;
     22 import static org.mockito.Matchers.anyLong;
     23 import static org.mockito.Matchers.anyShort;
     24 import static org.mockito.Matchers.anyString;
     25 import static org.mockito.Matchers.eq;
     26 import static org.mockito.Mockito.*;
     27 
     28 import android.app.test.MockAnswerUtil;
     29 import android.content.Context;
     30 import android.hardware.wifi.supplicant.V1_0.ISupplicant;
     31 import android.hardware.wifi.supplicant.V1_0.ISupplicantIface;
     32 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIface;
     33 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
     34 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback.BssidChangeReason;
     35 import android.hardware.wifi.supplicant.V1_0.ISupplicantStaNetwork;
     36 import android.hardware.wifi.supplicant.V1_0.IfaceType;
     37 import android.hardware.wifi.supplicant.V1_0.SupplicantStatus;
     38 import android.hardware.wifi.supplicant.V1_0.SupplicantStatusCode;
     39 import android.hardware.wifi.supplicant.V1_0.WpsConfigMethods;
     40 import android.hidl.manager.V1_0.IServiceManager;
     41 import android.hidl.manager.V1_0.IServiceNotification;
     42 import android.net.IpConfiguration;
     43 import android.net.wifi.SupplicantState;
     44 import android.net.wifi.WifiConfiguration;
     45 import android.net.wifi.WifiManager;
     46 import android.net.wifi.WifiSsid;
     47 import android.os.IHwBinder;
     48 import android.os.RemoteException;
     49 import android.text.TextUtils;
     50 import android.util.SparseArray;
     51 
     52 import com.android.server.wifi.hotspot2.AnqpEvent;
     53 import com.android.server.wifi.hotspot2.IconEvent;
     54 import com.android.server.wifi.hotspot2.WnmData;
     55 import com.android.server.wifi.util.NativeUtil;
     56 
     57 import libcore.util.NonNull;
     58 
     59 import org.junit.Before;
     60 import org.junit.Test;
     61 import org.mockito.ArgumentCaptor;
     62 import org.mockito.InOrder;
     63 import org.mockito.Mock;
     64 import org.mockito.MockitoAnnotations;
     65 
     66 import java.nio.ByteBuffer;
     67 import java.nio.ByteOrder;
     68 import java.util.ArrayList;
     69 import java.util.Arrays;
     70 import java.util.HashMap;
     71 import java.util.Map;
     72 import java.util.Random;
     73 
     74 /**
     75  * Unit tests for SupplicantStaIfaceHal
     76  */
     77 public 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 (at) blah.com";
    862         String encryptedIdentity = "blah2 (at) 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 (at) 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