WifiStateMachineTest.java revision 0fb9cf43830d67894b519c9a6271320c4842a5c0
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.any;
23import static org.mockito.Mockito.anyBoolean;
24import static org.mockito.Mockito.anyInt;
25import static org.mockito.Mockito.anyObject;
26import static org.mockito.Mockito.anyString;
27import static org.mockito.Mockito.eq;
28import static org.mockito.Mockito.mock;
29import static org.mockito.Mockito.never;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32import static org.mockito.Mockito.withSettings;
33
34import android.content.ContentResolver;
35import android.content.Context;
36import android.content.pm.PackageManager;
37import android.content.pm.UserInfo;
38import android.content.res.Resources;
39import android.net.ConnectivityManager;
40import android.net.DhcpResults;
41import android.net.LinkProperties;
42import android.net.ip.IpManager;
43import android.net.wifi.ScanResult;
44import android.net.wifi.SupplicantState;
45import android.net.wifi.WifiConfiguration;
46import android.net.wifi.WifiManager;
47import android.net.wifi.WifiSsid;
48import android.net.wifi.p2p.IWifiP2pManager;
49import android.os.BatteryStats;
50import android.os.Binder;
51import android.os.Handler;
52import android.os.HandlerThread;
53import android.os.IBinder;
54import android.os.IInterface;
55import android.os.INetworkManagementService;
56import android.os.IPowerManager;
57import android.os.Looper;
58import android.os.Message;
59import android.os.Messenger;
60import android.os.PowerManager;
61import android.os.UserHandle;
62import android.os.UserManager;
63import android.provider.Settings;
64import android.test.suitebuilder.annotation.SmallTest;
65import android.util.Log;
66
67import com.android.internal.R;
68import com.android.internal.app.IBatteryStats;
69import com.android.internal.util.AsyncChannel;
70import com.android.internal.util.IState;
71import com.android.internal.util.StateMachine;
72import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
73import com.android.server.wifi.hotspot2.NetworkDetail;
74import com.android.server.wifi.hotspot2.Utils;
75import com.android.server.wifi.p2p.WifiP2pServiceImpl;
76
77import org.junit.After;
78import org.junit.Before;
79import org.junit.Test;
80import org.mockito.Mock;
81import org.mockito.Mockito;
82import org.mockito.MockitoAnnotations;
83
84import java.io.ByteArrayOutputStream;
85import java.io.PrintWriter;
86import java.lang.reflect.Field;
87import java.lang.reflect.InvocationTargetException;
88import java.lang.reflect.Method;
89import java.util.ArrayList;
90import java.util.Arrays;
91import java.util.HashMap;
92import java.util.List;
93import java.util.Map;
94
95/**
96 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
97 */
98@SmallTest
99public class WifiStateMachineTest {
100    public static final String TAG = "WifiStateMachineTest";
101
102    private static final int MANAGED_PROFILE_UID = 1100000;
103    private static final int OTHER_USER_UID = 1200000;
104
105    private long mBinderToken;
106
107    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
108        return mock(class1, withSettings().extraInterfaces(interfaces));
109    }
110
111    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
112        T tImpl = mockWithInterfaces(class1, iface);
113        IBinder binder = mock(IBinder.class);
114        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
115        when(binder.queryLocalInterface(iface.getCanonicalName()))
116                .thenReturn((IInterface) tImpl);
117        return binder;
118    }
119
120    private void enableDebugLogs() {
121        mWsm.enableVerboseLogging(1);
122    }
123
124    private class TestIpManager extends IpManager {
125        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
126            // Call test-only superclass constructor.
127            super(ifname, callback);
128        }
129
130        @Override
131        public void startProvisioning() {}
132
133        @Override
134        public void stop() {}
135
136        @Override
137        public void confirmConfiguration() {}
138
139        void injectDhcpSuccess(DhcpResults dhcpResults) {
140            mCallback.onNewDhcpResults(dhcpResults);
141            mCallback.onProvisioningSuccess(new LinkProperties());
142        }
143
144        void injectDhcpFailure() {
145            mCallback.onNewDhcpResults(null);
146            mCallback.onProvisioningFailure(new LinkProperties());
147        }
148    }
149
150    private FrameworkFacade getFrameworkFacade() throws Exception {
151        FrameworkFacade facade = mock(FrameworkFacade.class);
152
153        when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class));
154        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
155                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
156
157        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
158        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
159
160        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
161                IWifiP2pManager.class.getCanonicalName());
162
163        final Object sync = new Object();
164        synchronized (sync) {
165            mP2pThread = new HandlerThread("WifiP2pMockThread") {
166                @Override
167                protected void onLooperPrepared() {
168                    synchronized (sync) {
169                        sync.notifyAll();
170                    }
171                }
172            };
173
174            mP2pThread.start();
175            sync.wait();
176        }
177
178        Handler handler = new Handler(mP2pThread.getLooper());
179        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
180
181        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
182        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);
183
184        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
185                .then(new AnswerWithArguments() {
186                    public IpManager answer(
187                            Context context, String ifname, IpManager.Callback callback) {
188                        mTestIpManager = new TestIpManager(context, ifname, callback);
189                        return mTestIpManager;
190                    }
191                });
192
193        when(facade.checkUidPermission(eq(android.Manifest.permission.OVERRIDE_WIFI_CONFIG),
194                anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
195
196        return facade;
197    }
198
199    private Context getContext() throws Exception {
200        PackageManager pkgMgr = mock(PackageManager.class);
201        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
202
203        Context context = mock(Context.class);
204        when(context.getPackageManager()).thenReturn(pkgMgr);
205        when(context.getContentResolver()).thenReturn(mock(ContentResolver.class));
206
207        MockResources resources = new com.android.server.wifi.MockResources();
208        when(context.getResources()).thenReturn(resources);
209
210        ContentResolver cr = mock(ContentResolver.class);
211        when(context.getContentResolver()).thenReturn(cr);
212
213        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
214                new PowerManager(context, mock(IPowerManager.class), new Handler()));
215
216        mAlarmManager = new MockAlarmManager();
217        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
218                mAlarmManager.getAlarmManager());
219
220        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
221                mock(ConnectivityManager.class));
222
223        return context;
224    }
225
226    private Resources getMockResources() {
227        MockResources resources = new MockResources();
228        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
229        return resources;
230    }
231
232    private IState getCurrentState() throws
233            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
234        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
235        method.setAccessible(true);
236        return (IState) method.invoke(mWsm);
237    }
238
239    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
240            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
241        Field field = StateMachine.class.getDeclaredField("mSmThread");
242        field.setAccessible(true);
243        return (HandlerThread) field.get(wsm);
244    }
245
246    private static void stopLooper(final Looper looper) throws Exception {
247        new Handler(looper).post(new Runnable() {
248            @Override
249            public void run() {
250                looper.quitSafely();
251            }
252        });
253    }
254
255    private void wait(int delayInMs) throws InterruptedException {
256        Looper looper = mWsmThread.getLooper();
257        final Handler handler = new Handler(looper);
258        synchronized (handler) {
259            handler.postDelayed(new Runnable() {
260                @Override
261                public void run() {
262                    synchronized (handler) {
263                        handler.notifyAll();
264                    }
265                }
266            }, delayInMs);
267
268            handler.wait();
269        }
270    }
271
272    private void dumpState() {
273        ByteArrayOutputStream stream = new ByteArrayOutputStream();
274        PrintWriter writer = new PrintWriter(stream);
275        mWsm.dump(null, writer, null);
276        writer.flush();
277        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
278    }
279
280    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
281        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
282        ie[0] = ScanResults.generateSsidIe(sSSID);
283        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
284        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
285                Long.MAX_VALUE, /* needed so that scan results aren't rejected because
286                                   there older than scan start */
287                null, null);
288        return detail;
289    }
290
291    private ArrayList<ScanDetail> getMockScanResults() {
292        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
293        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
294
295        int rssi = -65;
296        list.add(getGoogleGuestScanDetail(rssi));
297        return list;
298    }
299
300    static final String   sSSID = "\"GoogleGuest\"";
301    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
302    static final String   sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
303    static final String   sBSSID = "01:02:03:04:05:06";
304    static final int      sFreq = 2437;
305
306    WifiStateMachine mWsm;
307    HandlerThread mWsmThread;
308    HandlerThread mP2pThread;
309    HandlerThread mSyncThread;
310    AsyncChannel  mWsmAsyncChannel;
311    MockAlarmManager mAlarmManager;
312    MockWifiMonitor mWifiMonitor;
313    TestIpManager mTestIpManager;
314
315    @Mock WifiNative mWifiNative;
316    @Mock SupplicantStateTracker mSupplicantStateTracker;
317    @Mock WifiMetrics mWifiMetrics;
318    @Mock UserManager mUserManager;
319
320    public WifiStateMachineTest() throws Exception {
321    }
322
323    @Before
324    public void setUp() throws Exception {
325        Log.d(TAG, "Setting up ...");
326
327        // Ensure looper exists
328        MockLooper looper = new MockLooper();
329
330        MockitoAnnotations.initMocks(this);
331
332        /** uncomment this to enable logs from WifiStateMachines */
333        // enableDebugLogs();
334
335        TestUtil.installWlanWifiNative(mWifiNative);
336        mWifiMonitor = new MockWifiMonitor();
337        mWifiMetrics = mock(WifiMetrics.class);
338        FrameworkFacade factory = getFrameworkFacade();
339        Context context = getContext();
340
341        Resources resources = getMockResources();
342        when(context.getResources()).thenReturn(resources);
343
344        when(factory.getIntegerSetting(context,
345                Settings.Global.WIFI_FREQUENCY_BAND,
346                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
347                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
348
349        when(factory.makeApConfigStore(Mockito.eq(context)))
350                .thenCallRealMethod();
351
352        when(factory.makeSupplicantStateTracker(
353                any(Context.class), any(WifiStateMachine.class), any(WifiConfigStore.class),
354                any(Handler.class))).thenReturn(mSupplicantStateTracker);
355
356        when(mUserManager.getProfileParent(11))
357                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
358        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
359                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
360                new UserInfo(11, "managed profile", 0)));
361
362        mWsm = new WifiStateMachine(context, null, factory, mWifiMetrics, mUserManager);
363        mWsmThread = getWsmHandlerThread(mWsm);
364
365        final Object sync = new Object();
366        synchronized (sync) {
367            mSyncThread = new HandlerThread("SynchronizationThread");
368            final AsyncChannel channel = new AsyncChannel();
369            mSyncThread.start();
370            Handler handler = new Handler(mSyncThread.getLooper()) {
371                @Override
372                public void handleMessage(Message msg) {
373                    switch (msg.what) {
374                        case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
375                            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
376                                mWsmAsyncChannel = channel;
377                                synchronized (sync) {
378                                    sync.notifyAll();
379                                    Log.d(TAG, "Successfully connected " + this);
380                                }
381                            } else {
382                                Log.d(TAG, "Failed to connect Command channel " + this);
383                            }
384                            break;
385                        case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
386                            Log.d(TAG, "Command channel disconnected" + this);
387                            break;
388                    }
389                }
390            };
391
392            channel.connect(context, handler, mWsm.getMessenger());
393            sync.wait();
394        }
395
396        /* Now channel is supposed to be connected */
397
398        mBinderToken = Binder.clearCallingIdentity();
399    }
400
401    @After
402    public void cleanUp() throws Exception {
403        Binder.restoreCallingIdentity(mBinderToken);
404
405        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
406        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
407        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
408
409        mWsmThread = null;
410        mP2pThread = null;
411        mSyncThread = null;
412        mWsmAsyncChannel = null;
413        mWsm = null;
414    }
415
416    @Test
417    public void createNew() throws Exception {
418        assertEquals("InitialState", getCurrentState().getName());
419
420        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
421        wait(200);
422        assertEquals("InitialState", getCurrentState().getName());
423    }
424
425    @Test
426    public void loadComponents() throws Exception {
427
428        when(mWifiNative.loadDriver()).thenReturn(true);
429        when(mWifiNative.startHal()).thenReturn(true);
430        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
431
432        mWsm.setSupplicantRunning(true);
433        wait(200);
434        assertEquals("SupplicantStartingState", getCurrentState().getName());
435
436        when(mWifiNative.setBand(anyInt())).thenReturn(true);
437        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
438        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
439        when(mWifiNative.setModelName(anyString())).thenReturn(true);
440        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
441        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
442        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
443        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
444        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
445        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
446        when(mWifiNative.enableBackgroundScan(anyBoolean(),
447                any(ArrayList.class))).thenReturn(true);
448
449        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
450        wait(200);
451        assertEquals("DisconnectedState", getCurrentState().getName());
452    }
453
454    @Test
455    public void loadComponentsFailure() throws Exception {
456        when(mWifiNative.loadDriver()).thenReturn(false);
457        when(mWifiNative.startHal()).thenReturn(false);
458        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false);
459
460        mWsm.setSupplicantRunning(true);
461        wait(200);
462        assertEquals("InitialState", getCurrentState().getName());
463
464        when(mWifiNative.loadDriver()).thenReturn(true);
465        mWsm.setSupplicantRunning(true);
466        wait(200);
467        assertEquals("InitialState", getCurrentState().getName());
468
469        when(mWifiNative.startHal()).thenReturn(true);
470        mWsm.setSupplicantRunning(true);
471        wait(200);
472        assertEquals("InitialState", getCurrentState().getName());
473    }
474
475    private void addNetworkAndVerifySuccess() throws Exception {
476
477        loadComponents();
478
479        final HashMap<String, String> nameToValue = new HashMap<String, String>();
480
481        when(mWifiNative.addNetwork()).thenReturn(0);
482        when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString()))
483                .then(new AnswerWithArguments() {
484                    public boolean answer(int netId, String name, String value) {
485                        if (netId != 0) {
486                            Log.d(TAG, "Can't set var " + name + " for " + netId);
487                            return false;
488                        }
489
490                        Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId);
491                        nameToValue.put(name, value);
492                        return true;
493                    }
494                });
495
496        when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject()))
497                .then(new AnswerWithArguments() {
498                    public boolean answer(int netId, String name, Map<String, String> values) {
499                        if (netId != 0) {
500                            Log.d(TAG, "Can't set extra " + name + " for " + netId);
501                            return false;
502                        }
503
504                        Log.d(TAG, "Setting extra for " + netId);
505                        return true;
506                    }
507                });
508
509        when(mWifiNative.getNetworkVariable(anyInt(), anyString()))
510                .then(new AnswerWithArguments() {
511                    public String answer(int netId, String name) throws Throwable {
512                        if (netId != 0) {
513                            Log.d(TAG, "Can't find var " + name + " for " + netId);
514                            return null;
515                        }
516                        String value = nameToValue.get(name);
517                        if (value != null) {
518                            Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId);
519                        } else {
520                            Log.d(TAG, "Can't find var " + name + " for " + netId);
521                        }
522                        return value;
523                    }
524                });
525
526        WifiConfiguration config = new WifiConfiguration();
527        config.SSID = sSSID;
528        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
529        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
530        wait(200);
531
532        verify(mWifiNative).addNetwork();
533        verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID);
534
535        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
536        assertEquals(1, configs.size());
537
538        WifiConfiguration config2 = configs.get(0);
539        assertEquals("\"GoogleGuest\"", config2.SSID);
540        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
541    }
542
543    private void addNetworkAndVerifyFailure() throws Exception {
544        loadComponents();
545
546        final WifiConfiguration config = new WifiConfiguration();
547        config.SSID = sSSID;
548        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
549
550        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
551        wait(200);
552
553        verify(mWifiNative, never()).addNetwork();
554        verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString());
555
556        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
557    }
558
559    /**
560     * Verifies that the current foreground user is allowed to add a network.
561     */
562    @Test
563    public void addNetworkAsCurrentUser() throws Exception {
564        addNetworkAndVerifySuccess();
565    }
566
567    /**
568     * Verifies that a managed profile of the current foreground user is allowed to add a network.
569     */
570    @Test
571    public void addNetworkAsCurrentUsersManagedProfile() throws Exception {
572        BinderUtil.setUid(MANAGED_PROFILE_UID);
573        addNetworkAndVerifySuccess();
574    }
575
576    /**
577     * Verifies that a background user is not allowed to add a network.
578     */
579    @Test
580    public void addNetworkAsOtherUser() throws Exception {
581        BinderUtil.setUid(OTHER_USER_UID);
582        addNetworkAndVerifyFailure();
583    }
584
585    private void removeNetworkAndVerifySuccess() throws Exception {
586        when(mWifiNative.removeNetwork(0)).thenReturn(true);
587        assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
588        wait(200);
589        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
590    }
591
592    private void removeNetworkAndVerifyFailure() throws Exception {
593        assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
594        wait(200);
595        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
596        verify(mWifiNative, never()).removeNetwork(anyInt());
597    }
598
599    /**
600     * Verifies that the current foreground user is allowed to remove a network.
601     */
602    @Test
603    public void removeNetworkAsCurrentUser() throws Exception {
604        addNetworkAndVerifySuccess();
605        removeNetworkAndVerifySuccess();
606    }
607
608    /**
609     * Verifies that a managed profile of the current foreground user is allowed to remove a
610     * network.
611     */
612    @Test
613    public void removeNetworkAsCurrentUsersManagedProfile() throws Exception {
614        addNetworkAndVerifySuccess();
615        BinderUtil.setUid(MANAGED_PROFILE_UID);
616        removeNetworkAndVerifySuccess();
617    }
618
619    /**
620     * Verifies that a background user is not allowed to remove a network.
621     */
622    @Test
623    public void removeNetworkAsOtherUser() throws Exception {
624        addNetworkAndVerifySuccess();
625        BinderUtil.setUid(OTHER_USER_UID);
626        removeNetworkAndVerifyFailure();
627    }
628
629    private void enableNetworkAndVerifySuccess() throws Exception {
630        when(mWifiNative.enableNetwork(0, true)).thenReturn(true);
631        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
632        wait(200);
633        verify(mWifiNative).enableNetwork(0, true);
634    }
635
636    private void enableNetworkAndVerifyFailure() throws Exception {
637        assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
638        wait(200);
639        verify(mWifiNative, never()).enableNetwork(anyInt(), anyBoolean());
640    }
641
642    /**
643     * Verifies that the current foreground user is allowed to enable a network.
644     */
645    @Test
646    public void enableNetworkAsCurrentUser() throws Exception {
647        addNetworkAndVerifySuccess();
648        enableNetworkAndVerifySuccess();
649    }
650
651    /**
652     * Verifies that a managed profile of the current foreground user is allowed to enable a
653     * network.
654     */
655    @Test
656    public void enableNetworkAsCurrentUsersManagedProfile() throws Exception {
657        addNetworkAndVerifySuccess();
658        BinderUtil.setUid(MANAGED_PROFILE_UID);
659        enableNetworkAndVerifySuccess();
660    }
661
662    /**
663     * Verifies that a background user is not allowed to enable a network.
664     */
665    @Test
666    public void enableNetworkAsOtherUser() throws Exception {
667        addNetworkAndVerifySuccess();
668        BinderUtil.setUid(OTHER_USER_UID);
669        enableNetworkAndVerifyFailure();
670    }
671
672    private void forgetNetworkAndVerifySuccess() throws Exception {
673        when(mWifiNative.removeNetwork(0)).thenReturn(true);
674        final Message result =
675                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
676        assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what);
677        result.recycle();
678        wait(200);
679        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
680    }
681
682    private void forgetNetworkAndVerifyFailure() throws Exception {
683        final Message result =
684                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
685        assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what);
686        result.recycle();
687        wait(200);
688        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
689        verify(mWifiNative, never()).removeNetwork(anyInt());
690    }
691
692    /**
693     * Verifies that the current foreground user is allowed to forget a network.
694     */
695    @Test
696    public void forgetNetworkAsCurrentUser() throws Exception {
697        addNetworkAndVerifySuccess();
698        forgetNetworkAndVerifySuccess();
699    }
700
701    /**
702     * Verifies that a managed profile of the current foreground user is allowed to forget a
703     * network.
704     */
705    @Test
706    public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception {
707        addNetworkAndVerifySuccess();
708        BinderUtil.setUid(MANAGED_PROFILE_UID);
709        forgetNetworkAndVerifySuccess();
710    }
711
712    /**
713     * Verifies that a background user is not allowed to forget a network.
714     */
715    @Test
716    public void forgetNetworkAsOtherUser() throws Exception {
717        addNetworkAndVerifySuccess();
718        BinderUtil.setUid(OTHER_USER_UID);
719        forgetNetworkAndVerifyFailure();
720    }
721
722    @Test
723    public void scan() throws Exception {
724
725        addNetworkAndVerifySuccess();
726
727        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
728
729        mWsm.startScan(-1, 0, null, null);
730        wait(200);
731
732        verify(mWifiNative).scan(null);
733
734        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
735        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
736
737        wait(200);
738        List<ScanResult> results = mWsm.syncGetScanResultsList();
739        assertEquals(8, results.size());
740    }
741
742    @Test
743    public void connect() throws Exception {
744
745        addNetworkAndVerifySuccess();
746
747        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
748        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
749        wait(200);
750
751        verify(mWifiNative).enableNetwork(0, true);
752
753        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
754        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
755                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
756        wait(200);
757
758        assertEquals("ObtainingIpState", getCurrentState().getName());
759
760        DhcpResults dhcpResults = new DhcpResults();
761        dhcpResults.setGateway("1.2.3.4");
762        dhcpResults.setIpAddress("192.168.1.100", 0);
763        dhcpResults.addDns("8.8.8.8");
764        dhcpResults.setLeaseDuration(3600);
765
766        mTestIpManager.injectDhcpSuccess(dhcpResults);
767        wait(200);
768
769        assertEquals("ConnectedState", getCurrentState().getName());
770    }
771
772    @Test
773    public void testDhcpFailure() throws Exception {
774        addNetworkAndVerifySuccess();
775
776        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
777        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
778        wait(200);
779
780        verify(mWifiNative).enableNetwork(0, true);
781
782        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
783
784        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
785                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
786        wait(200);
787
788        assertEquals("ObtainingIpState", getCurrentState().getName());
789
790        mTestIpManager.injectDhcpFailure();
791        wait(200);
792
793        assertEquals("DisconnectingState", getCurrentState().getName());
794    }
795
796    @Test
797    public void testBadNetworkEvent() throws Exception {
798        addNetworkAndVerifySuccess();
799
800        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
801        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
802        wait(200);
803
804        verify(mWifiNative).enableNetwork(0, true);
805
806        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
807
808        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
809                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
810        wait(200);
811
812        assertEquals("DisconnectedState", getCurrentState().getName());
813    }
814
815
816    @Test
817    public void disconnect() throws Exception {
818        connect();
819
820        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
821        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
822                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
823        wait(200);
824
825        assertEquals("DisconnectedState", getCurrentState().getName());
826    }
827
828    @Test
829    public void handleUserSwitch() throws Exception {
830        assertEquals(UserHandle.USER_SYSTEM, mWsm.getCurrentUserId());
831
832        mWsm.handleUserSwitch(10);
833        wait(200);
834
835        assertEquals(10, mWsm.getCurrentUserId());
836    }
837
838    @Test
839    public void iconQueryTest() throws Exception {
840        /* enable wi-fi */
841        addNetworkAndVerifySuccess();
842
843        long bssid = 0x1234567800FFL;
844        String filename = "iconFileName.png";
845        String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename;
846
847        when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK");
848
849        boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename);
850
851        verify(mWifiNative).doCustomSupplicantCommand(command);
852        assertEquals(true, result);
853    }
854}
855