WifiStateMachineTest.java revision 173dae04272c1b40488292f6392a922b4c4b2949
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.content.ContentResolver;
26import android.content.Context;
27import android.content.pm.PackageManager;
28import android.content.pm.UserInfo;
29import android.content.res.Resources;
30import android.net.ConnectivityManager;
31import android.net.DhcpResults;
32import android.net.LinkProperties;
33import android.net.dhcp.DhcpClient;
34import android.net.ip.IpManager;
35import android.net.wifi.ScanResult;
36import android.net.wifi.SupplicantState;
37import android.net.wifi.WifiConfiguration;
38import android.net.wifi.WifiManager;
39import android.net.wifi.WifiScanner;
40import android.net.wifi.WifiSsid;
41import android.net.wifi.p2p.IWifiP2pManager;
42import android.os.BatteryStats;
43import android.os.Binder;
44import android.os.Handler;
45import android.os.HandlerThread;
46import android.os.IBinder;
47import android.os.IInterface;
48import android.os.INetworkManagementService;
49import android.os.IPowerManager;
50import android.os.Looper;
51import android.os.Message;
52import android.os.Messenger;
53import android.os.PowerManager;
54import android.os.UserHandle;
55import android.os.UserManager;
56import android.provider.Settings;
57import android.security.KeyStore;
58import android.telephony.TelephonyManager;
59import android.test.suitebuilder.annotation.SmallTest;
60import android.util.Base64;
61import android.util.Log;
62
63import com.android.internal.R;
64import com.android.internal.app.IBatteryStats;
65import com.android.internal.util.AsyncChannel;
66import com.android.internal.util.IState;
67import com.android.internal.util.StateMachine;
68import com.android.server.wifi.MockAnswerUtil.AnswerWithArguments;
69import com.android.server.wifi.hotspot2.NetworkDetail;
70import com.android.server.wifi.hotspot2.Utils;
71import com.android.server.wifi.p2p.WifiP2pServiceImpl;
72
73import org.junit.After;
74import org.junit.Before;
75import org.junit.Test;
76import org.mockito.ArgumentCaptor;
77import org.mockito.Mock;
78import org.mockito.MockitoAnnotations;
79
80import java.io.ByteArrayOutputStream;
81import java.io.PrintWriter;
82import java.lang.reflect.Field;
83import java.lang.reflect.InvocationTargetException;
84import java.lang.reflect.Method;
85import java.util.ArrayList;
86import java.util.Arrays;
87import java.util.HashMap;
88import java.util.HashSet;
89import java.util.List;
90import java.util.Map;
91import java.util.Set;
92
93/**
94 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
95 */
96@SmallTest
97public class WifiStateMachineTest {
98    public static final String TAG = "WifiStateMachineTest";
99
100    private static final int MANAGED_PROFILE_UID = 1100000;
101    private static final int OTHER_USER_UID = 1200000;
102    private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
103            (ActivityManager.isLowRamDeviceStatic()
104                    ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
105                    : WifiStateMachine.NUM_LOG_RECS_VERBOSE);
106    private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
107
108    private long mBinderToken;
109
110    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
111        return mock(class1, withSettings().extraInterfaces(interfaces));
112    }
113
114    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
115        T tImpl = mockWithInterfaces(class1, iface);
116        IBinder binder = mock(IBinder.class);
117        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
118        when(binder.queryLocalInterface(iface.getCanonicalName()))
119                .thenReturn((IInterface) tImpl);
120        return binder;
121    }
122
123    private void enableDebugLogs() {
124        mWsm.enableVerboseLogging(1);
125    }
126
127    private class TestIpManager extends IpManager {
128        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
129            // Call dependency-injection superclass constructor.
130            super(context, ifname, callback, mock(INetworkManagementService.class));
131        }
132
133        @Override
134        public void startProvisioning(IpManager.ProvisioningConfiguration config) {}
135
136        @Override
137        public void stop() {}
138
139        @Override
140        public void confirmConfiguration() {}
141
142        void injectDhcpSuccess(DhcpResults dhcpResults) {
143            mCallback.onNewDhcpResults(dhcpResults);
144            mCallback.onProvisioningSuccess(new LinkProperties());
145        }
146
147        void injectDhcpFailure() {
148            mCallback.onNewDhcpResults(null);
149            mCallback.onProvisioningFailure(new LinkProperties());
150        }
151    }
152
153    private FrameworkFacade getFrameworkFacade() throws Exception {
154        FrameworkFacade facade = mock(FrameworkFacade.class);
155
156        when(facade.makeWifiScanner(any(Context.class), any(Looper.class)))
157                .thenReturn(mWifiScanner);
158        when(facade.makeBaseLogger()).thenReturn(mock(BaseWifiLogger.class));
159        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
160                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
161
162        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
163        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
164
165        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
166                IWifiP2pManager.class.getCanonicalName());
167
168        final Object sync = new Object();
169        synchronized (sync) {
170            mP2pThread = new HandlerThread("WifiP2pMockThread") {
171                @Override
172                protected void onLooperPrepared() {
173                    synchronized (sync) {
174                        sync.notifyAll();
175                    }
176                }
177            };
178
179            mP2pThread.start();
180            sync.wait();
181        }
182
183        Handler handler = new Handler(mP2pThread.getLooper());
184        when(p2pm.getP2pStateMachineMessenger()).thenReturn(new Messenger(handler));
185
186        IBinder batteryStatsBinder = mockService(BatteryStats.class, IBatteryStats.class);
187        when(facade.getService(BatteryStats.SERVICE_NAME)).thenReturn(batteryStatsBinder);
188
189        when(facade.makeIpManager(any(Context.class), anyString(), any(IpManager.Callback.class)))
190                .then(new AnswerWithArguments() {
191                    public IpManager answer(
192                            Context context, String ifname, IpManager.Callback callback) {
193                        mTestIpManager = new TestIpManager(context, ifname, callback);
194                        return mTestIpManager;
195                    }
196                });
197
198        when(facade.checkUidPermission(eq(android.Manifest.permission.OVERRIDE_WIFI_CONFIG),
199                anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
200
201        when(facade.makeWifiConfigManager(any(Context.class), any(WifiNative.class),
202                any(FrameworkFacade.class), any(Clock.class),
203                any(UserManager.class), any(KeyStore.class))).then(new AnswerWithArguments() {
204            public WifiConfigManager answer(Context context, WifiNative wifiNative,
205                    FrameworkFacade frameworkFacade, Clock clock,
206                    UserManager userManager, KeyStore keyStore){
207                mWifiConfigManager = new WifiConfigManager(context, wifiNative, frameworkFacade,
208                        clock, userManager, keyStore);
209                return mWifiConfigManager;
210            }
211        });
212        return facade;
213    }
214
215    private Context getContext() throws Exception {
216        PackageManager pkgMgr = mock(PackageManager.class);
217        when(pkgMgr.hasSystemFeature(PackageManager.FEATURE_WIFI_DIRECT)).thenReturn(true);
218
219        Context context = mock(Context.class);
220        when(context.getPackageManager()).thenReturn(pkgMgr);
221        when(context.getContentResolver()).thenReturn(mock(ContentResolver.class));
222
223        MockResources resources = new com.android.server.wifi.MockResources();
224        when(context.getResources()).thenReturn(resources);
225
226        ContentResolver cr = mock(ContentResolver.class);
227        when(context.getContentResolver()).thenReturn(cr);
228
229        when(context.getSystemService(Context.POWER_SERVICE)).thenReturn(
230                new PowerManager(context, mock(IPowerManager.class), new Handler()));
231
232        mAlarmManager = new MockAlarmManager();
233        when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(
234                mAlarmManager.getAlarmManager());
235
236        when(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(
237                mock(ConnectivityManager.class));
238
239        return context;
240    }
241
242    private Resources getMockResources() {
243        MockResources resources = new MockResources();
244        resources.setBoolean(R.bool.config_wifi_enable_wifi_firmware_debugging, false);
245        return resources;
246    }
247
248    private IState getCurrentState() throws
249            NoSuchMethodException, InvocationTargetException, IllegalAccessException {
250        Method method = StateMachine.class.getDeclaredMethod("getCurrentState");
251        method.setAccessible(true);
252        return (IState) method.invoke(mWsm);
253    }
254
255    private static HandlerThread getWsmHandlerThread(WifiStateMachine wsm) throws
256            NoSuchFieldException, InvocationTargetException, IllegalAccessException {
257        Field field = StateMachine.class.getDeclaredField("mSmThread");
258        field.setAccessible(true);
259        return (HandlerThread) field.get(wsm);
260    }
261
262    private static void stopLooper(final Looper looper) throws Exception {
263        new Handler(looper).post(new Runnable() {
264            @Override
265            public void run() {
266                looper.quitSafely();
267            }
268        });
269    }
270
271    private void dumpState() {
272        ByteArrayOutputStream stream = new ByteArrayOutputStream();
273        PrintWriter writer = new PrintWriter(stream);
274        mWsm.dump(null, writer, null);
275        writer.flush();
276        Log.d(TAG, "WifiStateMachine state -" + stream.toString());
277    }
278
279    private static ScanDetail getGoogleGuestScanDetail(int rssi) {
280        ScanResult.InformationElement ie[] = new ScanResult.InformationElement[1];
281        ie[0] = ScanResults.generateSsidIe(sSSID);
282        NetworkDetail nd = new NetworkDetail(sBSSID, ie, new ArrayList<String>(), sFreq);
283        ScanDetail detail = new ScanDetail(nd, sWifiSsid, sBSSID, "", rssi, sFreq,
284                Long.MAX_VALUE, /* needed so that scan results aren't rejected because
285                                   there older than scan start */
286                ie, new ArrayList<String>());
287        return detail;
288    }
289
290    private ArrayList<ScanDetail> getMockScanResults() {
291        ScanResults sr = ScanResults.create(0, 2412, 2437, 2462, 5180, 5220, 5745, 5825);
292        ArrayList<ScanDetail> list = sr.getScanDetailArrayList();
293
294        int rssi = -65;
295        list.add(getGoogleGuestScanDetail(rssi));
296        return list;
297    }
298
299    static final String   sSSID = "\"GoogleGuest\"";
300    static final WifiSsid sWifiSsid = WifiSsid.createFromAsciiEncoded(sSSID);
301    static final String   sHexSSID = sWifiSsid.getHexString().replace("0x", "").replace("22", "");
302    static final String   sBSSID = "01:02:03:04:05:06";
303    static final int      sFreq = 2437;
304
305    WifiStateMachine mWsm;
306    HandlerThread mWsmThread;
307    HandlerThread mP2pThread;
308    HandlerThread mSyncThread;
309    AsyncChannel  mWsmAsyncChannel;
310    MockAlarmManager mAlarmManager;
311    MockWifiMonitor mWifiMonitor;
312    TestIpManager mTestIpManager;
313    MockLooper mLooper;
314    WifiConfigManager mWifiConfigManager;
315
316    @Mock WifiNative mWifiNative;
317    @Mock WifiScanner mWifiScanner;
318    @Mock SupplicantStateTracker mSupplicantStateTracker;
319    @Mock WifiMetrics mWifiMetrics;
320    @Mock UserManager mUserManager;
321    @Mock WifiApConfigStore mApConfigStore;
322    @Mock BackupManagerProxy mBackupManagerProxy;
323    @Mock WifiCountryCode mCountryCode;
324    @Mock WifiInjector mWifiInjector;
325    @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
326    @Mock PropertyService mPropertyService;
327    @Mock BuildProperties mBuildProperties;
328
329    public WifiStateMachineTest() throws Exception {
330    }
331
332    @Before
333    public void setUp() throws Exception {
334        Log.d(TAG, "Setting up ...");
335
336        // Ensure looper exists
337        mLooper = new MockLooper();
338
339        MockitoAnnotations.initMocks(this);
340
341        /** uncomment this to enable logs from WifiStateMachines */
342        // enableDebugLogs();
343
344        TestUtil.installWlanWifiNative(mWifiNative);
345        mWifiMonitor = new MockWifiMonitor();
346        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
347        when(mWifiInjector.getClock()).thenReturn(mock(Clock.class));
348        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
349        when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
350        when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
351        when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
352        FrameworkFacade factory = getFrameworkFacade();
353        Context context = getContext();
354
355        Resources resources = getMockResources();
356        when(context.getResources()).thenReturn(resources);
357
358        when(factory.getIntegerSetting(context,
359                Settings.Global.WIFI_FREQUENCY_BAND,
360                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
361                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
362
363        when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy)))
364                .thenReturn(mApConfigStore);
365
366        when(factory.makeSupplicantStateTracker(
367                any(Context.class), any(WifiConfigManager.class),
368                any(Handler.class))).thenReturn(mSupplicantStateTracker);
369
370        when(mUserManager.getProfileParent(11))
371                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
372        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
373                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
374                new UserInfo(11, "managed profile", 0)));
375
376        mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(),
377            mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode);
378        mWsmThread = getWsmHandlerThread(mWsm);
379
380        final AsyncChannel channel = new AsyncChannel();
381        Handler handler = new Handler(mLooper.getLooper()) {
382            @Override
383            public void handleMessage(Message msg) {
384                switch (msg.what) {
385                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
386                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
387                            mWsmAsyncChannel = channel;
388                        } else {
389                            Log.d(TAG, "Failed to connect Command channel " + this);
390                        }
391                        break;
392                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
393                        Log.d(TAG, "Command channel disconnected" + this);
394                        break;
395                }
396            }
397        };
398
399        channel.connect(context, handler, mWsm.getMessenger());
400        mLooper.dispatchAll();
401        /* Now channel is supposed to be connected */
402
403        mBinderToken = Binder.clearCallingIdentity();
404    }
405
406    @After
407    public void cleanUp() throws Exception {
408        Binder.restoreCallingIdentity(mBinderToken);
409
410        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
411        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
412        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
413
414        mWsmThread = null;
415        mP2pThread = null;
416        mSyncThread = null;
417        mWsmAsyncChannel = null;
418        mWsm = null;
419    }
420
421    @Test
422    public void createNew() throws Exception {
423        assertEquals("InitialState", getCurrentState().getName());
424
425        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
426        mLooper.dispatchAll();
427        assertEquals("InitialState", getCurrentState().getName());
428    }
429
430    @Test
431    public void loadComponents() throws Exception {
432        when(mWifiNative.loadDriver()).thenReturn(true);
433        when(mWifiNative.startHal()).thenReturn(true);
434        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
435        mWsm.setSupplicantRunning(true);
436        mLooper.dispatchAll();
437
438        assertEquals("SupplicantStartingState", getCurrentState().getName());
439
440        when(mWifiNative.setBand(anyInt())).thenReturn(true);
441        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
442        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
443        when(mWifiNative.setModelName(anyString())).thenReturn(true);
444        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
445        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
446        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
447        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
448        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
449        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
450
451        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
452        mLooper.dispatchAll();
453
454        assertEquals("DisconnectedState", getCurrentState().getName());
455    }
456
457    @Test
458    public void loadComponentsFailure() throws Exception {
459        when(mWifiNative.loadDriver()).thenReturn(false);
460        when(mWifiNative.startHal()).thenReturn(false);
461        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false);
462
463        mWsm.setSupplicantRunning(true);
464        mLooper.dispatchAll();
465        assertEquals("InitialState", getCurrentState().getName());
466
467        when(mWifiNative.loadDriver()).thenReturn(true);
468        mWsm.setSupplicantRunning(true);
469        mLooper.dispatchAll();
470        assertEquals("InitialState", getCurrentState().getName());
471
472        when(mWifiNative.startHal()).thenReturn(true);
473        mWsm.setSupplicantRunning(true);
474        mLooper.dispatchAll();
475        assertEquals("InitialState", getCurrentState().getName());
476    }
477
478    /**
479     * Test to check that mode changes from WifiController will be properly handled in the
480     * InitialState by WifiStateMachine.
481     */
482    @Test
483    public void checkOperationalModeInInitialState() throws Exception {
484        when(mWifiNative.loadDriver()).thenReturn(true);
485        when(mWifiNative.startHal()).thenReturn(true);
486        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
487
488        mLooper.dispatchAll();
489        assertEquals("InitialState", getCurrentState().getName());
490        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
491
492        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
493        mLooper.dispatchAll();
494        assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
495                mWsm.getOperationalModeForTest());
496
497        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
498        mLooper.dispatchAll();
499        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
500
501        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
502        mLooper.dispatchAll();
503        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
504    }
505
506    /**
507     * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
508     * is started.
509     */
510    @Test
511    public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
512        when(mWifiNative.loadDriver()).thenReturn(true);
513        when(mWifiNative.startHal()).thenReturn(true);
514        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
515
516        // Check initial state
517        mLooper.dispatchAll();
518        assertEquals("InitialState", getCurrentState().getName());
519        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
520
521        // Update the mode
522        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
523        mLooper.dispatchAll();
524        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
525
526        // Start supplicant so we move to the next state
527        mWsm.setSupplicantRunning(true);
528        mLooper.dispatchAll();
529        assertEquals("SupplicantStartingState", getCurrentState().getName());
530        when(mWifiNative.setBand(anyInt())).thenReturn(true);
531        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
532        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
533        when(mWifiNative.setModelName(anyString())).thenReturn(true);
534        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
535        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
536        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
537        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
538        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
539        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
540
541        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
542        mLooper.dispatchAll();
543
544        assertEquals("ScanModeState", getCurrentState().getName());
545    }
546
547    private void addNetworkAndVerifySuccess() throws Exception {
548        addNetworkAndVerifySuccess(false);
549    }
550
551    private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception {
552        loadComponents();
553
554        final HashMap<String, String> nameToValue = new HashMap<String, String>();
555
556        when(mWifiNative.addNetwork()).thenReturn(0);
557        when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString()))
558                .then(new AnswerWithArguments() {
559                    public boolean answer(int netId, String name, String value) {
560                        if (netId != 0) {
561                            Log.d(TAG, "Can't set var " + name + " for " + netId);
562                            return false;
563                        }
564
565                        Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId);
566                        nameToValue.put(name, value);
567                        return true;
568                    }
569                });
570
571        when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject()))
572                .then(new AnswerWithArguments() {
573                    public boolean answer(int netId, String name, Map<String, String> values) {
574                        if (netId != 0) {
575                            Log.d(TAG, "Can't set extra " + name + " for " + netId);
576                            return false;
577                        }
578
579                        Log.d(TAG, "Setting extra for " + netId);
580                        return true;
581                    }
582                });
583
584        when(mWifiNative.getNetworkVariable(anyInt(), anyString()))
585                .then(new AnswerWithArguments() {
586                    public String answer(int netId, String name) throws Throwable {
587                        if (netId != 0) {
588                            Log.d(TAG, "Can't find var " + name + " for " + netId);
589                            return null;
590                        }
591                        String value = nameToValue.get(name);
592                        if (value != null) {
593                            Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId);
594                        } else {
595                            Log.d(TAG, "Can't find var " + name + " for " + netId);
596                        }
597                        return value;
598                    }
599                });
600
601        WifiConfiguration config = new WifiConfiguration();
602        config.SSID = sSSID;
603        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
604        config.hiddenSSID = isHidden;
605        mLooper.startAutoDispatch();
606        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
607        mLooper.stopAutoDispatch();
608
609        verify(mWifiNative).addNetwork();
610        verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID);
611        if (isHidden) {
612            verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1));
613        }
614
615        mLooper.startAutoDispatch();
616        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
617        mLooper.stopAutoDispatch();
618        assertEquals(1, configs.size());
619
620        WifiConfiguration config2 = configs.get(0);
621        assertEquals("\"GoogleGuest\"", config2.SSID);
622        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
623    }
624
625    private void addNetworkAndVerifyFailure() throws Exception {
626        loadComponents();
627
628        final WifiConfiguration config = new WifiConfiguration();
629        config.SSID = sSSID;
630        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
631
632        mLooper.startAutoDispatch();
633        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
634        mLooper.stopAutoDispatch();
635
636        verify(mWifiNative, never()).addNetwork();
637        verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString());
638
639        mLooper.startAutoDispatch();
640        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
641        mLooper.stopAutoDispatch();
642    }
643
644    /**
645     * Verifies that the current foreground user is allowed to add a network.
646     */
647    @Test
648    public void addNetworkAsCurrentUser() throws Exception {
649        addNetworkAndVerifySuccess();
650    }
651
652    /**
653     * Verifies that a managed profile of the current foreground user is allowed to add a network.
654     */
655    @Test
656    public void addNetworkAsCurrentUsersManagedProfile() throws Exception {
657        BinderUtil.setUid(MANAGED_PROFILE_UID);
658        addNetworkAndVerifySuccess();
659    }
660
661    /**
662     * Verifies that a background user is not allowed to add a network.
663     */
664    @Test
665    public void addNetworkAsOtherUser() throws Exception {
666        BinderUtil.setUid(OTHER_USER_UID);
667        addNetworkAndVerifyFailure();
668    }
669
670    private void removeNetworkAndVerifySuccess() throws Exception {
671        when(mWifiNative.removeNetwork(0)).thenReturn(true);
672        mLooper.startAutoDispatch();
673        assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
674        mLooper.stopAutoDispatch();
675
676        mLooper.startAutoDispatch();
677        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
678        mLooper.stopAutoDispatch();
679    }
680
681    private void removeNetworkAndVerifyFailure() throws Exception {
682        mLooper.startAutoDispatch();
683        assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
684        mLooper.stopAutoDispatch();
685
686        mLooper.startAutoDispatch();
687        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
688        mLooper.stopAutoDispatch();
689        verify(mWifiNative, never()).removeNetwork(anyInt());
690    }
691
692    /**
693     * Verifies that the current foreground user is allowed to remove a network.
694     */
695    @Test
696    public void removeNetworkAsCurrentUser() throws Exception {
697        addNetworkAndVerifySuccess();
698        removeNetworkAndVerifySuccess();
699    }
700
701    /**
702     * Verifies that a managed profile of the current foreground user is allowed to remove a
703     * network.
704     */
705    @Test
706    public void removeNetworkAsCurrentUsersManagedProfile() throws Exception {
707        addNetworkAndVerifySuccess();
708        BinderUtil.setUid(MANAGED_PROFILE_UID);
709        removeNetworkAndVerifySuccess();
710    }
711
712    /**
713     * Verifies that a background user is not allowed to remove a network.
714     */
715    @Test
716    public void removeNetworkAsOtherUser() throws Exception {
717        addNetworkAndVerifySuccess();
718        BinderUtil.setUid(OTHER_USER_UID);
719        removeNetworkAndVerifyFailure();
720    }
721
722    private void enableNetworkAndVerifySuccess() throws Exception {
723        when(mWifiNative.selectNetwork(0)).thenReturn(true);
724
725        mLooper.startAutoDispatch();
726        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
727        mLooper.stopAutoDispatch();
728
729        verify(mWifiNative).selectNetwork(0);
730    }
731
732    private void enableNetworkAndVerifyFailure() throws Exception {
733        mLooper.startAutoDispatch();
734        assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
735        mLooper.stopAutoDispatch();
736
737        verify(mWifiNative, never()).selectNetwork(anyInt());
738    }
739
740    /**
741     * Verifies that the current foreground user is allowed to enable a network.
742     */
743    @Test
744    public void enableNetworkAsCurrentUser() throws Exception {
745        addNetworkAndVerifySuccess();
746        enableNetworkAndVerifySuccess();
747    }
748
749    /**
750     * Verifies that a managed profile of the current foreground user is allowed to enable a
751     * network.
752     */
753    @Test
754    public void enableNetworkAsCurrentUsersManagedProfile() throws Exception {
755        addNetworkAndVerifySuccess();
756        BinderUtil.setUid(MANAGED_PROFILE_UID);
757        enableNetworkAndVerifySuccess();
758    }
759
760    /**
761     * Verifies that a background user is not allowed to enable a network.
762     */
763    @Test
764    public void enableNetworkAsOtherUser() throws Exception {
765        addNetworkAndVerifySuccess();
766        BinderUtil.setUid(OTHER_USER_UID);
767        enableNetworkAndVerifyFailure();
768    }
769
770    private void forgetNetworkAndVerifySuccess() throws Exception {
771        when(mWifiNative.removeNetwork(0)).thenReturn(true);
772        mLooper.startAutoDispatch();
773        final Message result =
774                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
775        mLooper.stopAutoDispatch();
776        assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what);
777        result.recycle();
778        mLooper.startAutoDispatch();
779        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
780        mLooper.stopAutoDispatch();
781    }
782
783    private void forgetNetworkAndVerifyFailure() throws Exception {
784        mLooper.startAutoDispatch();
785        final Message result =
786                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
787        mLooper.stopAutoDispatch();
788        assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what);
789        result.recycle();
790        mLooper.startAutoDispatch();
791        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
792        mLooper.stopAutoDispatch();
793        verify(mWifiNative, never()).removeNetwork(anyInt());
794    }
795
796    /**
797     * Helper method to retrieve WifiConfiguration by SSID.
798     *
799     * Returns the associated WifiConfiguration if it is found, null otherwise.
800     */
801    private WifiConfiguration getWifiConfigurationForNetwork(String ssid) {
802        mLooper.startAutoDispatch();
803        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
804        mLooper.stopAutoDispatch();
805
806        for (WifiConfiguration checkConfig : configs) {
807            if (checkConfig.SSID.equals(ssid)) {
808                return checkConfig;
809            }
810        }
811        return null;
812    }
813
814    /**
815     * Verifies that the current foreground user is allowed to forget a network.
816     */
817    @Test
818    public void forgetNetworkAsCurrentUser() throws Exception {
819        addNetworkAndVerifySuccess();
820        forgetNetworkAndVerifySuccess();
821    }
822
823    /**
824     * Verifies that a managed profile of the current foreground user is allowed to forget a
825     * network.
826     */
827    @Test
828    public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception {
829        addNetworkAndVerifySuccess();
830        BinderUtil.setUid(MANAGED_PROFILE_UID);
831        forgetNetworkAndVerifySuccess();
832    }
833
834    /**
835     * Verifies that a background user is not allowed to forget a network.
836     */
837    @Test
838    public void forgetNetworkAsOtherUser() throws Exception {
839        addNetworkAndVerifySuccess();
840        BinderUtil.setUid(OTHER_USER_UID);
841        forgetNetworkAndVerifyFailure();
842    }
843
844    private void verifyScan(int band, int reportEvents, Set<Integer> configuredNetworkIds) {
845        ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
846                ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
847        ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
848                ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
849        verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(),
850                eq(null));
851        WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue();
852        assertEquals("band", band, actualSettings.band);
853        assertEquals("reportEvents", reportEvents, actualSettings.reportEvents);
854
855        if (configuredNetworkIds == null) {
856            configuredNetworkIds = new HashSet<>();
857        }
858        Set<Integer> actualConfiguredNetworkIds = new HashSet<>();
859        if (actualSettings.hiddenNetworkIds != null) {
860            for (int i = 0; i < actualSettings.hiddenNetworkIds.length; ++i) {
861                actualConfiguredNetworkIds.add(actualSettings.hiddenNetworkIds[i]);
862            }
863        }
864        assertEquals("configured networks", configuredNetworkIds, actualConfiguredNetworkIds);
865
866        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
867        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
868
869        mLooper.dispatchAll();
870
871        List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
872        assertEquals(8, reportedResults.size());
873    }
874
875    @Test
876    public void scan() throws Exception {
877        addNetworkAndVerifySuccess();
878
879        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
880        mWsm.startScan(-1, 0, null, null);
881        mLooper.dispatchAll();
882
883        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
884                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
885                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null);
886    }
887
888    @Test
889    public void scanWithHiddenNetwork() throws Exception {
890        addNetworkAndVerifySuccess(true);
891
892        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
893        mWsm.startScan(-1, 0, null, null);
894        mLooper.dispatchAll();
895
896        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
897                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
898                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
899                mWifiConfigManager.getHiddenConfiguredNetworkIds());
900    }
901
902    @Test
903    public void connect() throws Exception {
904        addNetworkAndVerifySuccess();
905
906        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
907        mLooper.dispatchAll();
908
909        mLooper.startAutoDispatch();
910        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
911        mLooper.stopAutoDispatch();
912
913        verify(mWifiNative).selectNetwork(0);
914
915        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
916        mLooper.dispatchAll();
917
918        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
919                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
920        mLooper.dispatchAll();
921
922        assertEquals("ObtainingIpState", getCurrentState().getName());
923
924        DhcpResults dhcpResults = new DhcpResults();
925        dhcpResults.setGateway("1.2.3.4");
926        dhcpResults.setIpAddress("192.168.1.100", 0);
927        dhcpResults.addDns("8.8.8.8");
928        dhcpResults.setLeaseDuration(3600);
929
930        mTestIpManager.injectDhcpSuccess(dhcpResults);
931        mLooper.dispatchAll();
932
933        assertEquals("ConnectedState", getCurrentState().getName());
934    }
935
936    @Test
937    public void testDhcpFailure() throws Exception {
938        addNetworkAndVerifySuccess();
939
940        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
941        mLooper.dispatchAll();
942
943        mLooper.startAutoDispatch();
944        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
945        mLooper.stopAutoDispatch();
946
947        verify(mWifiNative).selectNetwork(0);
948
949        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
950        mLooper.dispatchAll();
951
952        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
953                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
954        mLooper.dispatchAll();
955
956        assertEquals("ObtainingIpState", getCurrentState().getName());
957
958        mTestIpManager.injectDhcpFailure();
959        mLooper.dispatchAll();
960
961        assertEquals("DisconnectingState", getCurrentState().getName());
962    }
963
964    @Test
965    public void testBadNetworkEvent() throws Exception {
966        addNetworkAndVerifySuccess();
967
968        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
969        mLooper.dispatchAll();
970
971        mLooper.startAutoDispatch();
972        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
973        mLooper.stopAutoDispatch();
974
975        verify(mWifiNative).selectNetwork(0);
976
977        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
978        mLooper.dispatchAll();
979
980        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
981                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
982        mLooper.dispatchAll();
983
984        assertEquals("DisconnectedState", getCurrentState().getName());
985    }
986
987
988    @Test
989    public void smToString() throws Exception {
990        assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString(
991                AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
992        assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString(
993                DhcpClient.CMD_PRE_DHCP_ACTION));
994        assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString(
995                WifiStateMachine.CMD_IP_REACHABILITY_LOST));
996    }
997
998    @Test
999    public void disconnect() throws Exception {
1000        connect();
1001
1002        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
1003        mLooper.dispatchAll();
1004        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1005                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
1006        mLooper.dispatchAll();
1007
1008        assertEquals("DisconnectedState", getCurrentState().getName());
1009    }
1010
1011    /**
1012     * WifiConfigurations default to HasEverConnected to false,  creating and adding a config should
1013     * not update this value to true.
1014     *
1015     * Test: Successfully add a network. Check the config and verify
1016     * WifiConfiguration.getHasEverConnected() is false.
1017     */
1018    @Test
1019    public void addNetworkDoesNotSetHasEverConnectedTrue() throws Exception {
1020        addNetworkAndVerifySuccess();
1021
1022        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1023        assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1024    }
1025
1026    /**
1027     * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
1028     * to true.
1029     *
1030     * Test: Successfully create and connect to a network. Check the config and verify
1031     * WifiConfiguration.getHasEverConnected() is true.
1032     */
1033    @Test
1034    public void setHasEverConnectedTrueOnConnect() throws Exception {
1035        connect();
1036
1037        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1038        assertTrue(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1039    }
1040
1041    /**
1042     * Fail network connection attempt and verify HasEverConnected remains false.
1043     *
1044     * Test: Successfully create a network but fail when connecting. Check the config and verify
1045     * WifiConfiguration.getHasEverConnected() is false.
1046     */
1047    @Test
1048    public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
1049        testDhcpFailure();
1050
1051        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1052        assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1053    }
1054
1055    @Test
1056    public void handleUserSwitch() throws Exception {
1057        assertEquals(UserHandle.USER_SYSTEM, mWifiConfigManager.getCurrentUserId());
1058
1059        mWsm.handleUserSwitch(10);
1060        mLooper.dispatchAll();
1061
1062        assertEquals(10, mWifiConfigManager.getCurrentUserId());
1063    }
1064
1065    @Test
1066    public void iconQueryTest() throws Exception {
1067        /* enable wi-fi */
1068        addNetworkAndVerifySuccess();
1069
1070        long bssid = 0x1234567800FFL;
1071        String filename = "iconFileName.png";
1072        String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename;
1073
1074        when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK");
1075
1076        mLooper.startAutoDispatch();
1077        boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename);
1078        mLooper.stopAutoDispatch();
1079
1080        verify(mWifiNative).doCustomSupplicantCommand(command);
1081        assertEquals(true, result);
1082    }
1083
1084    private String createSimChallengeRequest(byte[] challengeValue) {
1085        // Produce a base64 encoded length byte + data.
1086        byte[] challengeLengthAndValue = new byte[challengeValue.length + 1];
1087        challengeLengthAndValue[0] = (byte) challengeValue.length;
1088        for (int i = 0; i < challengeValue.length; ++i) {
1089            challengeLengthAndValue[i + 1] = challengeValue[i];
1090        }
1091        return Base64.encodeToString(challengeLengthAndValue, android.util.Base64.NO_WRAP);
1092    }
1093
1094    private String createSimAuthResponse(byte[] sresValue, byte[] kcValue) {
1095        // Produce a base64 encoded sres length byte + sres + kc length byte + kc.
1096        int overallLength = sresValue.length + kcValue.length + 2;
1097        byte[] result = new byte[sresValue.length + kcValue.length + 2];
1098        int idx = 0;
1099        result[idx++] = (byte) sresValue.length;
1100        for (int i = 0; i < sresValue.length; ++i) {
1101            result[idx++] = sresValue[i];
1102        }
1103        result[idx++] = (byte) kcValue.length;
1104        for (int i = 0; i < kcValue.length; ++i) {
1105            result[idx++] = kcValue[i];
1106        }
1107        return Base64.encodeToString(result, Base64.NO_WRAP);
1108    }
1109
1110    /** Verifies function getGsmSimAuthResponse method. */
1111    @Test
1112    public void getGsmSimAuthResponseTest() throws Exception {
1113        TelephonyManager tm = mock(TelephonyManager.class);
1114        final String[] invalidRequests = { null, "", "XXXX" };
1115        assertEquals("", mWsm.getGsmSimAuthResponse(invalidRequests, tm));
1116
1117        final String[] failedRequests = { "5E5F" };
1118        when(tm.getIccAuthentication(anyInt(), anyInt(),
1119                eq(createSimChallengeRequest(new byte[] { 0x5e, 0x5f })))).thenReturn(null);
1120        assertEquals(null, mWsm.getGsmSimAuthResponse(failedRequests, tm));
1121
1122        when(tm.getIccAuthentication(2, tm.AUTHTYPE_EAP_SIM,
1123                createSimChallengeRequest(new byte[] { 0x1a, 0x2b })))
1124                .thenReturn(null);
1125        when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM,
1126                createSimChallengeRequest(new byte[] { 0x1a, 0x2b })))
1127                .thenReturn(createSimAuthResponse(new byte[] { 0x1D, 0x2C },
1128                       new byte[] { 0x3B, 0x4A }));
1129        when(tm.getIccAuthentication(1, tm.AUTHTYPE_EAP_SIM,
1130                createSimChallengeRequest(new byte[] { 0x01, 0x23 })))
1131                .thenReturn(createSimAuthResponse(new byte[] { 0x33, 0x22 },
1132                        new byte[] { 0x11, 0x00 }));
1133        assertEquals(":3b4a:1d2c:1100:3322", mWsm.getGsmSimAuthResponse(
1134                new String[] { "1A2B", "0123" }, tm));
1135    }
1136
1137    /**
1138     * Verifies that, by default, we allow only the "normal" number of log records.
1139     */
1140    @Test
1141    public void normalLogRecSizeIsUsedByDefault() {
1142        for (int i = 0; i < WifiStateMachine.NUM_LOG_RECS_NORMAL * 2; i++) {
1143            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1144        }
1145        mLooper.dispatchAll();
1146        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize());
1147    }
1148
1149    /**
1150     * Verifies that, in verbose mode, we allow a larger number of log records.
1151     */
1152    @Test
1153    public void enablingVerboseLoggingIncreasesLogRecSize() {
1154        assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL);
1155        mWsm.enableVerboseLogging(1);
1156        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE * 2; i++) {
1157            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1158        }
1159        mLooper.dispatchAll();
1160        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize());
1161    }
1162
1163    /**
1164     * Verifies that moving from verbose mode to normal mode resets the buffer, and limits new
1165     * records to a small number of entries.
1166     */
1167    @Test
1168    public void disablingVerboseLoggingClearsRecordsAndDecreasesLogRecSize() {
1169        mWsm.enableVerboseLogging(1);
1170        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) {
1171            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1172        }
1173        mLooper.dispatchAll();
1174        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize());
1175
1176        mWsm.enableVerboseLogging(0);
1177        assertEquals(0, mWsm.getLogRecSize());
1178        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) {
1179            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1180        }
1181        mLooper.dispatchAll();
1182        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize());
1183    }
1184
1185    /** Verifies that enabling verbose logging sets the hal log property in eng builds. */
1186    @Test
1187    public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() {
1188        reset(mPropertyService);  // Ignore calls made in setUp()
1189        when(mBuildProperties.isEngBuild()).thenReturn(true);
1190        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1191        when(mBuildProperties.isUserBuild()).thenReturn(false);
1192        mWsm.enableVerboseLogging(1);
1193        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1194    }
1195
1196    /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */
1197    @Test
1198    public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() {
1199        reset(mPropertyService);  // Ignore calls made in setUp()
1200        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
1201        when(mBuildProperties.isEngBuild()).thenReturn(false);
1202        when(mBuildProperties.isUserBuild()).thenReturn(false);
1203        mWsm.enableVerboseLogging(1);
1204        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1205    }
1206
1207    /** Verifies that enabling verbose logging does NOT set the hal log property in user builds. */
1208    @Test
1209    public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() {
1210        reset(mPropertyService);  // Ignore calls made in setUp()
1211        when(mBuildProperties.isUserBuild()).thenReturn(true);
1212        when(mBuildProperties.isEngBuild()).thenReturn(false);
1213        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1214        mWsm.enableVerboseLogging(1);
1215        verify(mPropertyService, never()).set(anyString(), anyString());
1216    }
1217}
1218