/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wifi;

import static android.net.wifi.WifiManager.EXTRA_PREVIOUS_WIFI_AP_STATE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_FAILURE_REASON;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLING;

import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;

import android.app.ActivityManager;
import android.app.test.MockAnswerUtil.AnswerWithArguments;
import android.app.test.TestAlarmManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.hardware.wifi.supplicant.V1_0.ISupplicantStaIfaceCallback;
import android.net.ConnectivityManager;
import android.net.DhcpResults;
import android.net.LinkProperties;
import android.net.dhcp.DhcpClient;
import android.net.ip.IpManager;
import android.net.wifi.IApInterface;
import android.net.wifi.IClientInterface;
import android.net.wifi.IWificond;
import android.net.wifi.ScanResult;
import android.net.wifi.SupplicantState;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiScanner;
import android.net.wifi.WifiSsid;
import android.net.wifi.WpsInfo;
import android.net.wifi.hotspot2.PasspointConfiguration;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.net.wifi.p2p.IWifiP2pManager;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IInterface;
import android.os.INetworkManagementService;
import android.os.IPowerManager;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.test.TestLooper;
import android.provider.Settings;
import android.security.KeyStore;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.test.mock.MockContentProvider;
import android.test.mock.MockContentResolver;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.Log;
import android.util.Pair;
import android.util.SparseArray;

import com.android.internal.R;
import com.android.internal.app.IBatteryStats;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IState;
import com.android.internal.util.StateMachine;
import com.android.server.wifi.hotspot2.NetworkDetail;
import com.android.server.wifi.hotspot2.PasspointManager;
import com.android.server.wifi.p2p.WifiP2pServiceImpl;
import com.android.server.wifi.util.WifiPermissionsUtil;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.io.ByteArrayOutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;

/**
 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
 */
@SmallTest
public class WifiStateMachineTest {
    public static final String TAG = "WifiStateMachineTest";

    private static final int MANAGED_PROFILE_UID = 1100000;
    private static final int OTHER_USER_UID = 1200000;
    private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
            (ActivityManager.isLowRamDeviceStatic()
                    ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
                    : WifiStateMachine.NUM_LOG_RECS_VERBOSE);
    private static final int WPS_SUPPLICANT_NETWORK_ID = 5;
    private static final int WPS_FRAMEWORK_NETWORK_ID = 10;
    private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";

