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