WifiStateMachineTest.java revision 835e781643b79c30fabbab5595770cf01b5861fb
1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wifi;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.Mockito.*;
23
24import android.app.ActivityManager;
25import android.app.test.MockAnswerUtil.AnswerWithArguments;
26import android.app.test.TestAlarmManager;
27import android.content.Context;
28import android.content.pm.PackageManager;
29import android.content.pm.UserInfo;
30import android.content.res.Resources;
31import android.net.ConnectivityManager;
32import android.net.DhcpResults;
33import android.net.LinkProperties;
34import android.net.dhcp.DhcpClient;
35import android.net.ip.IpManager;
36import android.net.wifi.IApInterface;
37import android.net.wifi.IClientInterface;
38import android.net.wifi.IWificond;
39import android.net.wifi.ScanResult;
40import android.net.wifi.SupplicantState;
41import android.net.wifi.WifiConfiguration;
42import android.net.wifi.WifiInfo;
43import android.net.wifi.WifiManager;
44import android.net.wifi.WifiScanner;
45import android.net.wifi.WifiSsid;
46import android.net.wifi.hotspot2.PasspointConfiguration;
47import android.net.wifi.hotspot2.pps.HomeSp;
48import android.net.wifi.p2p.IWifiP2pManager;
49import android.os.BatteryStats;
50import android.os.Binder;
51import android.os.Bundle;
52import android.os.Handler;
53import android.os.HandlerThread;
54import android.os.IBinder;
55import android.os.IInterface;
56import android.os.INetworkManagementService;
57import android.os.IPowerManager;
58import android.os.Looper;
59import android.os.Message;
60import android.os.Messenger;
61import android.os.PowerManager;
62import android.os.RemoteException;
63import android.os.UserHandle;
64import android.os.UserManager;
65import android.os.test.TestLooper;
66import android.provider.Settings;
67import android.security.KeyStore;
68import android.test.mock.MockContentProvider;
69import android.test.mock.MockContentResolver;
70import android.test.suitebuilder.annotation.SmallTest;
71import android.util.Log;
72
73import com.android.internal.R;
74import com.android.internal.app.IBatteryStats;
75import com.android.internal.util.AsyncChannel;
76import com.android.internal.util.IState;
77import com.android.internal.util.StateMachine;
78import com.android.server.wifi.hotspot2.NetworkDetail;
79import com.android.server.wifi.hotspot2.PasspointManager;
80import com.android.server.wifi.p2p.WifiP2pServiceImpl;
81
82import org.junit.After;
83import org.junit.Before;
84import org.junit.Test;
85import org.mockito.ArgumentCaptor;
86import org.mockito.Mock;
87import org.mockito.MockitoAnnotations;
88
89import java.io.ByteArrayOutputStream;
90import java.io.PrintWriter;
91import java.lang.reflect.Field;
92import java.lang.reflect.InvocationTargetException;
93import java.lang.reflect.Method;
94import java.util.ArrayList;
95import java.util.Arrays;
96import java.util.HashSet;
97import java.util.List;
98import java.util.Set;
99import java.util.concurrent.CountDownLatch;
100
101/**
102 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
103 */
104@SmallTest
105public class WifiStateMachineTest {
106    public static final String TAG = "WifiStateMachineTest";
107
108    private static final int MANAGED_PROFILE_UID = 1100000;
109    private static final int OTHER_USER_UID = 1200000;
110    private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
111            (ActivityManager.isLowRamDeviceStatic()
112                    ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
113                    : WifiStateMachine.NUM_LOG_RECS_VERBOSE);
114    private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
115
116    private long mBinderToken;
117
118    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
119        return mock(class1, withSettings().extraInterfaces(interfaces));
120    }
121
122    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
123        T tImpl = mockWithInterfaces(class1, iface);
124        IBinder binder = mock(IBinder.class);
125        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
126        when(binder.queryLocalInterface(iface.getCanonicalName()))
127                .thenReturn((IInterface) tImpl);
128        return binder;
129    }
130
131    private void enableDebugLogs() {
132        mWsm.enableVerboseLogging(1);
133    }
134
135    private class TestIpManager extends IpManager {
136        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
137            // Call dependency-injection superclass constructor.
138            super(context, ifname, callback, mock(INetworkManagementService.class));
139        }
140
141        @Override
142        public void startProvisioning(IpManager.ProvisioningConfiguration config) {}
143
144        @Override
145        public void stop() {}
146
147        @Override
148        public void confirmConfiguration() {}
149
150        void injectDhcpSuccess(DhcpResults dhcpResults) {
151            mCallback.onNewDhcpResults(dhcpResults);
152            mCallback.onProvisioningSuccess(new LinkProperties());
153        }
154
155        void injectDhcpFailure() {
156            mCallback.onNewDhcpResults(null);
157            mCallback.onProvisioningFailure(new LinkProperties());
158        }
159    }
160
161    private FrameworkFacade getFrameworkFacade() throws Exception {
162        FrameworkFacade facade = mock(FrameworkFacade.class);
163
164        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
165                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
166
167        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
168        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
169
170        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
171                IWifiP2pManager.class.getCanonicalName());
172
173        final CountDownLatch untilDone = new CountDownLatch(1);
174        mP2pThread = new HandlerThread("WifiP2pMockThread") {
175            @Override
176            protected void onLooperPrepared() {
177                untilDone.countDown();
178            }
179        };
180
181        mP2pThread.start();
182        untilDone.await();
183
184        Handler handler = new Handler(mP2pThread.getLooper());
185        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
186
187        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
188        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);
189
190        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
191                .then(new AnswerWithArguments() {
192                    public IpManager answer(
193                            Context context, String ifname, IpManager.Callback callback) {
194                        mTestIpManager = new TestIpManager(context, ifname, callback);
195                        return mTestIpManager;
196                    }
197                });
198
199        return facade;
200    }
201
202    private Context getContext() throws Exception {
203        PackageManager pkgMgr = mock(PackageManager.class);
204        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
205
206        Context context = mock(Context.class);
207        when(context.getPackageManager()).thenReturn(pkgMgr);
208
209        MockResources resources = new com.android.server.wifi.MockResources();
210        when(context.getResources()).thenReturn(resources);
211
212        MockContentResolver mockContentResolver = new MockContentResolver();
213        mockContentResolver.addProvider(Settings.AUTHORITY,
214                new MockContentProvider(context) {
215                    @Override
216                    public Bundle call(String method, String arg, Bundle extras) {
217                        return new Bundle();
218                    }
219                });
220        when(context.getContentResolver()).thenReturn(mockContentResolver);
221
222        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
223                new PowerManager(context, mock(IPowerManager.class), new Handler()));
224
225        mAlarmManager = new TestAlarmManager();
226        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
227                mAlarmManager.getAlarmManager());
228
229        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
230                mock(ConnectivityManager.class));
231
232        return context;
233    }
234
235    private Resources getMockResources() {
236        MockResources resources = new MockResources();
237        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
238        return resources;
239    }
240
241    private IState getCurrentState() throws
242            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
243        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
244        method.setAccessible(true);
245        return (IState) method.invoke(mWsm);
246    }
247
248    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
249            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
250        Field field = StateMachine.class.getDeclaredField("mSmThread");
251        field.setAccessible(true);
252        return (HandlerThread) field.get(wsm);
253    }
254
255    private static void stopLooper(final Looper looper) throws Exception {
256        new Handler(looper).post(new Runnable() {
257            @Override
258            public void run() {
259                looper.quitSafely();
260            }
261        });
262    }
263
264    private void dumpState() {
265        ByteArrayOutputStream stream = new ByteArrayOutputStream();
266        PrintWriter writer = new PrintWriter(stream);
267        mWsm.dump(null, writer, null);
268        writer.flush();
269        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
270    }
271
272    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
273        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
274        ie[0] = ScanResults.generateSsidIe(sSSID);
275        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
276        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
277                Long.MAX_VALUE, /* needed so that scan results aren't rejected because
278                                   there older than scan start */
279                ie, new ArrayList<String>());
280        return detail;
281    }
282
283    private ArrayList<ScanDetail> getMockScanResults() {
284        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
285        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
286
287        int rssi = -65;
288        list.add(getGoogleGuestScanDetail(rssi));
289        return list;
290    }
291
292    static final String   sSSID = "\"GoogleGuest\"";
293    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
294    static final String   sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
295    static final String   sBSSID = "01:02:03:04:05:06";
296    static final int      sFreq = 2437;
297
298    WifiStateMachine mWsm;
299    HandlerThread mWsmThread;
300    HandlerThread mP2pThread;
301    HandlerThread mSyncThread;
302    AsyncChannel  mWsmAsyncChannel;
303    TestAlarmManager mAlarmManager;
304    MockWifiMonitor mWifiMonitor;
305    TestIpManager mTestIpManager;
306    TestLooper mLooper;
307
308    @Mock WifiScanner mWifiScanner;
309    @Mock SupplicantStateTracker mSupplicantStateTracker;
310    @Mock WifiMetrics mWifiMetrics;
311    @Mock UserManager mUserManager;
312    @Mock WifiApConfigStore mApConfigStore;
313    @Mock BackupManagerProxy mBackupManagerProxy;
314    @Mock WifiCountryCode mCountryCode;
315    @Mock WifiInjector mWifiInjector;
316    @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
317    @Mock PropertyService mPropertyService;
318    @Mock BuildProperties mBuildProperties;
319    @Mock IWificond mWificond;
320    @Mock IApInterface mApInterface;
321    @Mock IClientInterface mClientInterface;
322    @Mock IBinder mApInterfaceBinder;
323    @Mock IBinder mClientInterfaceBinder;
324    @Mock WifiConfigManager mWifiConfigManager;
325    @Mock WifiNative mWifiNative;
326    @Mock WifiConnectivityManager mWifiConnectivityManager;
327    @Mock SoftApManager mSoftApManager;
328    @Mock WifiStateTracker mWifiStateTracker;
329    @Mock PasspointManager mPasspointManager;
330
331    public WifiStateMachineTest() throws Exception {
332    }
333
334    @Before
335    public void setUp() throws Exception {
336        Log.d(TAG, "Setting up ...");
337
338        // Ensure looper exists
339        mLooper = new TestLooper();
340
341        MockitoAnnotations.initMocks(this);
342
343        /** uncomment this to enable logs from WifiStateMachines */
344        // enableDebugLogs();
345
346        mWifiMonitor = new MockWifiMonitor();
347        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
348        when(mWifiInjector.getClock()).thenReturn(new Clock());
349        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
350        when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
351        when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
352        when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
353        when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class));
354        when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn(
355                mock(BaseWifiDiagnostics.class));
356        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
357        when(mWifiInjector.getWifiConfigManager()).thenReturn(mWifiConfigManager);
358        when(mWifiInjector.getWifiScanner()).thenReturn(mWifiScanner);
359        when(mWifiInjector.getWifiNetworkSelector()).thenReturn(mock(WifiNetworkSelector.class));
360        when(mWifiInjector.makeWifiConnectivityManager(any(WifiInfo.class), anyBoolean()))
361                .thenReturn(mWifiConnectivityManager);
362        when(mWifiInjector.makeSoftApManager(any(INetworkManagementService.class),
363                any(SoftApManager.Listener.class), any(IApInterface.class),
364                any(WifiConfiguration.class)))
365                .thenReturn(mSoftApManager);
366        when(mWifiInjector.getPasspointManager()).thenReturn(mPasspointManager);
367
368        when(mWifiNative.setupForClientMode()).thenReturn(mClientInterface);
369        when(mWifiNative.setupForSoftApMode()).thenReturn(mApInterface);
370        when(mWifiInjector.getWifiStateTracker()).thenReturn(mWifiStateTracker);
371        when(mWifiNative.getInterfaceName()).thenReturn("mockWlan");
372        when(mWifiNative.enableSupplicant()).thenReturn(true);
373        when(mWifiNative.disableSupplicant()).thenReturn(true);
374        when(mWifiNative.getFrameworkNetworkId(anyInt())).thenReturn(0);
375
376
377        FrameworkFacade factory = getFrameworkFacade();
378        Context context = getContext();
379
380        Resources resources = getMockResources();
381        when(context.getResources()).thenReturn(resources);
382
383        when(factory.getIntegerSetting(context,
384                Settings.Global.WIFI_FREQUENCY_BAND,
385                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
386                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
387
388        when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy)))
389                .thenReturn(mApConfigStore);
390
391        when(factory.makeSupplicantStateTracker(
392                any(Context.class), any(WifiConfigManager.class),
393                any(Handler.class))).thenReturn(mSupplicantStateTracker);
394
395        when(mUserManager.getProfileParent(11))
396                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
397        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
398                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
399                new UserInfo(11, "managed profile", 0)));
400
401        when(mApInterface.asBinder()).thenReturn(mApInterfaceBinder);
402        when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder);
403
404        mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(),
405            mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode, mWifiNative);
406        mWsmThread = getWsmHandlerThread(mWsm);
407
408        final AsyncChannel channel = new AsyncChannel();
409        Handler handler = new Handler(mLooper.getLooper()) {
410            @Override
411            public void handleMessage(Message msg) {
412                switch (msg.what) {
413                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
414                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
415                            mWsmAsyncChannel = channel;
416                        } else {
417                            Log.d(TAG, "Failed to connect Command channel " + this);
418                        }
419                        break;
420                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
421                        Log.d(TAG, "Command channel disconnected" + this);
422                        break;
423                }
424            }
425        };
426
427        channel.connect(context, handler, mWsm.getMessenger());
428        mLooper.dispatchAll();
429        /* Now channel is supposed to be connected */
430
431        mBinderToken = Binder.clearCallingIdentity();
432    }
433
434    @After
435    public void cleanUp() throws Exception {
436        Binder.restoreCallingIdentity(mBinderToken);
437
438        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
439        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
440        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
441
442        mWsmThread = null;
443        mP2pThread = null;
444        mSyncThread = null;
445        mWsmAsyncChannel = null;
446        mWsm = null;
447    }
448
449    @Test
450    public void createNew() throws Exception {
451        assertEquals("InitialState", getCurrentState().getName());
452
453        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
454        mLooper.dispatchAll();
455        assertEquals("InitialState", getCurrentState().getName());
456    }
457
458    @Test
459    public void loadComponentsInStaMode() throws Exception {
460        startSupplicantAndDispatchMessages();
461
462        assertEquals("DisconnectedState", getCurrentState().getName());
463    }
464
465    @Test
466    public void loadComponentsInApMode() throws Exception {
467        mWsm.setHostApRunning(new WifiConfiguration(), true);
468        mLooper.dispatchAll();
469
470        assertEquals("SoftApState", getCurrentState().getName());
471
472        verify(mSoftApManager).start();
473    }
474
475    @Test
476    public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception {
477        when(mWifiNative.enableSupplicant()).thenReturn(false);
478        mWsm.setSupplicantRunning(true);
479        mLooper.dispatchAll();
480        assertEquals("InitialState", getCurrentState().getName());
481    }
482
483    @Test
484    public void shouldRequireWificondToLeaveInitialState() throws Exception {
485        // We start out with valid default values, break them going backwards so that
486        // we test all the bailout cases.
487
488        // ClientInterface dies after creation.
489        doThrow(new RemoteException()).when(mClientInterfaceBinder).linkToDeath(any(), anyInt());
490        mWsm.setSupplicantRunning(true);
491        mLooper.dispatchAll();
492        assertEquals("InitialState", getCurrentState().getName());
493
494        // Failed to even create the client interface.
495        when(mWificond.createClientInterface()).thenReturn(null);
496        mWsm.setSupplicantRunning(true);
497        mLooper.dispatchAll();
498        assertEquals("InitialState", getCurrentState().getName());
499
500        // Failed to get wificond proxy.
501        when(mWifiInjector.makeWificond()).thenReturn(null);
502        mWsm.setSupplicantRunning(true);
503        mLooper.dispatchAll();
504        assertEquals("InitialState", getCurrentState().getName());
505    }
506
507    @Test
508    public void loadComponentsFailure() throws Exception {
509        when(mWifiNative.startHal(anyBoolean())).thenReturn(false);
510        when(mWifiNative.enableSupplicant()).thenReturn(false);
511
512        mWsm.setSupplicantRunning(true);
513        mLooper.dispatchAll();
514        assertEquals("InitialState", getCurrentState().getName());
515
516        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
517        mWsm.setSupplicantRunning(true);
518        mLooper.dispatchAll();
519        assertEquals("InitialState", getCurrentState().getName());
520    }
521
522    @Test
523    public void checkInitialStateStickyWhenDisabledMode() throws Exception {
524        mLooper.dispatchAll();
525        assertEquals("InitialState", getCurrentState().getName());
526        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
527
528        mWsm.setOperationalMode(WifiStateMachine.DISABLED_MODE);
529        mLooper.dispatchAll();
530        assertEquals(WifiStateMachine.DISABLED_MODE, mWsm.getOperationalModeForTest());
531        assertEquals("InitialState", getCurrentState().getName());
532    }
533
534    @Test
535    public void shouldStartSupplicantWhenConnectModeRequested() throws Exception {
536        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
537
538        // The first time we start out in InitialState, we sit around here.
539        mLooper.dispatchAll();
540        assertEquals("InitialState", getCurrentState().getName());
541        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
542
543        // But if someone tells us to enter connect mode, we start up supplicant
544        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
545        mLooper.dispatchAll();
546        assertEquals("SupplicantStartingState", getCurrentState().getName());
547    }
548
549    /**
550     *  Test that mode changes accurately reflect the value for isWifiEnabled.
551     */
552    @Test
553    public void checkIsWifiEnabledForModeChanges() throws Exception {
554        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
555
556        // Check initial state
557        mLooper.dispatchAll();
558        assertEquals("InitialState", getCurrentState().getName());
559        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
560
561        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
562        startSupplicantAndDispatchMessages();
563        mWsm.setSupplicantRunning(true);
564        mLooper.dispatchAll();
565        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
566        assertEquals("ScanModeState", getCurrentState().getName());
567        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
568
569        // switch to connect mode and verify wifi is reported as enabled
570        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
571        mLooper.dispatchAll();
572        assertEquals("DisconnectedState", getCurrentState().getName());
573        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
574        assertEquals(WifiManager.WIFI_STATE_ENABLED, mWsm.syncGetWifiState());
575
576        // now go back to scan mode with "wifi disabled" to verify the reported wifi state.
577        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
578        mLooper.dispatchAll();
579        assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
580                     mWsm.getOperationalModeForTest());
581        assertEquals("ScanModeState", getCurrentState().getName());
582        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
583
584        // now go to AP mode
585        mWsm.setSupplicantRunning(false);
586        mWsm.sendMessage(WifiStateMachine.CMD_DISABLE_P2P_RSP);
587        mWsm.sendMessage(WifiMonitor.SUP_DISCONNECTION_EVENT);
588        mWsm.setHostApRunning(new WifiConfiguration(), true);
589        mLooper.dispatchAll();
590        assertEquals("SoftApState", getCurrentState().getName());
591        assertEquals(WifiManager.WIFI_STATE_DISABLED, mWsm.syncGetWifiState());
592    }
593
594
595    /**
596     * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
597     * is started.
598     */
599    @Test
600    public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
601        when(mWifiNative.startHal(anyBoolean())).thenReturn(true);
602
603        // Check initial state
604        mLooper.dispatchAll();
605        assertEquals("InitialState", getCurrentState().getName());
606        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
607
608        // Update the mode
609        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
610        mLooper.dispatchAll();
611        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
612
613        // Start supplicant so we move to the next state
614        startSupplicantAndDispatchMessages();
615
616        assertEquals("ScanModeState", getCurrentState().getName());
617    }
618
619    /**
620     * Verifies that configs can be removed when in client mode.
621     */
622    @Test
623    public void canRemoveNetworkConfigInClientMode() throws Exception {
624        boolean result;
625        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
626        addNetworkAndVerifySuccess();
627        mLooper.startAutoDispatch();
628        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
629        mLooper.stopAutoDispatch();
630        assertTrue(result);
631    }
632
633    /**
634     * Verifies that configs can be removed when not in client mode.
635     */
636    @Test
637    public void canRemoveNetworkConfigWhenWifiDisabled() {
638        boolean result;
639        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
640        mLooper.startAutoDispatch();
641        result = mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0);
642        mLooper.stopAutoDispatch();
643
644        assertTrue(result);
645        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
646    }
647
648    /**
649     * Verifies that configs can be forgotten when in client mode.
650     */
651    @Test
652    public void canForgetNetworkConfigInClientMode() throws Exception {
653        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
654        addNetworkAndVerifySuccess();
655        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
656        mLooper.dispatchAll();
657        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
658    }
659
660    /**
661     * Verifies that configs can be removed when not in client mode.
662     */
663    @Test
664    public void canForgetNetworkConfigWhenWifiDisabled() throws Exception {
665        when(mWifiConfigManager.removeNetwork(eq(0), anyInt())).thenReturn(true);
666        mWsm.sendMessage(WifiManager.FORGET_NETWORK, 0, MANAGED_PROFILE_UID);
667        mLooper.dispatchAll();
668        verify(mWifiConfigManager).removeNetwork(anyInt(), anyInt());
669    }
670
671    /**
672     * Helper method to move through SupplicantStarting and SupplicantStarted states.
673     */
674    private void startSupplicantAndDispatchMessages() throws Exception {
675        mWsm.setSupplicantRunning(true);
676        mLooper.dispatchAll();
677
678        assertEquals("SupplicantStartingState", getCurrentState().getName());
679
680        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
681        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
682        when(mWifiNative.setModelName(anyString())).thenReturn(true);
683        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
684        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
685        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
686        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
687        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
688        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
689
690        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
691        mLooper.dispatchAll();
692    }
693
694    private void addNetworkAndVerifySuccess() throws Exception {
695        addNetworkAndVerifySuccess(false);
696    }
697
698    private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception {
699        loadComponentsInStaMode();
700
701        WifiConfiguration config = new WifiConfiguration();
702        config.SSID = sSSID;
703        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
704        config.hiddenSSID = isHidden;
705
706        when(mWifiConfigManager.addOrUpdateNetwork(any(WifiConfiguration.class), anyInt()))
707                .thenReturn(new NetworkUpdateResult(0));
708        when(mWifiConfigManager.getSavedNetworks()).thenReturn(Arrays.asList(config));
709        when(mWifiConfigManager.getConfiguredNetwork(0)).thenReturn(config);
710
711        mLooper.startAutoDispatch();
712        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
713        mLooper.stopAutoDispatch();
714
715        verify(mWifiConfigManager).addOrUpdateNetwork(eq(config), anyInt());
716
717        mLooper.startAutoDispatch();
718        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
719        mLooper.stopAutoDispatch();
720        assertEquals(1, configs.size());
721
722        WifiConfiguration config2 = configs.get(0);
723        assertEquals("\"GoogleGuest\"", config2.SSID);
724        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
725    }
726
727    /**
728     * Helper method to retrieve WifiConfiguration by SSID.
729     *
730     * Returns the associated WifiConfiguration if it is found, null otherwise.
731     */
732    private WifiConfiguration getWifiConfigurationForNetwork(String ssid) {
733        mLooper.startAutoDispatch();
734        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
735        mLooper.stopAutoDispatch();
736
737        for (WifiConfiguration checkConfig : configs) {
738            if (checkConfig.SSID.equals(ssid)) {
739                return checkConfig;
740            }
741        }
742        return null;
743    }
744
745    private void verifyScan(int band, int reportEvents, Set<String> hiddenNetworkSSIDSet) {
746        ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
747                ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
748        ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
749                ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
750        verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(),
751                eq(null));
752        WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue();
753        assertEquals("band", band, actualSettings.band);
754        assertEquals("reportEvents", reportEvents, actualSettings.reportEvents);
755
756        if (hiddenNetworkSSIDSet == null) {
757            hiddenNetworkSSIDSet = new HashSet<>();
758        }
759        Set<String> actualHiddenNetworkSSIDSet = new HashSet<>();
760        if (actualSettings.hiddenNetworks != null) {
761            for (int i = 0; i < actualSettings.hiddenNetworks.length; ++i) {
762                actualHiddenNetworkSSIDSet.add(actualSettings.hiddenNetworks[i].ssid);
763            }
764        }
765        assertEquals("hidden networks", hiddenNetworkSSIDSet, actualHiddenNetworkSSIDSet);
766
767        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
768        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
769
770        mLooper.dispatchAll();
771
772        List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
773        assertEquals(8, reportedResults.size());
774    }
775
776    @Test
777    public void scan() throws Exception {
778        addNetworkAndVerifySuccess();
779
780        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
781        mWsm.startScan(-1, 0, null, null);
782        mLooper.dispatchAll();
783
784        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
785                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
786                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null);
787    }
788
789    @Test
790    public void scanWithHiddenNetwork() throws Exception {
791        addNetworkAndVerifySuccess(true);
792
793        Set<String> hiddenNetworkSet = new HashSet<>();
794        hiddenNetworkSet.add(sSSID);
795        List<WifiScanner.ScanSettings.HiddenNetwork> hiddenNetworkList = new ArrayList<>();
796        hiddenNetworkList.add(new WifiScanner.ScanSettings.HiddenNetwork(sSSID));
797        when(mWifiConfigManager.retrieveHiddenNetworkList()).thenReturn(hiddenNetworkList);
798
799        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
800        mWsm.startScan(-1, 0, null, null);
801        mLooper.dispatchAll();
802
803        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
804                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
805                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
806                hiddenNetworkSet);
807    }
808
809    @Test
810    public void connect() throws Exception {
811        addNetworkAndVerifySuccess();
812
813        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
814        mLooper.dispatchAll();
815
816        mLooper.startAutoDispatch();
817        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
818        mLooper.stopAutoDispatch();
819
820        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
821
822        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
823        mLooper.dispatchAll();
824
825        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
826                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
827        mLooper.dispatchAll();
828
829        assertEquals("ObtainingIpState", getCurrentState().getName());
830
831        DhcpResults dhcpResults = new DhcpResults();
832        dhcpResults.setGateway("1.2.3.4");
833        dhcpResults.setIpAddress("192.168.1.100", 0);
834        dhcpResults.addDns("8.8.8.8");
835        dhcpResults.setLeaseDuration(3600);
836
837        mTestIpManager.injectDhcpSuccess(dhcpResults);
838        mLooper.dispatchAll();
839
840        assertEquals("ConnectedState", getCurrentState().getName());
841    }
842
843    /**
844     * If caller tries to connect to a network that is already connected, the connection request
845     * should succeed.
846     *
847     * Test: Create and connect to a network, then try to reconnect to the same network. Verify
848     * that connection request returns with CONNECT_NETWORK_SUCCEEDED.
849     */
850    @Test
851    public void reconnectToConnectedNetwork() throws Exception {
852        addNetworkAndVerifySuccess();
853
854        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
855        mLooper.dispatchAll();
856
857        mLooper.startAutoDispatch();
858        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
859        mLooper.stopAutoDispatch();
860
861        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
862
863        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
864        mLooper.dispatchAll();
865
866        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
867                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
868        mLooper.dispatchAll();
869
870        assertEquals("ObtainingIpState", getCurrentState().getName());
871
872        // try to reconnect
873        mLooper.startAutoDispatch();
874        Message reply = mWsmAsyncChannel.sendMessageSynchronously(WifiManager.CONNECT_NETWORK, 0);
875        mLooper.stopAutoDispatch();
876
877        assertEquals(WifiManager.CONNECT_NETWORK_SUCCEEDED, reply.what);
878    }
879
880    @Test
881    public void testDhcpFailure() throws Exception {
882        addNetworkAndVerifySuccess();
883
884        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
885        mLooper.dispatchAll();
886
887        mLooper.startAutoDispatch();
888        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
889        mLooper.stopAutoDispatch();
890
891        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
892
893        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
894        mLooper.dispatchAll();
895
896        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
897                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
898        mLooper.dispatchAll();
899
900        assertEquals("ObtainingIpState", getCurrentState().getName());
901
902        mTestIpManager.injectDhcpFailure();
903        mLooper.dispatchAll();
904
905        assertEquals("DisconnectingState", getCurrentState().getName());
906    }
907
908    @Test
909    public void testBadNetworkEvent() throws Exception {
910        addNetworkAndVerifySuccess();
911
912        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
913        mLooper.dispatchAll();
914
915        mLooper.startAutoDispatch();
916        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
917        mLooper.stopAutoDispatch();
918
919        verify(mWifiConfigManager).enableNetwork(eq(0), eq(true), anyInt());
920
921        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
922        mLooper.dispatchAll();
923
924        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
925                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
926        mLooper.dispatchAll();
927
928        assertEquals("DisconnectedState", getCurrentState().getName());
929    }
930
931
932    @Test
933    public void smToString() throws Exception {
934        assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString(
935                AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
936        assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString(
937                DhcpClient.CMD_PRE_DHCP_ACTION));
938        assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString(
939                WifiStateMachine.CMD_IP_REACHABILITY_LOST));
940    }
941
942    @Test
943    public void disconnect() throws Exception {
944        connect();
945
946        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
947        mLooper.dispatchAll();
948        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
949                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
950        mLooper.dispatchAll();
951
952        assertEquals("DisconnectedState", getCurrentState().getName());
953    }
954
955    /**
956     * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
957     * to true.
958     *
959     * Test: Successfully create and connect to a network. Check the config and verify
960     * WifiConfiguration.getHasEverConnected() is true.
961     */
962    @Test
963    public void setHasEverConnectedTrueOnConnect() throws Exception {
964        connect();
965        verify(mWifiConfigManager, atLeastOnce()).updateNetworkAfterConnect(0);
966    }
967
968    /**
969     * Fail network connection attempt and verify HasEverConnected remains false.
970     *
971     * Test: Successfully create a network but fail when connecting. Check the config and verify
972     * WifiConfiguration.getHasEverConnected() is false.
973     */
974    @Test
975    public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
976        testDhcpFailure();
977        verify(mWifiConfigManager, never()).updateNetworkAfterConnect(0);
978    }
979
980    @Test
981    public void iconQueryTest() throws Exception {
982        // TODO(b/31065385): Passpoint config management.
983    }
984
985    @Test
986    public void verboseLogRecSizeIsGreaterThanNormalSize() {
987        assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL);
988    }
989
990    /**
991     * Verifies that, by default, we allow only the "normal" number of log records.
992     */
993    @Test
994    public void normalLogRecSizeIsUsedByDefault() {
995        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
996    }
997
998    /**
999     * Verifies that, in verbose mode, we allow a larger number of log records.
1000     */
1001    @Test
1002    public void enablingVerboseLoggingUpdatesLogRecSize() {
1003        mWsm.enableVerboseLogging(1);
1004        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecMaxSize());
1005    }
1006
1007    @Test
1008    public void disablingVerboseLoggingClearsRecords() {
1009        mWsm.sendMessage(WifiStateMachine.CMD_DISCONNECT);
1010        mLooper.dispatchAll();
1011        assertTrue(mWsm.getLogRecSize() >= 1);
1012
1013        mWsm.enableVerboseLogging(0);
1014        assertEquals(0, mWsm.getLogRecSize());
1015    }
1016
1017    @Test
1018    public void disablingVerboseLoggingUpdatesLogRecSize() {
1019        mWsm.enableVerboseLogging(1);
1020        mWsm.enableVerboseLogging(0);
1021        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecMaxSize());
1022    }
1023
1024    /** Verifies that enabling verbose logging sets the hal log property in eng builds. */
1025    @Test
1026    public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() {
1027        reset(mPropertyService);  // Ignore calls made in setUp()
1028        when(mBuildProperties.isEngBuild()).thenReturn(true);
1029        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1030        when(mBuildProperties.isUserBuild()).thenReturn(false);
1031        mWsm.enableVerboseLogging(1);
1032        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1033    }
1034
1035    /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */
1036    @Test
1037    public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() {
1038        reset(mPropertyService);  // Ignore calls made in setUp()
1039        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
1040        when(mBuildProperties.isEngBuild()).thenReturn(false);
1041        when(mBuildProperties.isUserBuild()).thenReturn(false);
1042        mWsm.enableVerboseLogging(1);
1043        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1044    }
1045
1046    /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */
1047    @Test
1048    public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() {
1049        reset(mPropertyService);  // Ignore calls made in setUp()
1050        when(mBuildProperties.isUserBuild()).thenReturn(true);
1051        when(mBuildProperties.isEngBuild()).thenReturn(false);
1052        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1053        mWsm.enableVerboseLogging(1);
1054        verify(mPropertyService, never()).set(anyString(), anyString());
1055    }
1056
1057    private int testGetSupportedFeaturesCase(int supportedFeatures, boolean rttConfigured) {
1058        AsyncChannel channel = mock(AsyncChannel.class);
1059        Message reply = Message.obtain();
1060        reply.arg1 = supportedFeatures;
1061        reset(mPropertyService);  // Ignore calls made in setUp()
1062        when(channel.sendMessageSynchronously(WifiStateMachine.CMD_GET_SUPPORTED_FEATURES))
1063                .thenReturn(reply);
1064        when(mPropertyService.getBoolean("config.disable_rtt", false))
1065                .thenReturn(rttConfigured);
1066        return mWsm.syncGetSupportedFeatures(channel);
1067    }
1068
1069    /** Verifies that syncGetSupportedFeatures() masks out capabilities based on system flags. */
1070    @Test
1071    public void syncGetSupportedFeatures() {
1072        final int featureAware = WifiManager.WIFI_FEATURE_AWARE;
1073        final int featureInfra = WifiManager.WIFI_FEATURE_INFRA;
1074        final int featureD2dRtt = WifiManager.WIFI_FEATURE_D2D_RTT;
1075        final int featureD2apRtt = WifiManager.WIFI_FEATURE_D2AP_RTT;
1076
1077        assertEquals(0, testGetSupportedFeaturesCase(0, false));
1078        assertEquals(0, testGetSupportedFeaturesCase(0, true));
1079        assertEquals(featureAware | featureInfra,
1080                testGetSupportedFeaturesCase(featureAware | featureInfra, false));
1081        assertEquals(featureAware | featureInfra,
1082                testGetSupportedFeaturesCase(featureAware | featureInfra, true));
1083        assertEquals(featureInfra | featureD2dRtt,
1084                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, false));
1085        assertEquals(featureInfra,
1086                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt, true));
1087        assertEquals(featureInfra | featureD2apRtt,
1088                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, false));
1089        assertEquals(featureInfra,
1090                testGetSupportedFeaturesCase(featureInfra | featureD2apRtt, true));
1091        assertEquals(featureInfra | featureD2dRtt | featureD2apRtt,
1092                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, false));
1093        assertEquals(featureInfra,
1094                testGetSupportedFeaturesCase(featureInfra | featureD2dRtt | featureD2apRtt, true));
1095    }
1096
1097    /**
1098     * Verify that syncAddOrUpdatePasspointConfig will redirect calls to {@link PasspointManager}
1099     * and returning the result that's returned from {@link PasspointManager}.
1100     */
1101    @Test
1102    public void syncAddOrUpdatePasspointConfig() throws Exception {
1103        when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class)))
1104                .thenReturn(true);
1105        mLooper.startAutoDispatch();
1106        assertTrue(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel,
1107                new PasspointConfiguration()));
1108        mLooper.stopAutoDispatch();
1109        reset(mPasspointManager);
1110
1111        when(mPasspointManager.addOrUpdateProvider(any(PasspointConfiguration.class)))
1112                .thenReturn(false);
1113        mLooper.startAutoDispatch();
1114        assertFalse(mWsm.syncAddOrUpdatePasspointConfig(mWsmAsyncChannel,
1115                new PasspointConfiguration()));
1116        mLooper.stopAutoDispatch();
1117    }
1118
1119    /**
1120     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
1121     * and returning the result that's returned from {@link PasspointManager}.
1122     */
1123    @Test
1124    public void syncRemovePasspointConfig() throws Exception {
1125        String fqdn = "test.com";
1126        when(mPasspointManager.removeProvider(fqdn)).thenReturn(true);
1127        mLooper.startAutoDispatch();
1128        assertTrue(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
1129        mLooper.stopAutoDispatch();
1130        reset(mPasspointManager);
1131
1132        when(mPasspointManager.removeProvider(fqdn)).thenReturn(false);
1133        mLooper.startAutoDispatch();
1134        assertFalse(mWsm.syncRemovePasspointConfig(mWsmAsyncChannel, fqdn));
1135        mLooper.stopAutoDispatch();
1136    }
1137
1138    /**
1139     * Verify that syncRemovePasspointConfig will redirect calls to {@link PasspointManager}
1140     * and returning the result that's returned from {@link PasspointManager} when in client mode.
1141     */
1142    @Test
1143    public void syncRemovePasspointConfigInClientMode() throws Exception {
1144        loadComponentsInStaMode();
1145        syncRemovePasspointConfig();
1146    }
1147
1148    /**
1149     * Verify that syncGetPasspointConfigs will redirect calls to {@link PasspointManager}
1150     * and returning the result that's returned from {@link PasspointManager}.
1151     */
1152    @Test
1153    public void syncGetPasspointConfigs() throws Exception {
1154        // Setup expected configs.
1155        List<PasspointConfiguration> expectedConfigs = new ArrayList<>();
1156        PasspointConfiguration config = new PasspointConfiguration();
1157        HomeSp homeSp = new HomeSp();
1158        homeSp.setFqdn("test.com");
1159        config.setHomeSp(homeSp);
1160        expectedConfigs.add(config);
1161
1162        when(mPasspointManager.getProviderConfigs()).thenReturn(expectedConfigs);
1163        mLooper.startAutoDispatch();
1164        assertEquals(expectedConfigs, mWsm.syncGetPasspointConfigs(mWsmAsyncChannel));
1165        mLooper.stopAutoDispatch();
1166        reset(mPasspointManager);
1167
1168        when(mPasspointManager.getProviderConfigs())
1169                .thenReturn(new ArrayList<PasspointConfiguration>());
1170        mLooper.startAutoDispatch();
1171        assertTrue(mWsm.syncGetPasspointConfigs(mWsmAsyncChannel).isEmpty());
1172        mLooper.stopAutoDispatch();
1173    }
1174}
1175