WifiStateMachineTest.java revision 6ecd7a8dcde46e3524c15c4a07075ca06ab681b5
1055b4925fb282a029e6058b2d670f4a416df205bTor Norbye/*
2055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * Copyright (C) 2015 The Android Open Source Project
3055b4925fb282a029e6058b2d670f4a416df205bTor Norbye *
4055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * Licensed under the Apache License, Version 2.0 (the "License");
5055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * you may not use this file except in compliance with the License.
6055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * You may obtain a copy of the License at
7055b4925fb282a029e6058b2d670f4a416df205bTor Norbye *
8055b4925fb282a029e6058b2d670f4a416df205bTor Norbye *      http://www.apache.org/licenses/LICENSE-2.0
9055b4925fb282a029e6058b2d670f4a416df205bTor Norbye *
10055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * Unless required by applicable law or agreed to in writing, software
11055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * distributed under the License is distributed on an "AS IS" BASIS,
12055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * See the License for the specific language governing permissions and
14055b4925fb282a029e6058b2d670f4a416df205bTor Norbye * limitations under the License.
15055b4925fb282a029e6058b2d670f4a416df205bTor Norbye */
16055b4925fb282a029e6058b2d670f4a416df205bTor Norbye
17055b4925fb282a029e6058b2d670f4a416df205bTor Norbyepackage com.android.server.wifi;
18bf4b77f1b6bfa3ccf6c4fc8c89f1a1fb563b7a65Aurimas Liutikas
19bf4b77f1b6bfa3ccf6c4fc8c89f1a1fb563b7a65Aurimas Liutikasimport static org.junit.Assert.assertEquals;
20bf4b77f1b6bfa3ccf6c4fc8c89f1a1fb563b7a65Aurimas Liutikasimport static org.junit.Assert.assertFalse;
21c8d78f1623ec828ad2e0bce452e45d207f029d08Tor Norbyeimport static org.junit.Assert.assertNull;
22055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport static org.junit.Assert.assertTrue;
23055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport static org.mockito.Mockito.*;
24055b4925fb282a029e6058b2d670f4a416df205bTor Norbye
25055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.app.ActivityManager;
26055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.app.test.MockAnswerUtil.AnswerWithArguments;
27055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.app.test.TestAlarmManager;
28055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.content.Context;
29055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.content.pm.PackageManager;
30055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.content.pm.UserInfo;
31055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.content.res.Resources;
32055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.ConnectivityManager;
33385cccb8927b54284505b0bfdadb95e157cbdfd2Neil Fullerimport android.net.DhcpResults;
34055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.LinkProperties;
35055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.dhcp.DhcpClient;
36055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.ip.IpManager;
37055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.IApInterface;
38055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.IClientInterface;
39c8d78f1623ec828ad2e0bce452e45d207f029d08Tor Norbyeimport android.net.wifi.IWificond;
40055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.ScanResult;
41055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.SupplicantState;
42055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WifiConfiguration;
43055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WifiInfo;
44055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WifiManager;
45055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WifiScanner;
46055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WifiSsid;
47055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.WpsInfo;
48055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.hotspot2.PasspointConfiguration;
49055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.hotspot2.pps.HomeSp;
50055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.net.wifi.p2p.IWifiP2pManager;
51055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.BatteryStats;
52055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.Binder;
53055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.Bundle;
54055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.Handler;
55055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.HandlerThread;
56055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.IBinder;
57055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.IInterface;
58055b4925fb282a029e6058b2d670f4a416df205bTor Norbyeimport android.os.INetworkManagementService;
59import android.os.IPowerManager;
60import android.os.Looper;
61import android.os.Message;
62import android.os.Messenger;
63import android.os.PowerManager;
64import android.os.RemoteException;
65import android.os.UserHandle;
66import android.os.UserManager;
67import android.os.test.TestLooper;
68import android.provider.Settings;
69import android.security.KeyStore;
70import android.test.mock.MockContentProvider;
71import android.test.mock.MockContentResolver;
72import android.test.suitebuilder.annotation.SmallTest;
73import android.util.Log;
74import android.util.SparseArray;
75
76import com.android.internal.R;
77import com.android.internal.app.IBatteryStats;
78import com.android.internal.util.AsyncChannel;
79import com.android.internal.util.IState;
80import com.android.internal.util.StateMachine;
81import com.android.server.wifi.hotspot2.NetworkDetail;
82import com.android.server.wifi.hotspot2.PasspointManager;
83import com.android.server.wifi.p2p.WifiP2pServiceImpl;
84
85import org.junit.After;
86import org.junit.Before;
87import org.junit.Test;
88import org.mockito.ArgumentCaptor;
89import org.mockito.InOrder;
90import org.mockito.Mock;
91import org.mockito.MockitoAnnotations;
92
93import java.io.ByteArrayOutputStream;
94import java.io.PrintWriter;
95import java.lang.reflect.Field;
96import java.lang.reflect.InvocationTargetException;
97import java.lang.reflect.Method;
98import java.util.ArrayList;
99import java.util.Arrays;
100import java.util.HashSet;
101import java.util.List;
102import java.util.Map;
103import java.util.Set;
104import java.util.concurrent.CountDownLatch;
105
106/**
107 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
108 */
109@SmallTest
110public class WifiStateMachineTest {
111    public static final String TAG = "WifiStateMachineTest";
112
113    private static final int MANAGED_PROFILE_UID = 1100000;
114    private static final int OTHER_USER_UID = 1200000;
115    private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
116            (ActivityManager.isLowRamDeviceStatic()
117                    ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
118                    : WifiStateMachine.NUM_LOG_RECS_VERBOSE);
119    private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
120
121    private long mBinderToken;
122
123    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
124        return mock(class1, withSettings().extraInterfaces(interfaces));
125    }
126
127    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
128        T tImpl = mockWithInterfaces(class1, iface);
129        IBinder binder = mock(IBinder.class);
130        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
131        when(binder.queryLocalInterface(iface.getCanonicalName()))
132                .thenReturn((IInterface) tImpl);
133        return binder;
134    }
135
136    private void enableDebugLogs() {
137        mWsm.enableVerboseLogging(1);
138    }
139
140    private class TestIpManager extends IpManager {
141        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
142            // Call dependency-injection superclass constructor.
143            super(context, ifname, callback, mock(INetworkManagementService.class));
144        }
145
146        @Override
147        public void startProvisioning(IpManager.ProvisioningConfiguration config) {}
148
149        @Override
150        public void stop() {}
151
152        @Override
153        public void confirmConfiguration() {}
154
155        void injectDhcpSuccess(DhcpResults dhcpResults) {
156            mCallback.onNewDhcpResults(dhcpResults);
157            mCallback.onProvisioningSuccess(new LinkProperties());
158        }
159
160        void injectDhcpFailure() {
161            mCallback.onNewDhcpResults(null);
162            mCallback.onProvisioningFailure(new LinkProperties());
163        }
164    }
165
166    private FrameworkFacade getFrameworkFacade() throws Exception {
167        FrameworkFacade facade = mock(FrameworkFacade.class);
168
169        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
170                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
171
172        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
173        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
174
175        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
176                IWifiP2pManager.class.getCanonicalName());
177
178        final CountDownLatch untilDone = new CountDownLatch(1);
179        mP2pThread = new HandlerThread("WifiP2pMockThread") {
180            @Override
181            protected void onLooperPrepared() {
182                untilDone.countDown();
183            }
184        };
185
186        mP2pThread.start();
187        untilDone.await();
188
189        Handler handler = new Handler(mP2pThread.getLooper());
190        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
191
192        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
193        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);
194
195        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
196                .then(new AnswerWithArguments() {
197                    public IpManager answer(
198                            Context context, String ifname, IpManager.Callback callback) {
199                        mTestIpManager = new TestIpManager(context, ifname, callback);
200                        return mTestIpManager;
201                    }
202                });
203
204        return facade;
205    }
206
207    private Context getContext() throws Exception {
208        PackageManager pkgMgr = mock(PackageManager.class);
209        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
210
211        Context context = mock(Context.class);
212        when(context.getPackageManager()).thenReturn(pkgMgr);
213
214        MockResources resources = new com.android.server.wifi.MockResources();
215        when(context.getResources()).thenReturn(resources);
216
217        MockContentResolver mockContentResolver = new MockContentResolver();
218        mockContentResolver.addProvider(Settings.AUTHORITY,
219                new MockContentProvider(context) {
220                    @Override
221                    public Bundle call(String method, String arg, Bundle extras) {
222                        return new Bundle();
223                    }
224                });
225        when(context.getContentResolver()).thenReturn(mockContentResolver);
226
227        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
228                new PowerManager(context, mock(IPowerManager.class), new Handler()));
229
230        mAlarmManager = new TestAlarmManager();
231        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
232                mAlarmManager.getAlarmManager());
233
234        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
235                mock(ConnectivityManager.class));
236
237        return context;
238    }
239
240    private Resources getMockResources() {
241        MockResources resources = new MockResources();
242        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
243        return resources;
244    }
245
246    private IState getCurrentState() throws
247            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
248        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
249        method.setAccessible(true);
250        return (IState) method.invoke(mWsm);
251    }
252
253    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
254            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
255        Field field = StateMachine.class.getDeclaredField("mSmThread");
256        field.setAccessible(true);
257        return (HandlerThread) field.get(wsm);
258    }
259
260    private static void stopLooper(final Looper looper) throws Exception {
261        new Handler(looper).post(new Runnable() {
262            @Override
263            public void run() {
264                looper.quitSafely();
265            }
266        });
267    }
268
269    private void dumpState() {
270        ByteArrayOutputStream stream = new ByteArrayOutputStream();
271        PrintWriter writer = new PrintWriter(stream);
272        mWsm.dump(null, writer, null);
273        writer.flush();
274        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
275    }
276
277    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
278        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
279        ie[0] = ScanResults.generateSsidIe(sSSID);
280        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
281        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
282                Long.MAX_VALUE, /* needed so that scan results aren't rejected because
283                                   there older than scan start */
284                ie, new ArrayList<String>());
285        return detail;
286    }
287
288    private ArrayList<ScanDetail> getMockScanResults() {
289        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
290        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
291
292        int rssi = -65;
293        list.add(getGoogleGuestScanDetail(rssi));
294        return list;
295    }
296
297    static final String   sSSID = "\"GoogleGuest\"";
298    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
299    static final String   sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
300    static final String   sBSSID = "01:02:03:04:05:06";
301    static final int      sFreq = 2437;
302
303    WifiStateMachine mWsm;
304    HandlerThread mWsmThread;
305    HandlerThread mP2pThread;
306    HandlerThread mSyncThread;
307    AsyncChannel  mWsmAsyncChannel;
308    TestAlarmManager mAlarmManager;
309    MockWifiMonitor mWifiMonitor;
310    TestIpManager mTestIpManager;
311    TestLooper mLooper;
312
313    @Mock WifiScanner mWifiScanner;
314    @Mock SupplicantStateTracker mSupplicantStateTracker;
315    @Mock WifiMetrics mWifiMetrics;
316    @Mock UserManager mUserManager;
317    @Mock WifiApConfigStore mApConfigStore;
318    @Mock BackupManagerProxy mBackupManagerProxy;
319    @Mock WifiCountryCode mCountryCode;
320    @Mock WifiInjector mWifiInjector;
321    @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
322    @Mock PropertyService mPropertyService;
323    @Mock BuildProperties mBuildProperties;
324    @Mock IWificond mWificond;
325    @Mock IApInterface mApInterface;
326    @Mock IClientInterface mClientInterface;
327    @Mock IBinder mApInterfaceBinder;
328    @Mock IBinder mClientInterfaceBinder;
329    @Mock WifiConfigManager mWifiConfigManager;
330    @Mock WifiNative mWifiNative;
331    @Mock WifiConnectivityManager mWifiConnectivityManager;
332    @Mock SoftApManager mSoftApManager;
333    @Mock WifiStateTracker mWifiStateTracker;
334    @Mock PasspointManager mPasspointManager;
335
336    public WifiStateMachineTest() throws Exception {
337    }
338
339    @Before
340    public void setUp() throws Exception {
341        Log.d(TAG, "Setting up ...");
342
343        // Ensure looper exists
344        mLooper = new TestLooper();
345
346        MockitoAnnotations.initMocks(this);
347
348        /** uncomment this to enable logs from WifiStateMachines */
349        // enableDebugLogs();
350
351        mWifiMonitor = new MockWifiMonitor();
352        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
353        when(mWifiInjector.getClock()).thenReturn(new Clock());
354        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
355        when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
356        when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
357        when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
358        when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class));
359        when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn(
360                mock(BaseWifiDiagnostics.class));
361        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
362        when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
363        when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
364        when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean()))
365                .thenReturn(mWifiConnectivityManager);
366        when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
367                any(SoftApManager.Listener.class), any(IApInterface.class),
368                any(WifiConfiguration.class)))
369                .thenReturn(mSoftApManager);
370        when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
371        when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker);
372        when(mWifiInjector.getWifiMonitor()).thenReturn(mWifiMonitor);
373        when(mWifiInjector.getWifiNative()).thenReturn(mWifiNative);
374
375        when(mWifiNative.setupForClientMode()).thenReturn(mClientInterface);
376        when(mWifiNative.setupForSoftApMode()).thenReturn(mApInterface);
377        when(mWifiNative.getInterfaceName()).thenReturn("mockWlan");
378        when(mWifiNative.enableSupplicant()).thenReturn(true);
379        when(mWifiNative.disableSupplicant()).thenReturn(true);
380        when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0);
381
382
383        FrameworkFacade factory = getFrameworkFacade();
384        Context context = getContext();
385
386        Resources resources = getMockResources();
387        when(context.getResources()).thenReturn(resources);
388
389        when(factory.getIntegerSetting(context,
390                Settings.Global.WIFI_FREQUENCY_BAND,
391                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
392                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
393
394        when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy)))
395                .thenReturn(mApConfigStore);
396
397        when(factory.makeSupplicantStateTracker(
398                any(Context.class), any(WifiConfigManager.class),
399                any(Handler.class))).thenReturn(mSupplicantStateTracker);
400
401        when(mUserManager.getProfileParent(11))
402                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
403        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
404                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
405                new UserInfo(11, "managed profile", 0)));
406
407        when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
408        when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder);
409
410        mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(),
411            mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative);
412        mWsmThread = getWsmHandlerThread(mWsm);
413
414        final AsyncChannel channel = new AsyncChannel();
415        Handler handler = new Handler(mLooper.getLooper()) {
416            @Override
417            public void handleMessage(Message msg) {
418                switch (msg.what) {
419                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
420                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
421                            mWsmAsyncChannel = channel;
422                        } else {
423                            Log.d(TAG, "Failed to connect Command channel " + this);
424                        }
425                        break;
426                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
427                        Log.d(TAG, "Command channel disconnected" + this);
428                        break;
429                }
430            }
431        };
432
433        channel.connect(context, handler, mWsm.getMessenger());
434        mLooper.dispatchAll();
435        /* Now channel is supposed to be connected */
436
437        mBinderToken = Binder.clearCallingIdentity();
438    }
439
440    @After
441    public void cleanUp() throws Exception {
442        Binder.restoreCallingIdentity(mBinderToken);
443
444        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
445        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
446        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
447
448        mWsmThread = null;
449        mP2pThread = null;
450        mSyncThread = null;
451        mWsmAsyncChannel = null;
452        mWsm = null;
453    }
454
455    @Test
456    public void createNew() throws Exception {
457        assertEquals("InitialState", getCurrentState().getName());
458
459        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
460        mLooper.dispatchAll();
461        assertEquals("InitialState", getCurrentState().getName());
462    }
463
464    @Test
465    public void loadComponentsInStaMode() throws Exception {
466        startSupplicantAndDispatchMessages();
467
468        assertEquals("DisconnectedState", getCurrentState().getName());
469    }
470
471    @Test
472    public void loadComponentsInApMode() throws Exception {
473        mWsm.setHostApRunning(new WifiConfiguration(), true);
474        mLooper.dispatchAll();
475
476        assertEquals("SoftApState", getCurrentState().getName());
477
478        verify(mSoftApManager).start();
479    }
480
481    @Test
482    public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception {
483        when(mWifiNative.enableSupplicant()).thenReturn(false);
484        mWsm.setSupplicantRunning(true);
485        mLooper.dispatchAll();
486        assertEquals("InitialState", getCurrentState().getName());
487    }
488
489    @Test
490    public void shouldRequireWificondToLeaveInitialState() throws Exception {
491        // We start out with valid default values, break them going backwards so that
492        // we test all the bailout cases.
493
494        // ClientInterface dies after creation.
495        doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt());
496        mWsm.setSupplicantRunning(true);
497        mLooper.dispatchAll();
498        assertEquals("InitialState", getCurrentState().getName());
499
500        // Failed to even create the client interface.
501        when(mWificond.createClientInterface()).thenReturn(null);
502        mWsm.setSupplicantRunning(true);
503        mLooper.dispatchAll();
504        assertEquals("InitialState", getCurrentState().getName());
505
506        // Failed to get wificond proxy.
507        when(mWifiInjector.makeWificond()).thenReturn(null);
508        mWsm.setSupplicantRunning(true);
509        mLooper.dispatchAll();
510        assertEquals("InitialState", getCurrentState().getName());
511    }
512
513    @Test
514    public void loadComponentsFailure() throws Exception {
515        when(mWifiNative.startHal(anyBoolean())).thenReturn(false);
516        when(mWifiNative.enableSupplicant()).thenReturn(false);
517
518        mWsm.setSupplicantRunning(true);
519        mLooper.dispatchAll();
520        assertEquals("InitialState", getCurrentState().getName());
521
522        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
523        mWsm.setSupplicantRunning(true);
524        mLooper.dispatchAll();
525        assertEquals("InitialState", getCurrentState().getName());
526    }
527
528    @Test
529    public void checkInitialStateStickyWhenDisabledMode() throws Exception {
530        mLooper.dispatchAll();
531        assertEquals("InitialState", getCurrentState().getName());
532        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
533
534        mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE);
535        mLooper.dispatchAll();
536        assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest());
537        assertEquals("InitialState", getCurrentState().getName());
538    }
539
540    @Test
541    public void shouldStartSupplicantWhenConnectModeRequested() throws Exception {
542        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
543
544        // The first time we start out in InitialState, we sit around here.
545        mLooper.dispatchAll();
546        assertEquals("InitialState", getCurrentState().getName());
547        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
548
549        // But if someone tells us to enter connect mode, we start up supplicant
550        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
551        mLooper.dispatchAll();
552        assertEquals("SupplicantStartingState", getCurrentState().getName());
553    }
554
555    /**
556     *  Test that mode changes accurately reflect the value for isWifiEnabled.
557     */
558    @Test
559    public void checkIsWifiEnabledForModeChanges() throws Exception {
560        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
561
562        // Check initial state
563        mLooper.dispatchAll();
564        assertEquals("InitialState", getCurrentState().getName());
565        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
566
567        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
568        startSupplicantAndDispatchMessages();
569        mWsm.setSupplicantRunning(true);
570        mLooper.dispatchAll();
571        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
572        assertEquals("ScanModeState", getCurrentState().getName());
573        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
574
575        // switch to connect mode and verify wifi is reported as enabled
576        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
577        mLooper.dispatchAll();
578        assertEquals("DisconnectedState", getCurrentState().getName());
579        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
580        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
581
582        // now go back to scan mode with "wifi disabled" to verify the reported wifi state.
583        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
584        mLooper.dispatchAll();
585        assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
586                     mWsm.getOperationalModeForTest());
587        assertEquals("ScanModeState", getCurrentState().getName());
588        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
589
590        // now go to AP mode
591        mWsm.setSupplicantRunning(false);
592        mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
593        mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT);
594        mWsm.setHostApRunning(new WifiConfiguration(), true);
595        mLooper.dispatchAll();
596        assertEquals("SoftApState", getCurrentState().getName());
597        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
598    }
599
600
601    /**
602     * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
603     * is started.
604     */
605    @Test
606    public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
607        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
608
609        // Check initial state
610        mLooper.dispatchAll();
611        assertEquals("InitialState", getCurrentState().getName());
612        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
613
614        // Update the mode
615        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
616        mLooper.dispatchAll();
617        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
618
619        // Start supplicant so we move to the next state
620        startSupplicantAndDispatchMessages();
621
622        assertEquals("ScanModeState", getCurrentState().getName());
623    }
624
625    /**
626     * Verifies that configs can be removed when in client mode.
627     */
628    @Test
629    public void canRemoveNetworkConfigInClientMode() throws Exception {
630        boolean result;
631        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
632        addNetworkAndVerifySuccess();
633        mLooper.startAutoDispatch();
634        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
635        mLooper.stopAutoDispatch();
636        assertTrue(result);
637    }
638
639    /**
640     * Verifies that configs can be removed when not in client mode.
641     */
642    @Test
643    public void canRemoveNetworkConfigWhenWifiDisabled() {
644        boolean result;
645        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
646        mLooper.startAutoDispatch();
647        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
648        mLooper.stopAutoDispatch();
649
650        assertTrue(result);
651        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
652    }
653
654    /**
655     * Verifies that configs can be forgotten when in client mode.
656     */
657    @Test
658    public void canForgetNetworkConfigInClientMode() throws Exception {
659        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
660        addNetworkAndVerifySuccess();
661        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
662        mLooper.dispatchAll();
663        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
664    }
665
666    /**
667     * Verifies that configs can be removed when not in client mode.
668     */
669    @Test
670    public void canForgetNetworkConfigWhenWifiDisabled() throws Exception {
671        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
672        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
673        mLooper.dispatchAll();
674        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
675    }
676
677    /**
678     * Helper method to move through SupplicantStarting and SupplicantStarted states.
679     */
680    private void startSupplicantAndDispatchMessages() throws Exception {
681        mWsm.setSupplicantRunning(true);
682        mLooper.dispatchAll();
683
684        assertEquals("SupplicantStartingState", getCurrentState().getName());
685
686        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
687        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
688        when(mWifiNative.setModelName(anyString())).thenReturn(true);
689        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
690        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
691        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
692        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
693        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
694        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
695
696        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
697        mLooper.dispatchAll();
698    }
699
700    private void addNetworkAndVerifySuccess() throws Exception {
701        addNetworkAndVerifySuccess(false);
702    }
703
704    private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception {
705        loadComponentsInStaMode();
706
707        WifiConfiguration config = new WifiConfiguration();
708        config.SSID = sSSID;
709        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
710        config.hiddenSSID = isHidden;
711
712        when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
713                .thenReturn(new NetworkUpdateResult(0));
714        when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
715        when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
716
717        mLooper.startAutoDispatch();
718        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
719        mLooper.stopAutoDispatch();
720
721        verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt());
722
723        mLooper.startAutoDispatch();
724        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
725        mLooper.stopAutoDispatch();
726        assertEquals(1, configs.size());
727
728        WifiConfiguration config2 = configs.get(0);
729        assertEquals("\"GoogleGuest\"", config2.SSID);
730        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
731    }
732
733    /**
734     * Helper method to retrieve WifiConfiguration by SSID.
735     *
736     * Returns the associated WifiConfiguration if it is found, null otherwise.
737     */
738    private WifiConfiguration getWifiConfigurationForNetwork(String ssid) {
739        mLooper.startAutoDispatch();
740        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
741        mLooper.stopAutoDispatch();
742
743        for (WifiConfiguration checkConfig : configs) {
744            if (checkConfig.SSID.equals(ssid)) {
745                return checkConfig;
746            }
747        }
748        return null;
749    }
750
751    private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) {
752        ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
753                ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
754        ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
755                ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
756        verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(),
757                eq(null));
758        WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue();
759        assertEquals("band", band, actualSettings.band);
760        assertEquals("reportEvents", reportEvents, actualSettings.reportEvents);
761
762        if (hiddenNetworkSSIDSet == null) {
763            hiddenNetworkSSIDSet = new HashSet<>();
764        }
765        Set<String> actualHiddenNetworkSSIDSet = new HashSet<>();
766        if (actualSettings.hiddenNetworks != null) {
767            for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) {
768                actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid);
769            }
770        }
771        assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet);
772
773        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
774        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
775
776        mLooper.dispatchAll();
777
778        List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
779        assertEquals(8, reportedResults.size());
780    }
781
782    @Test
783    public void scan() throws Exception {
784        addNetworkAndVerifySuccess();
785
786        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
787        mWsm.startScan(-1, 0, null, null);
788        mLooper.dispatchAll();
789
790        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
791                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
792                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null);
793    }
794
795    @Test
796    public void scanWithHiddenNetwork() throws Exception {
797        addNetworkAndVerifySuccess(true);
798
799        Set<String> hiddenNetworkSet = new HashSet<>();
800        hiddenNetworkSet.add(sSSID);
801        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>();
802        hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID));
803        when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList);
804
805        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
806        mWsm.startScan(-1, 0, null, null);
807        mLooper.dispatchAll();
808
809        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
810                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
811                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
812                hiddenNetworkSet);
813    }
814
815    @Test
816    public void connect() throws Exception {
817        addNetworkAndVerifySuccess();
818        when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(true);
819        when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(true);
820
821        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
822        mLooper.dispatchAll();
823        verify(mWifiNative).removeAllNetworks();
824
825        mLooper.startAutoDispatch();
826        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
827        mLooper.stopAutoDispatch();
828
829        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
830        verify(mWifiConnectivityManager).setUserConnectChoice(eq(0));
831
832        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
833        mLooper.dispatchAll();
834
835        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
836                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
837        mLooper.dispatchAll();
838
839        assertEquals("ObtainingIpState", getCurrentState().getName());
840
841        DhcpResults dhcpResults = new DhcpResults();
842        dhcpResults.setGateway("1.2.3.4");
843        dhcpResults.setIpAddress("192.168.1.100", 0);
844        dhcpResults.addDns("8.8.8.8");
845        dhcpResults.setLeaseDuration(3600);
846
847        mTestIpManager.injectDhcpSuccess(dhcpResults);
848        mLooper.dispatchAll();
849
850        assertEquals("ConnectedState", getCurrentState().getName());
851    }
852
853    @Test
854    public void connectWithNoEnablePermission() throws Exception {
855        addNetworkAndVerifySuccess();
856        when(mWifiConfigManager.enableNetwork(eq(0), eq(true), anyInt())).thenReturn(false);
857        when(mWifiConfigManager.checkAndUpdateLastConnectUid(eq(0), anyInt())).thenReturn(false);
858
859        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
860        mLooper.dispatchAll();
861        verify(mWifiNative).removeAllNetworks();
862
863        mLooper.startAutoDispatch();
864        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
865        mLooper.stopAutoDispatch();
866
867        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
868        verify(mWifiConnectivityManager, never()).setUserConnectChoice(eq(0));
869
870        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
871        mLooper.dispatchAll();
872
873        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
874                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
875        mLooper.dispatchAll();
876
877        assertEquals("ObtainingIpState", getCurrentState().getName());
878
879        DhcpResults dhcpResults = new DhcpResults();
880        dhcpResults.setGateway("1.2.3.4");
881        dhcpResults.setIpAddress("192.168.1.100", 0);
882        dhcpResults.addDns("8.8.8.8");
883        dhcpResults.setLeaseDuration(3600);
884
885        mTestIpManager.injectDhcpSuccess(dhcpResults);
886        mLooper.dispatchAll();
887
888        assertEquals("ConnectedState", getCurrentState().getName());
889    }
890
891    @Test
892    public void enableWithInvalidNetworkId() throws Exception {
893        addNetworkAndVerifySuccess();
894        when(mWifiConfigManager.getConfiguredNetwork(eq(0))).thenReturn(null);
895
896        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
897        mLooper.dispatchAll();
898        verify(mWifiNative).removeAllNetworks();
899
900        mLooper.startAutoDispatch();
901        assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
902        mLooper.stopAutoDispatch();
903
904        verify(mWifiConfigManager, never()).enableNetwork(eq(0), eq(true), anyInt());
905        verify(mWifiConfigManager, never()).checkAndUpdateLastConnectUid(eq(0), anyInt());
906    }
907
908    /**
909     * If caller tries to connect to a network that is already connected, the connection request
910     * should succeed.
911     *
912     * Test: Create and connect to a network, then try to reconnect to the same network. Verify
913     * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
914     */
915    @Test
916    public void reconnectToConnectedNetwork() throws Exception {
917        addNetworkAndVerifySuccess();
918
919        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
920        mLooper.dispatchAll();
921        verify(mWifiNative).removeAllNetworks();
922
923        mLooper.startAutoDispatch();
924        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
925        mLooper.stopAutoDispatch();
926
927        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
928
929        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
930        mLooper.dispatchAll();
931
932        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
933                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
934        mLooper.dispatchAll();
935
936        assertEquals("ObtainingIpState", getCurrentState().getName());
937
938        // try to reconnect
939        mLooper.startAutoDispatch();
940        Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0);
941        mLooper.stopAutoDispatch();
942
943        assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what);
944    }
945
946    @Test
947    public void testDhcpFailure() throws Exception {
948        addNetworkAndVerifySuccess();
949
950        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
951        mLooper.dispatchAll();
952
953        mLooper.startAutoDispatch();
954        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
955        mLooper.stopAutoDispatch();
956
957        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
958
959        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
960        mLooper.dispatchAll();
961
962        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
963                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
964        mLooper.dispatchAll();
965
966        assertEquals("ObtainingIpState", getCurrentState().getName());
967
968        mTestIpManager.injectDhcpFailure();
969        mLooper.dispatchAll();
970
971        assertEquals("DisconnectingState", getCurrentState().getName());
972    }
973
974    @Test
975    public void testBadNetworkEvent() throws Exception {
976        addNetworkAndVerifySuccess();
977
978        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
979        mLooper.dispatchAll();
980
981        mLooper.startAutoDispatch();
982        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
983        mLooper.stopAutoDispatch();
984
985        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
986
987        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
988        mLooper.dispatchAll();
989
990        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
991                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
992        mLooper.dispatchAll();
993
994        assertEquals("DisconnectedState", getCurrentState().getName());
995    }
996
997
998    @Test
999    public void smToString() throws Exception {
1000        assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString(
1001                AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
1002        assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString(
1003                DhcpClient.CMD_PRE_DHCP_ACTION));
1004        assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString(
1005                WifiStateMachine.CMD_IP_REACHABILITY_LOST));
1006    }
1007
1008    @Test
1009    public void disconnect() throws Exception {
1010        connect();
1011
1012        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
1013        mLooper.dispatchAll();
1014        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1015                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
1016        mLooper.dispatchAll();
1017
1018        assertEquals("DisconnectedState", getCurrentState().getName());
1019    }
1020
1021    /**
1022     * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
1023     * to true.
1024     *
1025     * Test: Successfully create and connect to a network. Check the config and verify
1026     * WifiConfiguration.getHasEverConnected() is true.
1027     */
1028    @Test
1029    public void setHasEverConnectedTrueOnConnect() throws Exception {
1030        connect();
1031        verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0);
1032    }
1033
1034    /**
1035     * Fail network connection attempt and verify HasEverConnected remains false.
1036     *
1037     * Test: Successfully create a network but fail when connecting. Check the config and verify
1038     * WifiConfiguration.getHasEverConnected() is false.
1039     */
1040    @Test
1041    public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
1042        testDhcpFailure();
1043        verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0);
1044    }
1045
1046    @Test
1047    public void iconQueryTest() throws Exception {
1048        // TODO(b/31065385): Passpoint config management.
1049    }
1050
1051    @Test
1052    public void verboseLogRecSizeIsGreaterThanNormalSize() {
1053        assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL);
1054    }
1055
1056    /**
1057     * Verifies that, by default, we allow only the "normal" number of log records.
1058     */
1059    @Test
1060    public void normalLogRecSizeIsUsedByDefault() {
1061        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
1062    }
1063
1064    /**
1065     * Verifies that, in verbose mode, we allow a larger number of log records.
1066     */
1067    @Test
1068    public void enablingVerboseLoggingUpdatesLogRecSize() {
1069        mWsm.enableVerboseLogging(1);
1070        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize());
1071    }
1072
1073    @Test
1074    public void disablingVerboseLoggingClearsRecords() {
1075        mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT);
1076        mLooper.dispatchAll();
1077        assertTrue(mWsm.getLogRecSize() >= 1);
1078
1079        mWsm.enableVerboseLogging(0);
1080        assertEquals(0, mWsm.getLogRecSize());
1081    }
1082
1083    @Test
1084    public void disablingVerboseLoggingUpdatesLogRecSize() {
1085        mWsm.enableVerboseLogging(1);
1086        mWsm.enableVerboseLogging(0);
1087        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
1088    }
1089
1090    /** Verifies that enabling verbose logging sets the hal log property in eng builds. */
1091    @Test
1092    public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() {
1093        reset(mPropertyService);  // Ignore calls made in setUp()
1094        when(mBuildProperties.isEngBuild()).thenReturn(true);
1095        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1096        when(mBuildProperties.isUserBuild()).thenReturn(false);
1097        mWsm.enableVerboseLogging(1);
1098        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1099    }
1100
1101    /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */
1102    @Test
1103    public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() {
1104        reset(mPropertyService);  // Ignore calls made in setUp()
1105        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
1106        when(mBuildProperties.isEngBuild()).thenReturn(false);
1107        when(mBuildProperties.isUserBuild()).thenReturn(false);
1108        mWsm.enableVerboseLogging(1);
1109        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1110    }
1111
1112    /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */
1113    @Test
1114    public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() {
1115        reset(mPropertyService);  // Ignore calls made in setUp()
1116        when(mBuildProperties.isUserBuild()).thenReturn(true);
1117        when(mBuildProperties.isEngBuild()).thenReturn(false);
1118        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1119        mWsm.enableVerboseLogging(1);
1120        verify(mPropertyService, never()).set(anyString(), anyString());
1121    }
1122
1123    private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) {
1124        AsyncChannel channel = mock(AsyncChannel.class);
1125        Message reply = Message.obtain();
1126        reply.arg1 = supportedFeatures;
1127        reset(mPropertyService);  // Ignore calls made in setUp()
1128        when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES))
1129                .thenReturn(reply);
1130        when(mPropertyService.getBoolean("config.disable_rtt", false))
1131                .thenReturn(rttConfigured);
1132        return mWsm.syncGetSupportedFeatures(channel);
1133    }
1134
1135    /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
1136    @Test
1137    public void syncGetSupportedFeatures() {
1138        final int featureAware = WifiManager.WIFI_FEATURE_AWARE;
1139        final int featureInfra = WifiManager.WIFI_FEATURE_INFRA;
1140        final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
1141        final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;
1142
1143        assertEquals(0, testGetSupportedFeaturesCase(0, false));
1144        assertEquals(0, testGetSupportedFeaturesCase(0, true));
1145        assertEquals(featureAware | featureInfra,
1146                testGetSupportedFeaturesCase(featureAware | featureInfra, false));
1147        assertEquals(featureAware | featureInfra,
1148                testGetSupportedFeaturesCase(featureAware | featureInfra, true));
1149        assertEquals(featureInfra | featureD2dRtt,
1150                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false));
1151        assertEquals(featureInfra,
1152                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true));
1153        assertEquals(featureInfra | featureD2apRtt,
1154                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false));
1155        assertEquals(featureInfra,
1156                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true));
1157        assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
1158                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false));
1159        assertEquals(featureInfra,
1160                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true));
1161    }
1162
1163    /**
1164     * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager}
1165     * and returning the result that's returned from {@link PasspointManager}.
1166     */
1167    @Test
1168    public void syncAddOrUpdatePasspointConfig() throws Exception {
1169        PasspointConfiguration config = new PasspointConfiguration();
1170        HomeSp homeSp = new HomeSp();
1171        homeSp.setFqdn("test.com");
1172        config.setHomeSp(homeSp);
1173
1174        when(mPasspointManager.addOrUpdateProvider(config)).thenReturn(true);
1175        mLooper.startAutoDispatch();
1176        assertTrue(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, config));
1177        mLooper.stopAutoDispatch();
1178        reset(mPasspointManager);
1179
1180        when(mPasspointManager.addOrUpdateProvider(config)).thenReturn(false);
1181        mLooper.startAutoDispatch();
1182        assertFalse(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel, config));
1183        mLooper.stopAutoDispatch();
1184    }
1185
1186    /**
1187     * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager}
1188     * and returning the result that's returned from {@link PasspointManager} when in client mode.
1189     */
1190    @Test
1191    public void syncAddOrUpdatePasspointConfigInClientMode() throws Exception {
1192        loadComponentsInStaMode();
1193        syncAddOrUpdatePasspointConfig();
1194    }
1195
1196    /**
1197     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
1198     * and returning the result that's returned from {@link PasspointManager}.
1199     */
1200    @Test
1201    public void syncRemovePasspointConfig() throws Exception {
1202        String fqdn = "test.com";
1203        when(mPasspointManager.removeProvider(fqdn)).thenReturn(true);
1204        mLooper.startAutoDispatch();
1205        assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
1206        mLooper.stopAutoDispatch();
1207        reset(mPasspointManager);
1208
1209        when(mPasspointManager.removeProvider(fqdn)).thenReturn(false);
1210        mLooper.startAutoDispatch();
1211        assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
1212        mLooper.stopAutoDispatch();
1213    }
1214
1215    /**
1216     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
1217     * and returning the result that's returned from {@link PasspointManager} when in client mode.
1218     */
1219    @Test
1220    public void syncRemovePasspointConfigInClientMode() throws Exception {
1221        loadComponentsInStaMode();
1222        syncRemovePasspointConfig();
1223    }
1224
1225    /**
1226     * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager}
1227     * and returning the result that's returned from {@link PasspointManager}.
1228     */
1229    @Test
1230    public void syncGetPasspointConfigs() throws Exception {
1231        // Setup expected configs.
1232        List<PasspointConfiguration> expectedConfigs = new ArrayList<>();
1233        PasspointConfiguration config = new PasspointConfiguration();
1234        HomeSp homeSp = new HomeSp();
1235        homeSp.setFqdn("test.com");
1236        config.setHomeSp(homeSp);
1237        expectedConfigs.add(config);
1238
1239        when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs);
1240        mLooper.startAutoDispatch();
1241        assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel));
1242        mLooper.stopAutoDispatch();
1243        reset(mPasspointManager);
1244
1245        when(mPasspointManager.getProviderConfigs())
1246                .thenReturn(new ArrayList<PasspointConfiguration>());
1247        mLooper.startAutoDispatch();
1248        assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty());
1249        mLooper.stopAutoDispatch();
1250    }
1251
1252    /**
1253     * Verify that syncGetMatchingWifiConfig will redirect calls to {@link PasspointManager}
1254     * with expected {@link WifiConfiguration} being returned when in client mode.
1255     *
1256     * @throws Exception
1257     */
1258    @Test
1259    public void syncGetMatchingWifiConfigInClientMode() throws Exception {
1260        loadComponentsInStaMode();
1261
1262        when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class))).thenReturn(null);
1263        mLooper.startAutoDispatch();
1264        assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel));
1265        mLooper.stopAutoDispatch();
1266        reset(mPasspointManager);
1267
1268        WifiConfiguration expectedConfig = new WifiConfiguration();
1269        expectedConfig.SSID = "TestSSID";
1270        when(mPasspointManager.getMatchingWifiConfig(any(ScanResult.class)))
1271                .thenReturn(expectedConfig);
1272        mLooper.startAutoDispatch();
1273        WifiConfiguration actualConfig = mWsm.syncGetMatchingWifiConfig(new ScanResult(),
1274                mWsmAsyncChannel);
1275        mLooper.stopAutoDispatch();
1276        assertEquals(expectedConfig.SSID, actualConfig.SSID);
1277    }
1278
1279    /**
1280     * Verify that syncGetMatchingWifiConfig will be a no-op and return {@code null} when not in
1281     * client mode.
1282     *
1283     * @throws Exception
1284     */
1285    @Test
1286    public void syncGetMatchingWifiConfigInNonClientMode() throws Exception {
1287        mLooper.startAutoDispatch();
1288        assertNull(mWsm.syncGetMatchingWifiConfig(new ScanResult(), mWsmAsyncChannel));
1289        mLooper.stopAutoDispatch();
1290        verify(mPasspointManager, never()).getMatchingWifiConfig(any(ScanResult.class));
1291    }
1292
1293    /**
1294     * Verify successful Wps PBC network connection.
1295     */
1296    @Test
1297    public void wpsPbcConnectSuccess() throws Exception {
1298        loadComponentsInStaMode();
1299        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1300        mLooper.dispatchAll();
1301
1302        when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(true);
1303        WpsInfo wpsInfo = new WpsInfo();
1304        wpsInfo.setup = WpsInfo.PBC;
1305        wpsInfo.BSSID = sBSSID;
1306
1307        mLooper.startAutoDispatch();
1308        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
1309        mLooper.stopAutoDispatch();
1310        verify(mWifiNative).startWpsPbc(eq(sBSSID));
1311
1312        assertEquals("WpsRunningState", getCurrentState().getName());
1313
1314        setupMocksForWpsNetworkMigration();
1315
1316        mLooper.startAutoDispatch();
1317        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
1318        mLooper.stopAutoDispatch();
1319
1320        assertEquals("DisconnectedState", getCurrentState().getName());
1321    }
1322
1323    /**
1324     * Verify failure in starting Wps PBC network connection.
1325     */
1326    @Test
1327    public void wpsPbcConnectFailure() throws Exception {
1328        loadComponentsInStaMode();
1329        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1330        mLooper.dispatchAll();
1331
1332        when(mWifiNative.startWpsPbc(eq(sBSSID))).thenReturn(false);
1333        WpsInfo wpsInfo = new WpsInfo();
1334        wpsInfo.setup = WpsInfo.PBC;
1335        wpsInfo.BSSID = sBSSID;
1336
1337        mLooper.startAutoDispatch();
1338        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
1339        mLooper.stopAutoDispatch();
1340        verify(mWifiNative).startWpsPbc(eq(sBSSID));
1341
1342        assertFalse("WpsRunningState".equals(getCurrentState().getName()));
1343    }
1344
1345    /**
1346     * Verify successful Wps Pin Display network connection.
1347     */
1348    @Test
1349    public void wpsPinDisplayConnectSuccess() throws Exception {
1350        loadComponentsInStaMode();
1351        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1352        mLooper.dispatchAll();
1353
1354        when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn("34545434");
1355        WpsInfo wpsInfo = new WpsInfo();
1356        wpsInfo.setup = WpsInfo.DISPLAY;
1357        wpsInfo.BSSID = sBSSID;
1358
1359        mLooper.startAutoDispatch();
1360        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
1361        mLooper.stopAutoDispatch();
1362        verify(mWifiNative).startWpsPinDisplay(eq(sBSSID));
1363
1364        assertEquals("WpsRunningState", getCurrentState().getName());
1365
1366        setupMocksForWpsNetworkMigration();
1367
1368        mLooper.startAutoDispatch();
1369        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, null);
1370        mLooper.stopAutoDispatch();
1371
1372        assertEquals("DisconnectedState", getCurrentState().getName());
1373    }
1374
1375    /**
1376     * Verify failure in Wps Pin Display network connection.
1377     */
1378    @Test
1379    public void wpsPinDisplayConnectFailure() throws Exception {
1380        loadComponentsInStaMode();
1381        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1382        mLooper.dispatchAll();
1383
1384        when(mWifiNative.startWpsPinDisplay(eq(sBSSID))).thenReturn(null);
1385        WpsInfo wpsInfo = new WpsInfo();
1386        wpsInfo.setup = WpsInfo.DISPLAY;
1387        wpsInfo.BSSID = sBSSID;
1388
1389        mLooper.startAutoDispatch();
1390        mWsm.sendMessage(WifiManager.START_WPS, 0, 0, wpsInfo);
1391        mLooper.stopAutoDispatch();
1392        verify(mWifiNative).startWpsPinDisplay(eq(sBSSID));
1393
1394        assertFalse("WpsRunningState".equals(getCurrentState().getName()));
1395    }
1396
1397    @Test
1398    public void handleVendorHalDeath() throws Exception {
1399        ArgumentCaptor<WifiNative.VendorHalDeathEventHandler> deathHandlerCapturer =
1400                ArgumentCaptor.forClass(WifiNative.VendorHalDeathEventHandler.class);
1401        when(mWifiNative.initializeVendorHal(deathHandlerCapturer.capture())).thenReturn(true);
1402
1403        // Trigger initialize to capture the death handler registration.
1404        mLooper.startAutoDispatch();
1405        assertTrue(mWsm.syncInitialize(mWsmAsyncChannel));
1406        mLooper.stopAutoDispatch();
1407
1408        verify(mWifiNative).initializeVendorHal(any(WifiNative.VendorHalDeathEventHandler.class));
1409        WifiNative.VendorHalDeathEventHandler deathHandler = deathHandlerCapturer.getValue();
1410
1411        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1412        mLooper.dispatchAll();
1413
1414        // We should not be in initial state now.
1415        assertFalse("InitialState".equals(getCurrentState().getName()));
1416
1417        // Now trigger the death notification.
1418        mLooper.startAutoDispatch();
1419        deathHandler.onDeath();
1420        mLooper.stopAutoDispatch();
1421
1422        // We should back to initial state after vendor HAL death.
1423        assertTrue("InitialState".equals(getCurrentState().getName()));
1424    }
1425
1426    private void setupMocksForWpsNetworkMigration() {
1427        int newNetworkId = 5;
1428        // Now trigger the network connection event for adding the WPS network.
1429        doAnswer(new AnswerWithArguments() {
1430            public boolean answer(Map<String, WifiConfiguration> configs,
1431                                  SparseArray<Map<String, String>> networkExtras) throws Exception {
1432                configs.put("dummy", new WifiConfiguration());
1433                return true;
1434            }
1435        }).when(mWifiNative).migrateNetworksFromSupplicant(any(Map.class), any(SparseArray.class));
1436        when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
1437                .thenReturn(new NetworkUpdateResult(newNetworkId));
1438        when(mWifiConfigManager.enableNetwork(eq(newNetworkId), anyBoolean(), anyInt()))
1439                .thenReturn(true);
1440    }
1441
1442    /**
1443     * Verifies that WifiInfo is cleared upon exiting and entering WifiInfo, and that it is not
1444     * updated by SUPPLICAN_STATE_CHANGE_EVENTs in ScanModeState.
1445     * This protects WifiStateMachine from  getting into a bad state where WifiInfo says wifi is
1446     * already Connected or Connecting, (when it is in-fact Disconnected), so
1447     * WifiConnectivityManager does not attempt any new Connections, freezing wifi.
1448     */
1449    @Test
1450    public void testWifiInfoCleanedUpEnteringExitingConnectModeState() throws Exception {
1451        InOrder inOrder = inOrder(mWifiConnectivityManager);
1452        Log.i(TAG, mWsm.getCurrentState().getName());
1453        String initialBSSID = "aa:bb:cc:dd:ee:ff";
1454        WifiInfo wifiInfo = mWsm.getWifiInfo();
1455        wifiInfo.setBSSID(initialBSSID);
1456
1457        // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager
1458        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1459        startSupplicantAndDispatchMessages();
1460        mWsm.setSupplicantRunning(true);
1461        mLooper.dispatchAll();
1462        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
1463        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
1464        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
1465        assertNull(wifiInfo.getBSSID());
1466
1467        // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is updated
1468        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1469                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1470        mLooper.dispatchAll();
1471        assertEquals(sBSSID, wifiInfo.getBSSID());
1472        assertEquals(SupplicantState.COMPLETED, wifiInfo.getSupplicantState());
1473
1474        // Set WSM to SCAN_ONLY_MODE, verify state and wifi disabled in ConnectivityManager, and
1475        // WifiInfo is reset() and state set to DISCONNECTED
1476        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
1477        mLooper.dispatchAll();
1478        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
1479        assertEquals("ScanModeState", getCurrentState().getName());
1480        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
1481        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(false));
1482        assertNull(wifiInfo.getBSSID());
1483        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
1484
1485        // Send a SUPPLICANT_STATE_CHANGE_EVENT, verify WifiInfo is not updated
1486        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1487                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1488        mLooper.dispatchAll();
1489        assertNull(wifiInfo.getBSSID());
1490        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
1491
1492        // Set the bssid to something, so we can verify it is cleared (just in case)
1493        wifiInfo.setBSSID(initialBSSID);
1494
1495        // Set WSM to CONNECT_MODE and verify state, and wifi enabled in ConnectivityManager,
1496        // and WifiInfo has been reset
1497        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1498        mLooper.dispatchAll();
1499        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
1500        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
1501        inOrder.verify(mWifiConnectivityManager).setWifiEnabled(eq(true));
1502        assertEquals("DisconnectedState", getCurrentState().getName());
1503        assertEquals(SupplicantState.DISCONNECTED, wifiInfo.getSupplicantState());
1504        assertNull(wifiInfo.getBSSID());
1505    }
1506}
1507