    private long mBinderToken;

    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
        return mock(class1, withSettings().extraInterfaces(interfaces));
    }

    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
        T tImpl = mockWithInterfaces(class1, iface);
        IBinder binder = mock(IBinder.class);
        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
        when(binder.queryLocalInterface(iface.getCanonicalName()))
                .thenReturn((IInterface) tImpl);
        return binder;
    }

    private void enableDebugLogs() {
        mWsm.enableVerboseLogging(1);
    }

    private FrameworkFacade getFrameworkFacade() throws Exception {
        FrameworkFacade facade = mock(FrameworkFacade.class);

        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
                mockWithInterfaces(IBinder.class, INetworkManagementService.class));

        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);

        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
                IWifiP2pManager.class.getCanonicalName());

        final CountDownLatch untilDone = new CountDownLatch(1);
        mP2pThread = new HandlerThread("WifiP2pMockThread") {
            @Override
            protected void onLooperPrepared() {
                untilDone.countDown();
            }
        };

        mP2pThread.start();
        untilDone.await();

        Handler handler = new Handler(mP2pThread.getLooper());
        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));

        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);

        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
                .then(new AnswerWithArguments() {
                    public IpManager answer(
                            Context context, String ifname, IpManager.Callback callback) {
                        mIpManagerCallback = callback;
                        return mIpManager;
                    }
                });

        return facade;
    }

    private Context getContext() throws Exception {
        PackageManager pkgMgr = mock(PackageManager.class);
        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);

        Context context = mock(Context.class);
        when(context.getPackageManager()).thenReturn(pkgMgr);

        MockContentResolver mockContentResolver = new MockContentResolver();
        mockContentResolver.addProvider(Settings.AUTHORITY,
                new MockContentProvider(context) {
                    @Override
                    public Bundle call(String method, String arg, Bundle extras) {
                        return new Bundle();
                    }
                });
        when(context.getContentResolver()).thenReturn(mockContentResolver);

        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
                new PowerManager(context, mock(IPowerManager.class), new Handler()));

        mAlarmManager = new TestAlarmManager();
        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
                mAlarmManager.getAlarmManager());

        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
                mock(ConnectivityManager.class));

        return context;
    }

    private MockResources getMockResources() {
        MockResources resources = new MockResources();
        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
        resources.setBoolean(
                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, false);
        return resources;
    }

    private IState getCurrentState() throws
            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
        method.setAccessible(true);
        return (IState) method.invoke(mWsm);
    }

    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
        Field field = StateMachine.class.getDeclaredField("mSmThread");
        field.setAccessible(true);
        return (HandlerThread) field.get(wsm);
    }

    private static void stopLooper(final Looper looper) throws Exception {
        new Handler(looper).post(new Runnable() {
            @Override
            public void run() {
                looper.quitSafely();
            }
        });
    }

    private void dumpState() {
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        PrintWriter writer = new PrintWriter(stream);
        mWsm.dump(null, writer, null);
        writer.flush();
        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
    }

    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
        ie[0] = ScanResults.generateSsidIe(sSSID);
        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
                Long.MAX_VALUE, /* needed so that scan results aren't rejected because
                                   there older than scan start */
                ie, new ArrayList<String>());
        return detail;
    }

    private ArrayList<ScanDetail> getMockScanResults() {
        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();

        int rssi = -65;
        list.add(getGoogleGuestScanDetail(rssi));
        return list;
    }

    private void injectDhcpSuccess(DhcpResults dhcpResults) {
        mIpManagerCallback.onNewDhcpResults(dhcpResults);
        mIpManagerCallback.onProvisioningSuccess(new LinkProperties());
    }

    private void injectDhcpFailure() {
        mIpManagerCallback.onNewDhcpResults(null);
        mIpManagerCallback.onProvisioningFailure(new LinkProperties());
    }

    static final String   sSSID = "\"GoogleGuest\"";
    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
    static final String   sBSSID = "01:02:03:04:05:06";
    static final int      sFreq = 2437;
    static final String   WIFI_IFACE_NAME = "mockWlan";

    WifiStateMachine mWsm;
    HandlerThread mWsmThread;
    HandlerThread mP2pThread;
    HandlerThread mSyncThread;
    AsyncChannel  mWsmAsyncChannel;
    TestAlarmManager mAlarmManager;
    MockWifiMonitor mWifiMonitor;
    TestLooper mLooper;
    Context mContext;
    MockResources mResources;
    FrameworkFacade mFrameworkFacade;
    IpManager.Callback mIpManagerCallback;
    PhoneStateListener mPhoneStateListener;

    final ArgumentCaptor<SoftApManager.Listener> mSoftApManagerListenerCaptor =
                    ArgumentCaptor.forClass(SoftApManager.Listener.class);

    @Mock WifiScanner mWifiScanner;
    @Mock SupplicantStateTracker mSupplicantStateTracker;
    @Mock WifiMetrics mWifiMetrics;
    @Mock UserManager mUserManager;
    @Mock WifiApConfigStore mApConfigStore;
    @Mock BackupManagerProxy mBackupManagerProxy;
    @Mock WifiCountryCode mCountryCode;
    @Mock WifiInjector mWifiInjector;
    @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
    @Mock PropertyService mPropertyService;
    @Mock BuildProperties mBuildProperties;
    @Mock IWificond mWificond;
    @Mock IApInterface mApInterface;
    @Mock IClientInterface mClientInterface;
    @Mock IBinder mApInterfaceBinder;
    @Mock IBinder mClientInterfaceBinder;
    @Mock IBinder mPackageManagerBinder;
    @Mock WifiConfigManager mWifiConfigManager;
    @Mock WifiNative mWifiNative;
    @Mock WifiConnectivityManager mWifiConnectivityManager;
    @Mock SoftApManager mSoftApManager;
    @Mock WifiStateTracker mWifiStateTracker;
    @Mock PasspointManager mPasspointManager;
    @Mock SelfRecovery mSelfRecovery;
    @Mock WifiPermissionsUtil mWifiPermissionsUtil;
    @Mock IpManager mIpManager;
    @Mock TelephonyManager mTelephonyManager;
    @Mock WrongPasswordNotifier mWrongPasswordNotifier;
    @Mock Clock mClock;

    public WifiStateMachineTest() throws Exception {
    }

    @Before
    public void setUp() throws Exception {
        Log.d(TAG, "Setting up ...");

        // Ensure looper exists
        mLooper = new TestLooper();

        MockitoAnnotations.initMocks(this);

        /** uncomment this to enable logs from WifiStateMachines */
        // enableDebugLogs();

        mWifiMonitor = new MockWifiMonitor();
        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
        when(mWifiInjector.getClock()).thenReturn(new Clock());
        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
        when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
        when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
        when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
        when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class));
        when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn(
                mock(BaseWifiDiagnostics.class));
        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
        when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
        when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
        when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean()))
                .thenReturn(mWifiConnectivityManager);
        when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
                mSoftApManagerListenerCaptor.capture(), any(IApInterface.class),
                any(WifiConfiguration.class)))
                .thenReturn(mSoftApManager);
        when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
        when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker);
        when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor);
        when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
        when(mWifiInjector.getSelfRecovery()).thenReturn(mSelfRecovery);
        when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil);
        when(mWifiInjector.makeTelephonyManager()).thenReturn(mTelephonyManager);
        when(mWifiInjector.getClock()).thenReturn(mClock);

        when(mWifiNative.setupForClientMode())
                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mClientInterface));
        when(mWifiNative.setupForSoftApMode())
                .thenReturn(Pair.create(WifiNative.SETUP_SUCCESS, mApInterface));
        when(mApInterface.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
        when(mWifiNative.getInterfaceName()).thenReturn(WIFI_IFACE_NAME);
        when(mWifiNative.enableSupplicant()).thenReturn(true);
        when(mWifiNative.disableSupplicant()).thenReturn(true);
        when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0);


        mFrameworkFacade = getFrameworkFacade();
        mContext = getContext();

        mResources = getMockResources();
        when(mContext.getResources()).thenReturn(mResources);

        when(mFrameworkFacade.getIntegerSetting(mContext,
                Settings.Global.WIFI_FREQUENCY_BAND,
                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
                WifiManager.WIFI_FREQUENCY_BAND_AUTO);

        when(mFrameworkFacade.makeApConfigStore(eq(mContext), eq(mBackupManagerProxy)))
                .thenReturn(mApConfigStore);

        when(mFrameworkFacade.makeSupplicantStateTracker(
                any(Context.class), any(WifiConfigManager.class),
                any(Handler.class))).thenReturn(mSupplicantStateTracker);

        when(mUserManager.getProfileParent(11))
                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
                new UserInfo(11, "managed profile", 0)));

        when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
        when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder);

        doAnswer(new AnswerWithArguments() {
            public void answer(PhoneStateListener phoneStateListener, int events)
                    throws Exception {
                mPhoneStateListener = phoneStateListener;
            }
        }).when(mTelephonyManager).listen(any(PhoneStateListener.class), anyInt());

        initializeWsm();
    }

    private void initializeWsm() throws Exception {
        mWsm = new WifiStateMachine(mContext, mFrameworkFacade, mLooper.getLooper(),
                mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative,
                mWrongPasswordNotifier);
        mWsmThread = getWsmHandlerThread(mWsm);

        final AsyncChannel channel = new AsyncChannel();
        Handler handler = new Handler(mLooper.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                            mWsmAsyncChannel = channel;
                        } else {
                            Log.d(TAG, "Failed to connect Command channel " + this);
                        }
                        break;
                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
                        Log.d(TAG, "Command channel disconnected" + this);
                        break;
                }
            }
        };

        channel.connect(mContext, handler, mWsm.getMessenger());
        mLooper.dispatchAll();
        /* Now channel is supposed to be connected */

        mBinderToken = Binder.clearCallingIdentity();

        /* Send the BOOT_COMPLETED message to setup some WSM state. */
        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
        mLooper.dispatchAll();
    }

    @After
    public void cleanUp() throws Exception {
        Binder.restoreCallingIdentity(mBinderToken);

        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());

        mWsmThread = null;
        mP2pThread = null;
        mSyncThread = null;
        mWsmAsyncChannel = null;
        mWsm = null;
    }

    @Test
    public void createNew() throws Exception {
        assertEquals("InitialState", getCurrentState().getName());

        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
    }

    @Test
    public void loadComponentsInStaMode() throws Exception {
        startSupplicantAndDispatchMessages();

        verify(mContext).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL));

        assertEquals("DisconnectedState", getCurrentState().getName());
    }

    private void checkApStateChangedBroadcast(Intent intent, int expectedCurrentState,
            int expectedPrevState, int expectedErrorCode, String expectedIfaceName,
            int expectedMode) {
        int currentState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
        int prevState = intent.getIntExtra(EXTRA_PREVIOUS_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
        int errorCode = intent.getIntExtra(EXTRA_WIFI_AP_FAILURE_REASON, HOTSPOT_NO_ERROR);
        String ifaceName = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
        int mode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, WifiManager.IFACE_IP_MODE_UNSPECIFIED);
        assertEquals(expectedCurrentState, currentState);
        assertEquals(expectedPrevState, prevState);
        assertEquals(expectedErrorCode, errorCode);
        assertEquals(expectedIfaceName, ifaceName);
        assertEquals(expectedMode, mode);
    }

    private void loadComponentsInApMode(int mode) throws Exception {
        SoftApModeConfiguration config = new SoftApModeConfiguration(mode, new WifiConfiguration());
        mWsm.setHostApRunning(config, true);
        mLooper.dispatchAll();

        assertEquals("SoftApState", getCurrentState().getName());

        verify(mWifiNative).setupForSoftApMode();
        verify(mSoftApManager).start();

        // reset expectations for mContext due to previously sent AP broadcast
        reset(mContext);

        // get the SoftApManager.Listener and trigger some updates
        SoftApManager.Listener listener = mSoftApManagerListenerCaptor.getValue();
        listener.onStateChanged(WIFI_AP_STATE_ENABLING, 0);
        listener.onStateChanged(WIFI_AP_STATE_ENABLED, 0);
        listener.onStateChanged(WIFI_AP_STATE_DISABLING, 0);
        // note, this will trigger a mode change when TestLooper is dispatched
        listener.onStateChanged(WIFI_AP_STATE_DISABLED, 0);

        ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mContext, times(4))
                .sendStickyBroadcastAsUser(intentCaptor.capture(), eq(UserHandle.ALL));

        List<Intent> capturedIntents = intentCaptor.getAllValues();
        checkApStateChangedBroadcast(capturedIntents.get(0), WIFI_AP_STATE_ENABLING,
                WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
        checkApStateChangedBroadcast(capturedIntents.get(1), WIFI_AP_STATE_ENABLED,
                WIFI_AP_STATE_ENABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
        checkApStateChangedBroadcast(capturedIntents.get(2), WIFI_AP_STATE_DISABLING,
                WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
        checkApStateChangedBroadcast(capturedIntents.get(3), WIFI_AP_STATE_DISABLED,
                WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME, mode);
    }

    @Test
    public void loadComponentsInApModeForTethering() throws Exception {
        loadComponentsInApMode(WifiManager.IFACE_IP_MODE_TETHERED);
    }

    @Test
    public void loadComponentsInApModeForLOHS() throws Exception {
        loadComponentsInApMode(WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
    }

    @Test
    public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception {
        when(mWifiNative.enableSupplicant()).thenReturn(false);
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
        // we should not be sending a wifi enabling update
        verify(mContext, never()).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());
    }

    @Test
    public void shouldRequireWificondToLeaveInitialState() throws Exception {
        // We start out with valid default values, break them going backwards so that
        // we test all the bailout cases.

        // ClientInterface dies after creation.
        doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt());
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());

        // Failed to even create the client interface.
        when(mWificond.createClientInterface()).thenReturn(null);
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());

        // Failed to get wificond proxy.
        when(mWifiInjector.makeWificond()).thenReturn(null);
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
    }

    @Test
    public void loadComponentsFailure() throws Exception {
        when(mWifiNative.enableSupplicant()).thenReturn(false);

        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());

        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
    }

    @Test
    public void checkInitialStateStickyWhenDisabledMode() throws Exception {
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());

        mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest());
        assertEquals("InitialState", getCurrentState().getName());
    }

    @Test
    public void shouldStartSupplicantWhenConnectModeRequested() throws Exception {
        // The first time we start out in InitialState, we sit around here.
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());

        // But if someone tells us to enter connect mode, we start up supplicant
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        assertEquals("SupplicantStartingState", getCurrentState().getName());
    }

    /**
     *  Test that mode changes accurately reflect the value for isWifiEnabled.
     */
    @Test
    public void checkIsWifiEnabledForModeChanges() throws Exception {
        // Check initial state
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());

        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
        startSupplicantAndDispatchMessages();
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
        assertEquals("ScanModeState", getCurrentState().getName());
        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
        verify(mContext, never()).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());


        // switch to connect mode and verify wifi is reported as enabled
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
        verify(mContext).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), eq(UserHandle.ALL));

        // reset the expectations on mContext since we did get an expected broadcast, but we should
        // not on the next transition
        reset(mContext);

        // now go back to scan mode with "wifi disabled" to verify the reported wifi state.
        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
                     mWsm.getOperationalModeForTest());
        assertEquals("ScanModeState", getCurrentState().getName());
        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
        verify(mContext, never()).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());

        // now go to AP mode
        mWsm.setSupplicantRunning(false);
        mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
        mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT);
        SoftApModeConfiguration config = new SoftApModeConfiguration(
                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
        mWsm.setHostApRunning(config, true);
        mLooper.dispatchAll();
        assertEquals("SoftApState", getCurrentState().getName());
        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
        verify(mContext, never()).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());
    }

    private class WifiEnablingStateIntentMatcher implements ArgumentMatcher<Intent> {
        @Override
        public boolean matches(Intent intent) {
            if (WifiManager.WIFI_STATE_CHANGED_ACTION != intent.getAction()) {
                // not the correct type
                return false;
            }
            return WifiManager.WIFI_STATE_ENABLING
                    == intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
                                          WifiManager.WIFI_STATE_DISABLED);
        }
    }

    /**
     * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
     * is started.
     */
    @Test
    public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
        // Check initial state
        mLooper.dispatchAll();
        assertEquals("InitialState", getCurrentState().getName());
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());

        // Update the mode
        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());

        // Start supplicant so we move to the next state
        startSupplicantAndDispatchMessages();

        assertEquals("ScanModeState", getCurrentState().getName());
        verify(mContext, never()).sendStickyBroadcastAsUser(
                (Intent) argThat(new WifiEnablingStateIntentMatcher()), any());
    }

    /**
     * Verifies that configs can be removed when in client mode.
     */
    @Test
    public void canRemoveNetworkConfigInClientMode() throws Exception {
        boolean result;
        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
        initializeAndAddNetworkAndVerifySuccess();
        mLooper.startAutoDispatch();
        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
        mLooper.stopAutoDispatch();
        assertTrue(result);
    }

    /**
     * Verifies that configs can be removed when not in client mode.
     */
    @Test
    public void canRemoveNetworkConfigWhenWifiDisabled() {
        boolean result;
        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
        mLooper.startAutoDispatch();
        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
        mLooper.stopAutoDispatch();

        assertTrue(result);
        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
    }

    /**
     * Verifies that configs can be forgotten when in client mode.
     */
    @Test
    public void canForgetNetworkConfigInClientMode() throws Exception {
        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
        initializeAndAddNetworkAndVerifySuccess();
        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
        mLooper.dispatchAll();
        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
    }

    /**
     * Verifies that configs can be removed when not in client mode.
     */
    @Test
    public void canForgetNetworkConfigWhenWifiDisabled() throws Exception {
        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
        mLooper.dispatchAll();
        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
    }

    /**
     * Helper method to move through SupplicantStarting and SupplicantStarted states.
     */
    private void startSupplicantAndDispatchMessages() throws Exception {
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();

        assertEquals("SupplicantStartingState", getCurrentState().getName());

        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
        when(mWifiNative.setModelName(anyString())).thenReturn(true);
        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);

        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
        mLooper.dispatchAll();

        verify(mWifiNative).setupForClientMode();
        verify(mWifiLastResortWatchdog).clearAllFailureCounts();
    }

    private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception {
        WifiConfiguration config = new WifiConfiguration();
        config.SSID = sSSID;
        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        config.hiddenSSID = isHidden;

        when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
                .thenReturn(new NetworkUpdateResult(0));
        when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
        when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
        when(mWifiConfigManager.getConfiguredNetworkWithPassword(0)).thenReturn(config);

        mLooper.startAutoDispatch();
        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt());

        mLooper.startAutoDispatch();
        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
        mLooper.stopAutoDispatch();
        assertEquals(1, configs.size());

        WifiConfiguration config2 = configs.get(0);
        assertEquals("\"GoogleGuest\"", config2.SSID);
        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
    }

    private void initializeAndAddNetworkAndVerifySuccess() throws Exception {
        initializeAndAddNetworkAndVerifySuccess(false);
    }

    private void initializeAndAddNetworkAndVerifySuccess(boolean isHidden) throws Exception {
        loadComponentsInStaMode();
        addNetworkAndVerifySuccess(isHidden);
    }

    /**
     * Helper method to retrieve WifiConfiguration by SSID.
     *
     * Returns the associated WifiConfiguration if it is found, null otherwise.
     */
    private WifiConfiguration getWifiConfigurationForNetwork(String ssid) {
        mLooper.startAutoDispatch();
        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
        mLooper.stopAutoDispatch();

        for (WifiConfiguration checkConfig : configs) {
            if (checkConfig.SSID.equals(ssid)) {
                return checkConfig;
            }
        }
        return null;
    }

    private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) {
        ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
                ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
        ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
                ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
        verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(),
                eq(null));
        WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue();
        assertEquals("band", band, actualSettings.band);
        assertEquals("reportEvents", reportEvents, actualSettings.reportEvents);

        if (hiddenNetworkSSIDSet == null) {
            hiddenNetworkSSIDSet = new HashSet<>();
        }
        Set<String> actualHiddenNetworkSSIDSet = new HashSet<>();
        if (actualSettings.hiddenNetworks != null) {
            for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) {
                actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid);
            }
        }
        assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet);

        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);

        mLooper.dispatchAll();

        List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
        assertEquals(8, reportedResults.size());
    }

    @Test
    public void scan() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mWsm.startScan(-1, 0, null, null);
        mLooper.dispatchAll();

        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null);
    }

    @Test
    public void scanWithHiddenNetwork() throws Exception {
        initializeAndAddNetworkAndVerifySuccess(true);

        Set<String> hiddenNetworkSet = new HashSet<>();
        hiddenNetworkSet.add(sSSID);
        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>();
        hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID));
        when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList);

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mWsm.startScan(-1, 0, null, null);
        mLooper.dispatchAll();

        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
                hiddenNetworkSet);
    }

    @Test
    public void connect() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();
        when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(true);
        when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(true);

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        verify(mWifiNative).removeAllNetworks();

        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
        verify(mWifiConnectivityManager).setUserConnectChoice(eq(0));

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();

        assertEquals("ObtainingIpState", getCurrentState().getName());

        DhcpResults dhcpResults = new DhcpResults();
        dhcpResults.setGateway("1.2.3.4");
        dhcpResults.setIpAddress("192.168.1.100", 0);
        dhcpResults.addDns("8.8.8.8");
        dhcpResults.setLeaseDuration(3600);

        injectDhcpSuccess(dhcpResults);
        mLooper.dispatchAll();

        assertEquals("ConnectedState", getCurrentState().getName());
    }

    @Test
    public void connectWithNoEnablePermission() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();
        when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(false);
        when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(false);

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        verify(mWifiNative).removeAllNetworks();

        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
        verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0));

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();

        assertEquals("ObtainingIpState", getCurrentState().getName());

        DhcpResults dhcpResults = new DhcpResults();
        dhcpResults.setGateway("1.2.3.4");
        dhcpResults.setIpAddress("192.168.1.100", 0);
        dhcpResults.addDns("8.8.8.8");
        dhcpResults.setLeaseDuration(3600);

        injectDhcpSuccess(dhcpResults);
        mLooper.dispatchAll();

        assertEquals("ConnectedState", getCurrentState().getName());
    }

    @Test
    public void enableWithInvalidNetworkId() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();
        when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null);

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        verify(mWifiNative).removeAllNetworks();

        mLooper.startAutoDispatch();
        assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt());
        verify(mWifiConfigManager, never()).checkAndUpdateLastConnectUid(eq(0), anyInt());
    }

    /**
     * If caller tries to connect to a network that is already connected, the connection request
     * should succeed.
     *
     * Test: Create and connect to a network, then try to reconnect to the same network. Verify
     * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
     */
    @Test
    public void reconnectToConnectedNetwork() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        verify(mWifiNative).removeAllNetworks();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();

        assertEquals("ObtainingIpState", getCurrentState().getName());

        // try to reconnect
        mLooper.startAutoDispatch();
        Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0);
        mLooper.stopAutoDispatch();

        assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what);
    }

    @Test
    public void testDhcpFailure() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();

        assertEquals("ObtainingIpState", getCurrentState().getName());

        injectDhcpFailure();
        mLooper.dispatchAll();

        assertEquals("DisconnectingState", getCurrentState().getName());
    }

    /**
     * Verify that the network selection status will be updated with DISABLED_AUTHENTICATION_FAILURE
     * when wrong password authentication failure is detected and the network had been
     * connected previously.
     */
    @Test
    public void testWrongPasswordWithPreviouslyConnected() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        WifiConfiguration config = new WifiConfiguration();
        config.getNetworkSelectionStatus().setHasEverConnected(true);
        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);

        mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0,
                WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
        mLooper.dispatchAll();

        verify(mWrongPasswordNotifier, never()).onWrongPasswordError(anyString());
        verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
                eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_AUTHENTICATION_FAILURE));

        assertEquals("DisconnectedState", getCurrentState().getName());
    }

    /**
     * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD
     * when wrong password authentication failure is detected and the network has never been
     * connected.
     */
    @Test
    public void testWrongPasswordWithNeverConnected() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        WifiConfiguration config = new WifiConfiguration();
        config.SSID = sSSID;
        config.getNetworkSelectionStatus().setHasEverConnected(false);
        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(config);

        mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0,
                WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
        mLooper.dispatchAll();

        verify(mWrongPasswordNotifier).onWrongPasswordError(eq(sSSID));
        verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
                eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));

        assertEquals("DisconnectedState", getCurrentState().getName());
    }

    /**
     * Verify that the network selection status will be updated with DISABLED_BY_WRONG_PASSWORD
     * when wrong password authentication failure is detected and the network is unknown.
     */
    @Test
    public void testWrongPasswordWithNullNetwork() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        when(mWifiConfigManager.getConfiguredNetwork(anyInt())).thenReturn(null);

        mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0,
                WifiManager.ERROR_AUTH_FAILURE_WRONG_PSWD);
        mLooper.dispatchAll();

        verify(mWifiConfigManager).updateNetworkSelectionStatus(anyInt(),
                eq(WifiConfiguration.NetworkSelectionStatus.DISABLED_BY_WRONG_PASSWORD));

        assertEquals("DisconnectedState", getCurrentState().getName());
    }

    @Test
    public void testBadNetworkEvent() throws Exception {
        initializeAndAddNetworkAndVerifySuccess();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        mLooper.startAutoDispatch();
        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
        mLooper.stopAutoDispatch();

        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());

        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();

        assertEquals("DisconnectedState", getCurrentState().getName());
    }


    @Test
    public void smToString() throws Exception {
        assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString(
                AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
        assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString(
                DhcpClient.CMD_PRE_DHCP_ACTION));
        assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString(
                WifiStateMachine.CMD_IP_REACHABILITY_LOST));
    }

    @Test
    public void disconnect() throws Exception {
        connect();

        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
        mLooper.dispatchAll();
        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
        mLooper.dispatchAll();

        assertEquals("DisconnectedState", getCurrentState().getName());
    }

    /**
     * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
     * to true.
     *
     * Test: Successfully create and connect to a network. Check the config and verify
     * WifiConfiguration.getHasEverConnected() is true.
     */
    @Test
    public void setHasEverConnectedTrueOnConnect() throws Exception {
        connect();
        verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0);
    }

    /**
     * Fail network connection attempt and verify HasEverConnected remains false.
     *
     * Test: Successfully create a network but fail when connecting. Check the config and verify
     * WifiConfiguration.getHasEverConnected() is false.
     */
    @Test
    public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
        testDhcpFailure();
        verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0);
    }

    @Test
    public void iconQueryTest() throws Exception {
        // TODO(b/31065385): Passpoint config management.
    }

    @Test
    public void verboseLogRecSizeIsGreaterThanNormalSize() {
        assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL);
    }

    /**
     * Verifies that, by default, we allow only the "normal" number of log records.
     */
    @Test
    public void normalLogRecSizeIsUsedByDefault() {
        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
    }

    /**
     * Verifies that, in verbose mode, we allow a larger number of log records.
     */
    @Test
    public void enablingVerboseLoggingUpdatesLogRecSize() {
        mWsm.enableVerboseLogging(1);
        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize());
    }

    @Test
    public void disablingVerboseLoggingClearsRecords() {
        mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT);
        mLooper.dispatchAll();
        assertTrue(mWsm.getLogRecSize() >= 1);

        mWsm.enableVerboseLogging(0);
        assertEquals(0, mWsm.getLogRecSize());
    }

    @Test
    public void disablingVerboseLoggingUpdatesLogRecSize() {
        mWsm.enableVerboseLogging(1);
        mWsm.enableVerboseLogging(0);
        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
    }

    @Test
    public void logRecsIncludeDisconnectCommand() {
        // There's nothing special about the DISCONNECT command. It's just representative of
        // "normal" commands.
        mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT);
        mLooper.dispatchAll();
        assertEquals(1, mWsm.copyLogRecs()
                .stream()
                .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_DISCONNECT)
                .count());
    }

    @Test
    public void logRecsExcludeRssiPollCommandByDefault() {
        mWsm.sendMessage(WifiStateMachine.CMD_RSSI_POLL);
        mLooper.dispatchAll();
        assertEquals(0, mWsm.copyLogRecs()
                .stream()
                .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_RSSI_POLL)
                .count());
    }

    @Test
    public void logRecsIncludeRssiPollCommandWhenVerboseLoggingIsEnabled() {
        mWsm.enableVerboseLogging(1);
        mWsm.sendMessage(WifiStateMachine.CMD_RSSI_POLL);
        mLooper.dispatchAll();
        assertEquals(1, mWsm.copyLogRecs()
                .stream()
                .filter(logRec -> logRec.getWhat() == WifiStateMachine.CMD_RSSI_POLL)
                .count());
    }

    /** Verifies that enabling verbose logging sets the hal log property in eng builds. */
    @Test
    public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() {
        reset(mPropertyService);  // Ignore calls made in setUp()
        when(mBuildProperties.isEngBuild()).thenReturn(true);
        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mWsm.enableVerboseLogging(1);
        verify(mPropertyService).set("log.tag.WifiHAL", "V");
    }

    /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */
    @Test
    public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() {
        reset(mPropertyService);  // Ignore calls made in setUp()
        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
        when(mBuildProperties.isEngBuild()).thenReturn(false);
        when(mBuildProperties.isUserBuild()).thenReturn(false);
        mWsm.enableVerboseLogging(1);
        verify(mPropertyService).set("log.tag.WifiHAL", "V");
    }

    /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */
    @Test
    public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() {
        reset(mPropertyService);  // Ignore calls made in setUp()
        when(mBuildProperties.isUserBuild()).thenReturn(true);
        when(mBuildProperties.isEngBuild()).thenReturn(false);
        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
        mWsm.enableVerboseLogging(1);
        verify(mPropertyService, never()).set(anyString(), anyString());
    }

    private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) {
        AsyncChannel channel = mock(AsyncChannel.class);
        Message reply = Message.obtain();
        reply.arg1 = supportedFeatures;
        reset(mPropertyService);  // Ignore calls made in setUp()
        when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES))
                .thenReturn(reply);
        when(mPropertyService.getBoolean("config.disable_rtt", false))
                .thenReturn(rttConfigured);
        return mWsm.syncGetSupportedFeatures(channel);
    }

    /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
    @Test
    public void syncGetSupportedFeatures() {
        final int featureAware = WifiManager.WIFI_FEATURE_AWARE;
        final int featureInfra = WifiManager.WIFI_FEATURE_INFRA;
        final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
        final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;

        assertEquals(0, testGetSupportedFeaturesCase(0, false));
        assertEquals(0, testGetSupportedFeaturesCase(0, true));
        assertEquals(featureAware | featureInfra,
                testGetSupportedFeaturesCase(featureAware | featureInfra, false));
        assertEquals(featureAware | featureInfra,
                testGetSupportedFeaturesCase(featureAware | featureInfra, true));
        assertEquals(featureInfra | featureD2dRtt,
                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false));
        assertEquals(featureInfra,
                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true));
        assertEquals(featureInfra | featureD2apRtt,
                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false));
        assertEquals(featureInfra,
                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true));
        assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false));
        assertEquals(featureInfra,
                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true));
    }

    /**
     * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager}
     * and returning the result that's returned from {@link PasspointManager}.
     */
    @Test
    public void syncAddOrUpdatePasspointConfig() throws Exception {
        PasspointConfiguration config = new PasspointConfiguration();
        HomeSp homeSp = new HomeSp();
        homeSp.setFqdn("test.com");
        config.setHomeSp(homeSp);

        when(mPasspointManager.addOrUpdateProvider(config, MANAGED_PROFILE_UID)).thenReturn(true);
        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncAddOrUpdatePasspointConfig(
                mWsmAsyncChannel, config, MANAGED_PROFILE_UID));
        mLooper.stopAutoDispatch();
        reset(mPasspointManager);

        when(mPasspointManager.addOrUpdateProvider(config, MANAGED_PROFILE_UID)).thenReturn(false);
        mLooper.startAutoDispatch();
        assertFalse(mWsm.syncAddOrUpdatePasspointConfig(
                mWsmAsyncChannel, config, MANAGED_PROFILE_UID));
        mLooper.stopAutoDispatch();
    }

    /**
     * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager}
     * and returning the result that's returned from {@link PasspointManager} when in client mode.
     */
    @Test
    public void syncAddOrUpdatePasspointConfigInClientMode() throws Exception {
        loadComponentsInStaMode();
        syncAddOrUpdatePasspointConfig();
    }

    /**
     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
     * and returning the result that's returned from {@link PasspointManager}.
     */
    @Test
    public void syncRemovePasspointConfig() throws Exception {
        String fqdn = "test.com";
        when(mPasspointManager.removeProvider(fqdn)).thenReturn(true);
        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
        mLooper.stopAutoDispatch();
        reset(mPasspointManager);

        when(mPasspointManager.removeProvider(fqdn)).thenReturn(false);
        mLooper.startAutoDispatch();
        assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
        mLooper.stopAutoDispatch();
    }

    /**
     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
     * and returning the result that's returned from {@link PasspointManager} when in client mode.
     */
    @Test
    public void syncRemovePasspointConfigInClientMode() throws Exception {
        loadComponentsInStaMode();
        syncRemovePasspointConfig();
    }

    /**
     * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager}
     * and returning the result that's returned from {@link PasspointManager}.
     */
    @Test
    public void syncGetPasspointConfigs() throws Exception {
        // Setup expected configs.
        List<PasspointConfiguration> expectedConfigs = new ArrayList<>();
        PasspointConfiguration config = new PasspointConfiguration();
        HomeSp homeSp = new HomeSp();
        homeSp.setFqdn("test.com");
        config.setHomeSp(homeSp);
        expectedConfigs.add(config);

        when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs);
        mLooper.startAutoDispatch();
        assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel));
        mLooper.stopAutoDispatch();
        reset(mPasspointManager);

        when(mPasspointManager.getProviderConfigs())
                .thenReturn(new ArrayList<PasspointConfiguration>());
        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty());
        mLooper.stopAutoDispatch();
    }

    /**
     * Verify that syncGetMatchingWifiConfig will redirect calls to {@link PasspointManager}
     * with expected {@link WifiConfiguration} being returned when in client mode.
     *
     * @throws Exception
     */
    @Test
    public void syncGetMatchingWifiConfigInClientMode() throws Exception {
        loadComponentsInStaMode();

        when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))).thenReturn(null);
        mLooper.startAutoDispatch();
        assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel));
        mLooper.stopAutoDispatch();
        reset(mPasspointManager);

        WifiConfiguration expectedConfig = new WifiConfiguration();
        expectedConfig.SSID = "TestSSID";
        when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class)))
                .thenReturn(expectedConfig);
        mLooper.startAutoDispatch();
        WifiConfiguration actualConfig = mWsm.syncGetMatchingWifiConfig(new ScanResult(),
                mWsmAsyncChannel);
        mLooper.stopAutoDispatch();
        assertEquals(expectedConfig.SSID, actualConfig.SSID);
    }

    /**
     * Verify that syncGetMatchingWifiConfig will be a no-op and return {@code null} when not in
     * client mode.
     *
     * @throws Exception
     */
    @Test
    public void syncGetMatchingWifiConfigInNonClientMode() throws Exception {
        mLooper.startAutoDispatch();
        assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel));
        mLooper.stopAutoDispatch();
        verify(mPasspointManager, never()).getMatchingWifiConfig(any(ScanResult.class));
    }

    /**
     * Verify successful Wps PBC network connection.
     */
    @Test
    public void wpsPbcConnectSuccess() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(true);
        WpsInfo wpsInfo = new WpsInfo();
        wpsInfo.setup = WpsInfo.PBC;
        wpsInfo.BSSID = sBSSID;

        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
        mLooper.dispatchAll();
        verify(mWifiNative).startWpsPbc(eq(sBSSID));

        assertEquals("WpsRunningState", getCurrentState().getName());

        setupMocksForWpsNetworkMigration();

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
        mLooper.dispatchAll();

        assertEquals("DisconnectedState", getCurrentState().getName());
        verifyMocksForWpsNetworkMigration();
    }

    /**
     * Verify failure in starting Wps PBC network connection.
     */
    @Test
    public void wpsPbcConnectFailure() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(false);
        WpsInfo wpsInfo = new WpsInfo();
        wpsInfo.setup = WpsInfo.PBC;
        wpsInfo.BSSID = sBSSID;

        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
        mLooper.dispatchAll();
        verify(mWifiNative).startWpsPbc(eq(sBSSID));

        assertFalse("WpsRunningState".equals(getCurrentState().getName()));
    }

    /**
     * Verify successful Wps Pin Display network connection.
     */
    @Test
    public void wpsPinDisplayConnectSuccess() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn("34545434");
        WpsInfo wpsInfo = new WpsInfo();
        wpsInfo.setup = WpsInfo.DISPLAY;
        wpsInfo.BSSID = sBSSID;

        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
        mLooper.dispatchAll();
        verify(mWifiNative).startWpsPinDisplay(eq(sBSSID));

        assertEquals("WpsRunningState", getCurrentState().getName());

        setupMocksForWpsNetworkMigration();

        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
        mLooper.dispatchAll();

        assertEquals("DisconnectedState", getCurrentState().getName());
        verifyMocksForWpsNetworkMigration();
    }

    /**
     * Verify failure in Wps Pin Display network connection.
     */
    @Test
    public void wpsPinDisplayConnectFailure() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn(null);
        WpsInfo wpsInfo = new WpsInfo();
        wpsInfo.setup = WpsInfo.DISPLAY;
        wpsInfo.BSSID = sBSSID;

        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
        mLooper.dispatchAll();
        verify(mWifiNative).startWpsPinDisplay(eq(sBSSID));

        assertFalse("WpsRunningState".equals(getCurrentState().getName()));
    }

    @Test
    public void handleVendorHalDeath() throws Exception {
        ArgumentCaptor<WifiNative.VendorHalDeathEventHandler> deathHandlerCapturer =
                ArgumentCaptor.forClass(WifiNative.VendorHalDeathEventHandler.class);
        when(mWifiNative.initializeVendorHal(deathHandlerCapturer.capture())).thenReturn(true);

        // Trigger initialize to capture the death handler registration.
        mLooper.startAutoDispatch();
        assertTrue(mWsm.syncInitialize(mWsmAsyncChannel));
        mLooper.stopAutoDispatch();

        verify(mWifiNative).initializeVendorHal(any(WifiNative.VendorHalDeathEventHandler.class));
        WifiNative.VendorHalDeathEventHandler deathHandler = deathHandlerCapturer.getValue();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        // Now trigger the death notification.
        deathHandler.onDeath();
        mLooper.dispatchAll();

        verify(mWifiMetrics).incrementNumHalCrashes();
        verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_HAL_CRASH));
    }

    @Test
    public void handleWificondDeath() throws Exception {
        ArgumentCaptor<StateMachineDeathRecipient> deathHandlerCapturer =
                ArgumentCaptor.forClass(StateMachineDeathRecipient.class);

        // Trigger initialize to capture the death handler registration.
        loadComponentsInStaMode();

        verify(mClientInterfaceBinder).linkToDeath(deathHandlerCapturer.capture(), anyInt());
        StateMachineDeathRecipient deathHandler = deathHandlerCapturer.getValue();

        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();

        // Now trigger the death notification.
        deathHandler.binderDied();
        mLooper.dispatchAll();

        verify(mWifiMetrics).incrementNumWificondCrashes();
        verify(mSelfRecovery).trigger(eq(SelfRecovery.REASON_WIFICOND_CRASH));
    }

    private void setupMocksForWpsNetworkMigration() {
        // Now trigger the network connection event for adding the WPS network.
        doAnswer(new AnswerWithArguments() {
            public boolean answer(Map<String, WifiConfiguration> configs,
                                  SparseArray<Map<String, String>> networkExtras) throws Exception {
                WifiConfiguration config = new WifiConfiguration();
                config.networkId = WPS_SUPPLICANT_NETWORK_ID;
                config.SSID = DEFAULT_TEST_SSID;
                configs.put("dummy", config);
                return true;
            }
        }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class));
        when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
                .thenReturn(new NetworkUpdateResult(WPS_FRAMEWORK_NETWORK_ID));
        when(mWifiConfigManager.enableNetwork(eq(WPS_FRAMEWORK_NETWORK_ID), anyBoolean(), anyInt()))
                .thenReturn(true);
    }

    private void verifyMocksForWpsNetworkMigration() {
        // Network Ids should be reset so that it is treated as addition.
        ArgumentCaptor<WifiConfiguration> wifiConfigCaptor =
                ArgumentCaptor.forClass(WifiConfiguration.class);
        verify(mWifiConfigManager).addOrUpdateNetwork(wifiConfigCaptor.capture(), anyInt());
        assertEquals(WifiConfiguration.INVALID_NETWORK_ID, wifiConfigCaptor.getValue().networkId);
        assertEquals(DEFAULT_TEST_SSID, wifiConfigCaptor.getValue().SSID);
        verify(mWifiConfigManager).enableNetwork(eq(WPS_FRAMEWORK_NETWORK_ID), anyBoolean(),
                anyInt());
    }

    /**
     * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not
     * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState.
     * This protects WifiStateMachine from  getting into a bad state where WifiInfo says wifi is
     * already Connected or Connecting, (when it is in-fact Disconnected), so
     * WifiConnectivityManager does not attempt any new Connections, freezing wifi.
     */
    @Test
    public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception {
        InOrder inOrder = inOrder(mWifiConnectivityManager);
        Log.i(TAG, mWsm.getCurrentState().getName());
        String initialBSSID = "aa:bb:cc:dd:ee:ff";
        WifiInfo wifiInfo = mWsm.getWifiInfo();
        wifiInfo.setBSSID(initialBSSID);

        // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        startSupplicantAndDispatchMessages();
        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
        assertNull(wifiInfo.getBSSID());

        // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated
        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();
        assertEquals(sBSSID, wifiInfo.getBSSID());
        assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());

        // Set WSM to SCAN_ONLY_MODE, verify state and wifi disabled in ConnectivityManager, and
        // WifiInfo is reset() and state set to DISCONNECTED
        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
        assertEquals("ScanModeState", getCurrentState().getName());
        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false));
        assertNull(wifiInfo.getBSSID());
        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());

        // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated
        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
        mLooper.dispatchAll();
        assertNull(wifiInfo.getBSSID());
        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());

        // Set the bssid to something, so we can verify it is cleared (just in case)
        wifiInfo.setBSSID(initialBSSID);

        // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager,
        // and WifiInfo has been reset
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
        assertNull(wifiInfo.getBSSID());
    }

    /**
     * Test that the process uid has full wifiInfo access
     */
    @Test
    public void testConnectedIdsAreVisibleFromOwnUid() throws Exception {
        assertEquals(Process.myUid(), Binder.getCallingUid());
        WifiInfo wifiInfo = mWsm.getWifiInfo();
        connect();
        WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo();
        assertEquals(wifiInfo, connectionInfo);
    }

    /**
     * Test that connected SSID and BSSID are not exposed to an app that does not have the
     * appropriate permissions.
     */
    @Test
    public void testConnectedIdsAreHiddenFromRandomApp() throws Exception {
        int actualUid = Binder.getCallingUid();
        int fakeUid = Process.myUid() + 100000;
        assertNotEquals(actualUid, fakeUid);
        BinderUtil.setUid(fakeUid);
        try {
            WifiInfo wifiInfo = mWsm.getWifiInfo();

            // Get into a connected state, with known BSSID and SSID
            connect();
            assertEquals(sBSSID, wifiInfo.getBSSID());
            assertEquals(sWifiSsid, wifiInfo.getWifiSsid());

            when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt()))
                    .thenReturn(false);

            WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo();

            assertNotEquals(wifiInfo, connectionInfo);
            assertEquals(WifiSsid.NONE, connectionInfo.getSSID());
            assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID());
        } finally {
            BinderUtil.setUid(actualUid);
        }
    }

    /**
     * Test that connected SSID and BSSID are not exposed to an app that does not have the
     * appropriate permissions, when canAccessScanResults raises a SecurityException.
     */
    @Test
    public void testConnectedIdsAreHiddenOnSecurityException() throws Exception {
        int actualUid = Binder.getCallingUid();
        int fakeUid = Process.myUid() + 100000;
        assertNotEquals(actualUid, fakeUid);
        BinderUtil.setUid(fakeUid);
        try {
            WifiInfo wifiInfo = mWsm.getWifiInfo();

            // Get into a connected state, with known BSSID and SSID
            connect();
            assertEquals(sBSSID, wifiInfo.getBSSID());
            assertEquals(sWifiSsid, wifiInfo.getWifiSsid());

            when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt()))
                    .thenThrow(new SecurityException());

            WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo();

            assertNotEquals(wifiInfo, connectionInfo);
            assertEquals(WifiSsid.NONE, connectionInfo.getSSID());
            assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getBSSID());
        } finally {
            BinderUtil.setUid(actualUid);
        }
    }

    /**
     * Test that connected SSID and BSSID are exposed to an app that does have the
     * appropriate permissions.
     */
    @Test
    public void testConnectedIdsAreVisibleFromPermittedApp() throws Exception {
        int actualUid = Binder.getCallingUid();
        int fakeUid = Process.myUid() + 100000;
        BinderUtil.setUid(fakeUid);
        try {
            WifiInfo wifiInfo = mWsm.getWifiInfo();

            // Get into a connected state, with known BSSID and SSID
            connect();
            assertEquals(sBSSID, wifiInfo.getBSSID());
            assertEquals(sWifiSsid, wifiInfo.getWifiSsid());

            when(mWifiPermissionsUtil.canAccessScanResults(anyString(), eq(fakeUid), anyInt()))
                    .thenReturn(true);

            WifiInfo connectionInfo = mWsm.syncRequestConnectionInfo();

            assertNotEquals(wifiInfo, connectionInfo);
            assertEquals(wifiInfo.getSSID(), connectionInfo.getSSID());
            assertEquals(wifiInfo.getBSSID(), connectionInfo.getBSSID());
            // Access to our MAC address uses a different permission, make sure it is not granted
            assertEquals(WifiInfo.DEFAULT_MAC_ADDRESS, connectionInfo.getMacAddress());
        } finally {
            BinderUtil.setUid(actualUid);
        }
    }

    /**
     * Adds the network without putting WifiStateMachine into ConnectMode.
     */
    @Test
    public void addNetworkInInitialState() throws Exception {
        // We should not be in initial state now.
        assertTrue("InitialState".equals(getCurrentState().getName()));
        addNetworkAndVerifySuccess(false);
        verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0));
    }

    /**
     * Test START_WPS with a null wpsInfo object fails gracefully (No NPE)
     */
    @Test
    public void testStartWps_nullWpsInfo() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        mLooper.startAutoDispatch();
        Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.START_WPS, 0, 0,
                null);
        mLooper.stopAutoDispatch();
        assertEquals(WifiManager.WPS_FAILED, reply.what);
    }

    /**
     * Test that DISABLE_NETWORK returns failure to public API when WifiConfigManager returns
     * failure.
     */
    @Test
    public void testSyncDisableNetwork_failure() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        when(mWifiConfigManager.disableNetwork(anyInt(), anyInt())).thenReturn(false);

        mLooper.startAutoDispatch();
        boolean succeeded = mWsm.syncDisableNetwork(mWsmAsyncChannel, 0);
        mLooper.stopAutoDispatch();
        assertFalse(succeeded);
    }

    /**
     * Test that failure to start HAL in AP mode increments the corresponding metrics.
     */
    @Test
    public void testSetupForSoftApModeHalFailureIncrementsMetrics() throws Exception {
        when(mWifiNative.setupForSoftApMode())
                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null));

        SoftApModeConfiguration config = new SoftApModeConfiguration(
                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
        mWsm.setHostApRunning(config, true);
        mLooper.dispatchAll();

        verify(mWifiNative).setupForSoftApMode();
        verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal();
    }

    /**
     * Test that failure to start HAL in AP mode increments the corresponding metrics.
     */
    @Test
    public void testSetupForSoftApModeWificondFailureIncrementsMetrics() throws Exception {
        when(mWifiNative.setupForSoftApMode())
                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null));

        SoftApModeConfiguration config = new SoftApModeConfiguration(
                WifiManager.IFACE_IP_MODE_TETHERED, new WifiConfiguration());
        mWsm.setHostApRunning(config, true);
        mLooper.dispatchAll();

        verify(mWifiNative).setupForSoftApMode();
        verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond();
    }

    /**
     * Test that failure to start HAL in client mode increments the corresponding metrics.
     */
    @Test
    public void testSetupForClientModeHalFailureIncrementsMetrics() throws Exception {
        when(mWifiNative.setupForClientMode())
                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_HAL, null));

        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
        mLooper.dispatchAll();

        verify(mWifiNative).setupForClientMode();
        verify(mWifiMetrics).incrementNumWifiOnFailureDueToHal();
    }

    /**
     * Test that failure to start HAL in client mode increments the corresponding metrics.
     */
    @Test
    public void testSetupForClientModeWificondFailureIncrementsMetrics() throws Exception {
        when(mWifiNative.setupForClientMode())
                .thenReturn(Pair.create(WifiNative.SETUP_FAILURE_WIFICOND, null));

        mWsm.setSupplicantRunning(true);
        mLooper.dispatchAll();

        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
        mLooper.dispatchAll();

        verify(mWifiNative).setupForClientMode();
        verify(mWifiMetrics).incrementNumWifiOnFailureDueToWificond();
    }

    /**
     * Test that we don't register the telephony call state listener on devices which do not support
     * setting/resetting Tx power limit.
     */
    @Test
    public void testVoiceCallSar_disabledTxPowerLimit_WifiOn() throws Exception {
        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertNull(mPhoneStateListener);
    }

    /**
     * Test that we do register the telephony call state listener on devices which do support
     * setting/resetting Tx power limit.
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimit_WifiOn() throws Exception {
        mResources.setBoolean(
                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true);
        initializeWsm();

        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertNotNull(mPhoneStateListener);
    }

    /**
     * Test that we do register the telephony call state listener on devices which do support
     * setting/resetting Tx power limit and set the tx power level if we're in state
     * {@link TelephonyManager#CALL_STATE_OFFHOOK}.
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimitCallStateOffHook_WhenWifiTurnedOn()
            throws Exception {
        int powerLevelInDbm = -45;
        mResources.setInteger(
                R.integer.config_wifi_framework_voice_call_sar_tx_power_limit_in_dbm,
                powerLevelInDbm);
        mResources.setBoolean(
                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true);
        initializeWsm();

        when(mTelephonyManager.isOffhook()).thenReturn(true);

        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertNotNull(mPhoneStateListener);
        verify(mWifiNative).setTxPowerLimit(eq(powerLevelInDbm));
    }

    /**
     * Test that we do register the telephony call state listener on devices which do support
     * setting/resetting Tx power limit and set the tx power level if we're in state
     * {@link TelephonyManager#CALL_STATE_IDLE}.
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimitCallStateIdle_WhenWifiTurnedOn()
            throws Exception {
        mResources.setBoolean(
                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true);
        initializeWsm();

        when(mTelephonyManager.isIdle()).thenReturn(true);

        loadComponentsInStaMode();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
        assertEquals("DisconnectedState", getCurrentState().getName());
        assertNotNull(mPhoneStateListener);
        verify(mWifiNative).resetTxPowerLimit();
    }

    /**
     * Test that we invoke the corresponding WifiNative method when
     * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state
     * {@link TelephonyManager#CALL_STATE_OFFHOOK}.
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimitCallStateOffHook_WhenWifiOn() throws Exception {
        int powerLevelInDbm = -45;
        mResources.setInteger(
                R.integer.config_wifi_framework_voice_call_sar_tx_power_limit_in_dbm,
                powerLevelInDbm);
        testVoiceCallSar_enabledTxPowerLimit_WifiOn();

        mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, "");
        mLooper.dispatchAll();
        verify(mWifiNative).setTxPowerLimit(eq(powerLevelInDbm));
    }

    /**
     * Test that we invoke the corresponding WifiNative method when
     * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state
     * {@link TelephonyManager#CALL_STATE_IDLE}.
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimitCallStateIdle_WhenWifiOn() throws Exception {
        testVoiceCallSar_enabledTxPowerLimit_WifiOn();

        mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, "");
        mLooper.dispatchAll();
        verify(mWifiNative).resetTxPowerLimit();
    }

    /**
     * Test that we don't invoke the corresponding WifiNative method when
     * {@link PhoneStateListener#onCallStateChanged(int, String)} is invoked with state
     * {@link TelephonyManager#CALL_STATE_IDLE} or {@link TelephonyManager#CALL_STATE_OFFHOOK} when
     * wifi is off (state machine is not in SupplicantStarted state).
     */
    @Test
    public void testVoiceCallSar_enabledTxPowerLimitCallState_WhenWifiOff() throws Exception {
        mResources.setBoolean(
                R.bool.config_wifi_framework_enable_voice_call_sar_tx_power_limit, true);
        initializeWsm();

        mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_OFFHOOK, "");
        mLooper.dispatchAll();
        verify(mWifiNative, never()).setTxPowerLimit(anyInt());

        mPhoneStateListener.onCallStateChanged(TelephonyManager.CALL_STATE_IDLE, "");
        mLooper.dispatchAll();
        verify(mWifiNative, never()).resetTxPowerLimit();
    }

    /**
     * Verifies that a network disconnection event will result in WifiStateMachine invoking
     * {@link WifiConfigManager#removeAllEphemeralOrPasspointConfiguredNetworks()} to remove
     * any ephemeral or passpoint networks from it's internal database.
     */
    @Test
    public void testDisconnectionRemovesEphemeralAndPasspointNetworks() throws Exception {
        disconnect();
        verify(mWifiConfigManager).removeAllEphemeralOrPasspointConfiguredNetworks();
    }

    /**
     * Verifies that WifiStateMachine sets and unsets appropriate 'RecentFailureReason' values
     * on a WifiConfiguration when it fails association, authentication, or successfully connects
     */
    @Test
    public void testExtraFailureReason_ApIsBusy() throws Exception {
        // Setup CONNECT_MODE & a WifiConfiguration
        initializeAndAddNetworkAndVerifySuccess();
        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
        mLooper.dispatchAll();
        // Trigger a connection to this (CMD_START_CONNECT will actually fail, but it sets up
        // targetNetworkId state)
        mWsm.sendMessage(WifiStateMachine.CMD_START_CONNECT, 0, 0, sBSSID);
        mLooper.dispatchAll();
        // Simulate an ASSOCIATION_REJECTION_EVENT, due to the AP being busy
        mWsm.sendMessage(WifiMonitor.ASSOCIATION_REJECTION_EVENT, 0,
                ISupplicantStaIfaceCallback.StatusCode.AP_UNABLE_TO_HANDLE_NEW_STA, sBSSID);
        mLooper.dispatchAll();
        verify(mWifiConfigManager).setRecentFailureAssociationStatus(eq(0),
                eq(WifiConfiguration.RecentFailure.STATUS_AP_UNABLE_TO_HANDLE_NEW_STA));
        assertEquals("DisconnectedState", getCurrentState().getName());

        // Simulate an AUTHENTICATION_FAILURE_EVENT, which should clear the ExtraFailureReason
        reset(mWifiConfigManager);
        mWsm.sendMessage(WifiMonitor.AUTHENTICATION_FAILURE_EVENT, 0, 0, null);
        mLooper.dispatchAll();
        verify(mWifiConfigManager).clearRecentFailureReason(eq(0));
        verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt());

        // Simulate a NETWORK_CONNECTION_EVENT which should clear the ExtraFailureReason
        reset(mWifiConfigManager);
        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
        mLooper.dispatchAll();
        verify(mWifiConfigManager).clearRecentFailureReason(eq(0));
        verify(mWifiConfigManager, never()).setRecentFailureAssociationStatus(anyInt(), anyInt());
    }

    /**
     * Test that the helper method
     * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
     * returns true when we connect to the last selected network before expiration of
     * {@link WifiStateMachine#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
     */
    @Test
    public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkNotExpired() {
        long lastSelectedTimestamp = 45666743454L;
        int lastSelectedNetworkId = 5;

        when(mClock.getElapsedSinceBootMillis()).thenReturn(
                lastSelectedTimestamp
                        + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
        when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp);
        when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId);

        WifiConfiguration currentConfig = new WifiConfiguration();
        currentConfig.networkId = lastSelectedNetworkId;
        assertTrue(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
    }

    /**
     * Test that the helper method
     * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
     * returns false when we connect to the last selected network after expiration of
     * {@link WifiStateMachine#LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS}.
     */
    @Test
    public void testShouldEvaluateWhetherToSendExplicitlySelected_SameNetworkExpired() {
        long lastSelectedTimestamp = 45666743454L;
        int lastSelectedNetworkId = 5;

        when(mClock.getElapsedSinceBootMillis()).thenReturn(
                lastSelectedTimestamp
                        + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS + 1);
        when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp);
        when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId);

        WifiConfiguration currentConfig = new WifiConfiguration();
        currentConfig.networkId = lastSelectedNetworkId;
        assertFalse(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
    }

    /**
     * Test that the helper method
     * {@link WifiStateMachine#shouldEvaluateWhetherToSendExplicitlySelected(WifiConfiguration)}
     * returns false when we connect to a different network to the last selected network.
     */
    @Test
    public void testShouldEvaluateWhetherToSendExplicitlySelected_DifferentNetwork() {
        long lastSelectedTimestamp = 45666743454L;
        int lastSelectedNetworkId = 5;

        when(mClock.getElapsedSinceBootMillis()).thenReturn(
                lastSelectedTimestamp
                        + WifiStateMachine.LAST_SELECTED_NETWORK_EXPIRATION_AGE_MILLIS - 1);
        when(mWifiConfigManager.getLastSelectedTimeStamp()).thenReturn(lastSelectedTimestamp);
        when(mWifiConfigManager.getLastSelectedNetwork()).thenReturn(lastSelectedNetworkId);

        WifiConfiguration currentConfig = new WifiConfiguration();
        currentConfig.networkId = lastSelectedNetworkId - 1;
        assertFalse(mWsm.shouldEvaluateWhetherToSendExplicitlySelected(currentConfig));
    }
}
