WifiStateMachineTest.java revision 22538d9b292581859bb6d21415527521218b89db
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.ContentResolver;
28import android.content.Context;
29import android.content.pm.PackageManager;
30import android.content.pm.UserInfo;
31import android.content.res.Resources;
32import android.net.ConnectivityManager;
33import android.net.DhcpResults;
34import android.net.LinkProperties;
35import android.net.dhcp.DhcpClient;
36import android.net.ip.IpManager;
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.WifiManager;
43import android.net.wifi.WifiScanner;
44import android.net.wifi.WifiSsid;
45import android.net.wifi.p2p.IWifiP2pManager;
46import android.os.BatteryStats;
47import android.os.Binder;
48import android.os.Handler;
49import android.os.HandlerThread;
50import android.os.IBinder;
51import android.os.IInterface;
52import android.os.INetworkManagementService;
53import android.os.IPowerManager;
54import android.os.Looper;
55import android.os.Message;
56import android.os.Messenger;
57import android.os.PowerManager;
58import android.os.RemoteException;
59import android.os.UserHandle;
60import android.os.UserManager;
61import android.os.test.TestLooper;
62import android.provider.Settings;
63import android.security.KeyStore;
64import android.telephony.TelephonyManager;
65import android.test.suitebuilder.annotation.SmallTest;
66import android.util.Log;
67
68import com.android.internal.R;
69import com.android.internal.app.IBatteryStats;
70import com.android.internal.util.AsyncChannel;
71import com.android.internal.util.IState;
72import com.android.internal.util.StateMachine;
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.ArgumentCaptor;
81import org.mockito.Mock;
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.concurrent.CountDownLatch;
92import java.util.HashMap;
93import java.util.HashSet;
94import java.util.List;
95import java.util.Map;
96import java.util.Set;
97
98/**
99 * Unit tests for {@link com.android.server.wifi.WifiStateMachine}.
100 */
101@SmallTest
102public class WifiStateMachineTest {
103    public static final String TAG = "WifiStateMachineTest";
104
105    private static final int MANAGED_PROFILE_UID = 1100000;
106    private static final int OTHER_USER_UID = 1200000;
107    private static final int LOG_REC_LIMIT_IN_VERBOSE_MODE =
108            (ActivityManager.isLowRamDeviceStatic()
109                    ? WifiStateMachine.NUM_LOG_RECS_VERBOSE_LOW_MEMORY
110                    : WifiStateMachine.NUM_LOG_RECS_VERBOSE);
111    private static final String DEFAULT_TEST_SSID = "\"GoogleGuest\"";
112
113    private long mBinderToken;
114
115    private static <T> T mockWithInterfaces(Class<T> class1, Class<?>... interfaces) {
116        return mock(class1, withSettings().extraInterfaces(interfaces));
117    }
118
119    private static <T, I> IBinder mockService(Class<T> class1, Class<I> iface) {
120        T tImpl = mockWithInterfaces(class1, iface);
121        IBinder binder = mock(IBinder.class);
122        when(((IInterface) tImpl).asBinder()).thenReturn(binder);
123        when(binder.queryLocalInterface(iface.getCanonicalName()))
124                .thenReturn((IInterface) tImpl);
125        return binder;
126    }
127
128    private void enableDebugLogs() {
129        mWsm.enableVerboseLogging(1);
130    }
131
132    private class TestIpManager extends IpManager {
133        TestIpManager(Context context, String ifname, IpManager.Callback callback) {
134            // Call dependency-injection superclass constructor.
135            super(context, ifname, callback, mock(INetworkManagementService.class));
136        }
137
138        @Override
139        public void startProvisioning(IpManager.ProvisioningConfiguration config) {}
140
141        @Override
142        public void stop() {}
143
144        @Override
145        public void confirmConfiguration() {}
146
147        void injectDhcpSuccess(DhcpResults dhcpResults) {
148            mCallback.onNewDhcpResults(dhcpResults);
149            mCallback.onProvisioningSuccess(new LinkProperties());
150        }
151
152        void injectDhcpFailure() {
153            mCallback.onNewDhcpResults(null);
154            mCallback.onProvisioningFailure(new LinkProperties());
155        }
156    }
157
158    private FrameworkFacade getFrameworkFacade() throws Exception {
159        FrameworkFacade facade = mock(FrameworkFacade.class);
160
161        when(facade.makeWifiScanner(any(Context.class), any(Looper.class)))
162                .thenReturn(mWifiScanner);
163        when(facade.getService(Context.NETWORKMANAGEMENT_SERVICE)).thenReturn(
164                mockWithInterfaces(IBinder.class, INetworkManagementService.class));
165
166        IBinder p2pBinder = mockService(WifiP2pServiceImpl.class, IWifiP2pManager.class);
167        when(facade.getService(Context.WIFI_P2P_SERVICE)).thenReturn(p2pBinder);
168
169        WifiP2pServiceImpl p2pm = (WifiP2pServiceImpl) p2pBinder.queryLocalInterface(
170                IWifiP2pManager.class.getCanonicalName());
171
172        final CountDownLatch untilDone = new CountDownLatch(1);
173        mP2pThread = new HandlerThread("WifiP2pMockThread") {
174            @Override
175            protected void onLooperPrepared() {
176                untilDone.countDown();
177            }
178        };
179
180        mP2pThread.start();
181        untilDone.await();
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 TestAlarmManager();
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    TestAlarmManager mAlarmManager;
311    MockWifiMonitor mWifiMonitor;
312    TestIpManager mTestIpManager;
313    TestLooper 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    @Mock IWificond mWificond;
329    @Mock IClientInterface mClientInterface;
330    @Mock IBinder mClientInterfaceBinder;
331
332    public WifiStateMachineTest() throws Exception {
333    }
334
335    @Before
336    public void setUp() throws Exception {
337        Log.d(TAG, "Setting up ...");
338
339        // Ensure looper exists
340        mLooper = new TestLooper();
341
342        MockitoAnnotations.initMocks(this);
343
344        /** uncomment this to enable logs from WifiStateMachines */
345        // enableDebugLogs();
346
347        TestUtil.installWlanWifiNative(mWifiNative);
348        mWifiMonitor = new MockWifiMonitor();
349        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
350        when(mWifiInjector.getClock()).thenReturn(mock(Clock.class));
351        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
352        when(mWifiInjector.getPropertyService()).thenReturn(mPropertyService);
353        when(mWifiInjector.getBuildProperties()).thenReturn(mBuildProperties);
354        when(mWifiInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
355        when(mWifiInjector.getWifiBackupRestore()).thenReturn(mock(WifiBackupRestore.class));
356        when(mWifiInjector.makeWifiDiagnostics(anyObject())).thenReturn(
357                mock(BaseWifiDiagnostics.class));
358        when(mWifiInjector.makeWificond()).thenReturn(mWificond);
359
360        FrameworkFacade factory = getFrameworkFacade();
361        Context context = getContext();
362
363        Resources resources = getMockResources();
364        when(context.getResources()).thenReturn(resources);
365
366        when(factory.getIntegerSetting(context,
367                Settings.Global.WIFI_FREQUENCY_BAND,
368                WifiManager.WIFI_FREQUENCY_BAND_AUTO)).thenReturn(
369                WifiManager.WIFI_FREQUENCY_BAND_AUTO);
370
371        when(factory.makeApConfigStore(eq(context), eq(mBackupManagerProxy)))
372                .thenReturn(mApConfigStore);
373
374        when(factory.makeSupplicantStateTracker(
375                any(Context.class), any(WifiConfigManager.class),
376                any(Handler.class))).thenReturn(mSupplicantStateTracker);
377
378        when(mUserManager.getProfileParent(11))
379                .thenReturn(new UserInfo(UserHandle.USER_SYSTEM, "owner", 0));
380        when(mUserManager.getProfiles(UserHandle.USER_SYSTEM)).thenReturn(Arrays.asList(
381                new UserInfo(UserHandle.USER_SYSTEM, "owner", 0),
382                new UserInfo(11, "managed profile", 0)));
383
384        when(mWificond.createClientInterface()).thenReturn(mClientInterface);
385        when(mClientInterface.asBinder()).thenReturn(mClientInterfaceBinder);
386
387        mWsm = new WifiStateMachine(context, factory, mLooper.getLooper(),
388            mUserManager, mWifiInjector, mBackupManagerProxy, mCountryCode);
389        mWsmThread = getWsmHandlerThread(mWsm);
390
391        final AsyncChannel channel = new AsyncChannel();
392        Handler handler = new Handler(mLooper.getLooper()) {
393            @Override
394            public void handleMessage(Message msg) {
395                switch (msg.what) {
396                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
397                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
398                            mWsmAsyncChannel = channel;
399                        } else {
400                            Log.d(TAG, "Failed to connect Command channel " + this);
401                        }
402                        break;
403                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
404                        Log.d(TAG, "Command channel disconnected" + this);
405                        break;
406                }
407            }
408        };
409
410        channel.connect(context, handler, mWsm.getMessenger());
411        mLooper.dispatchAll();
412        /* Now channel is supposed to be connected */
413
414        mBinderToken = Binder.clearCallingIdentity();
415    }
416
417    @After
418    public void cleanUp() throws Exception {
419        Binder.restoreCallingIdentity(mBinderToken);
420
421        if (mSyncThread != null) stopLooper(mSyncThread.getLooper());
422        if (mWsmThread != null) stopLooper(mWsmThread.getLooper());
423        if (mP2pThread != null) stopLooper(mP2pThread.getLooper());
424
425        mWsmThread = null;
426        mP2pThread = null;
427        mSyncThread = null;
428        mWsmAsyncChannel = null;
429        mWsm = null;
430    }
431
432    @Test
433    public void createNew() throws Exception {
434        assertEquals("InitialState", getCurrentState().getName());
435
436        mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
437        mLooper.dispatchAll();
438        assertEquals("InitialState", getCurrentState().getName());
439    }
440
441    @Test
442    public void loadComponents() throws Exception {
443        when(mWifiNative.startHal()).thenReturn(true);
444        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
445        mWsm.setSupplicantRunning(true);
446        mLooper.dispatchAll();
447
448        assertEquals("SupplicantStartingState", getCurrentState().getName());
449
450        when(mWifiNative.setBand(anyInt())).thenReturn(true);
451        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
452        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
453        when(mWifiNative.setModelName(anyString())).thenReturn(true);
454        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
455        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
456        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
457        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
458        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
459        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
460
461        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
462        mLooper.dispatchAll();
463
464        assertEquals("DisconnectedState", getCurrentState().getName());
465    }
466
467    @Test
468    public void shouldRequireHalToLeaveInitialState() throws Exception {
469        when(mWifiNative.startHal()).thenReturn(false);
470        mWsm.setSupplicantRunning(true);
471        mLooper.dispatchAll();
472        assertEquals("InitialState", getCurrentState().getName());
473    }
474
475    @Test
476    public void shouldRequireSupplicantStartupToLeaveInitialState() throws Exception {
477        when(mWifiNative.startSupplicant(true)).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()).thenReturn(false);
510        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(false);
511
512        mWsm.setSupplicantRunning(true);
513        mLooper.dispatchAll();
514        assertEquals("InitialState", getCurrentState().getName());
515
516        when(mWifiNative.startHal()).thenReturn(true);
517        mWsm.setSupplicantRunning(true);
518        mLooper.dispatchAll();
519        assertEquals("InitialState", getCurrentState().getName());
520    }
521
522    /**
523     * Test to check that mode changes from WifiController will be properly handled in the
524     * InitialState by WifiStateMachine.
525     */
526    @Test
527    public void checkOperationalModeInInitialState() throws Exception {
528        when(mWifiNative.startHal()).thenReturn(true);
529        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
530
531        mLooper.dispatchAll();
532        assertEquals("InitialState", getCurrentState().getName());
533        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
534
535        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE);
536        mLooper.dispatchAll();
537        assertEquals(WifiStateMachine.SCAN_ONLY_WITH_WIFI_OFF_MODE,
538                mWsm.getOperationalModeForTest());
539
540        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
541        mLooper.dispatchAll();
542        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
543
544        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
545        mLooper.dispatchAll();
546        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
547    }
548
549    /**
550     * Test that mode changes for WifiStateMachine in the InitialState are realized when supplicant
551     * is started.
552     */
553    @Test
554    public void checkStartInCorrectStateAfterChangingInitialState() throws Exception {
555        when(mWifiNative.startHal()).thenReturn(true);
556        when(mWifiNative.startSupplicant(anyBoolean())).thenReturn(true);
557
558        // Check initial state
559        mLooper.dispatchAll();
560        assertEquals("InitialState", getCurrentState().getName());
561        assertEquals(WifiStateMachine.CONNECT_MODE, mWsm.getOperationalModeForTest());
562
563        // Update the mode
564        mWsm.setOperationalMode(WifiStateMachine.SCAN_ONLY_MODE);
565        mLooper.dispatchAll();
566        assertEquals(WifiStateMachine.SCAN_ONLY_MODE, mWsm.getOperationalModeForTest());
567
568        // Start supplicant so we move to the next state
569        mWsm.setSupplicantRunning(true);
570        mLooper.dispatchAll();
571        assertEquals("SupplicantStartingState", getCurrentState().getName());
572        when(mWifiNative.setBand(anyInt())).thenReturn(true);
573        when(mWifiNative.setDeviceName(anyString())).thenReturn(true);
574        when(mWifiNative.setManufacturer(anyString())).thenReturn(true);
575        when(mWifiNative.setModelName(anyString())).thenReturn(true);
576        when(mWifiNative.setModelNumber(anyString())).thenReturn(true);
577        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
578        when(mWifiNative.setConfigMethods(anyString())).thenReturn(true);
579        when(mWifiNative.setDeviceType(anyString())).thenReturn(true);
580        when(mWifiNative.setSerialNumber(anyString())).thenReturn(true);
581        when(mWifiNative.setScanningMacOui(any(byte[].class))).thenReturn(true);
582
583        mWsm.sendMessage(WifiMonitor.SUP_CONNECTION_EVENT);
584        mLooper.dispatchAll();
585
586        assertEquals("ScanModeState", getCurrentState().getName());
587    }
588
589    private void addNetworkAndVerifySuccess() throws Exception {
590        addNetworkAndVerifySuccess(false);
591    }
592
593    private void addNetworkAndVerifySuccess(boolean isHidden) throws Exception {
594        loadComponents();
595
596        final HashMap<String, String> nameToValue = new HashMap<>();
597
598        when(mWifiNative.addNetwork()).thenReturn(0);
599        when(mWifiNative.setNetworkVariable(anyInt(), anyString(), anyString()))
600                .then(new AnswerWithArguments() {
601                    public boolean answer(int netId, String name, String value) {
602                        if (netId != 0) {
603                            Log.d(TAG, "Can't set var " + name + " for " + netId);
604                            return false;
605                        }
606
607                        Log.d(TAG, "Setting var " + name + " to " + value + " for " + netId);
608                        nameToValue.put(name, value);
609                        return true;
610                    }
611                });
612
613        when(mWifiNative.setNetworkExtra(anyInt(), anyString(), (Map<String, String>) anyObject()))
614                .then(new AnswerWithArguments() {
615                    public boolean answer(int netId, String name, Map<String, String> values) {
616                        if (netId != 0) {
617                            Log.d(TAG, "Can't set extra " + name + " for " + netId);
618                            return false;
619                        }
620
621                        Log.d(TAG, "Setting extra for " + netId);
622                        return true;
623                    }
624                });
625
626        when(mWifiNative.getNetworkVariable(anyInt(), anyString()))
627                .then(new AnswerWithArguments() {
628                    public String answer(int netId, String name) throws Throwable {
629                        if (netId != 0) {
630                            Log.d(TAG, "Can't find var " + name + " for " + netId);
631                            return null;
632                        }
633                        String value = nameToValue.get(name);
634                        if (value != null) {
635                            Log.d(TAG, "Returning var " + name + " to " + value + " for " + netId);
636                        } else {
637                            Log.d(TAG, "Can't find var " + name + " for " + netId);
638                        }
639                        return value;
640                    }
641                });
642
643        WifiConfiguration config = new WifiConfiguration();
644        config.SSID = sSSID;
645        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
646        config.hiddenSSID = isHidden;
647        mLooper.startAutoDispatch();
648        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
649        mLooper.stopAutoDispatch();
650
651        verify(mWifiNative).addNetwork();
652        verify(mWifiNative).setNetworkVariable(0, "ssid", sHexSSID);
653        if (isHidden) {
654            verify(mWifiNative).setNetworkVariable(0, "scan_ssid", Integer.toString(1));
655        }
656
657        mLooper.startAutoDispatch();
658        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
659        mLooper.stopAutoDispatch();
660        assertEquals(1, configs.size());
661
662        WifiConfiguration config2 = configs.get(0);
663        assertEquals("\"GoogleGuest\"", config2.SSID);
664        assertTrue(config2.allowedKeyManagement.get(WifiConfiguration.KeyMgmt.NONE));
665    }
666
667    private void addNetworkAndVerifyFailure() throws Exception {
668        loadComponents();
669
670        final WifiConfiguration config = new WifiConfiguration();
671        config.SSID = sSSID;
672        config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
673
674        mLooper.startAutoDispatch();
675        mWsm.syncAddOrUpdateNetwork(mWsmAsyncChannel, config);
676        mLooper.stopAutoDispatch();
677
678        verify(mWifiNative, never()).addNetwork();
679        verify(mWifiNative, never()).setNetworkVariable(anyInt(), anyString(), anyString());
680
681        mLooper.startAutoDispatch();
682        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
683        mLooper.stopAutoDispatch();
684    }
685
686    /**
687     * Verifies that the current foreground user is allowed to add a network.
688     */
689    @Test
690    public void addNetworkAsCurrentUser() throws Exception {
691        addNetworkAndVerifySuccess();
692    }
693
694    /**
695     * Verifies that a managed profile of the current foreground user is allowed to add a network.
696     */
697    @Test
698    public void addNetworkAsCurrentUsersManagedProfile() throws Exception {
699        BinderUtil.setUid(MANAGED_PROFILE_UID);
700        addNetworkAndVerifySuccess();
701    }
702
703    /**
704     * Verifies that a background user is not allowed to add a network.
705     */
706    @Test
707    public void addNetworkAsOtherUser() throws Exception {
708        BinderUtil.setUid(OTHER_USER_UID);
709        addNetworkAndVerifyFailure();
710    }
711
712    private void removeNetworkAndVerifySuccess() throws Exception {
713        when(mWifiNative.removeNetwork(0)).thenReturn(true);
714        mLooper.startAutoDispatch();
715        assertTrue(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
716        mLooper.stopAutoDispatch();
717
718        mLooper.startAutoDispatch();
719        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
720        mLooper.stopAutoDispatch();
721    }
722
723    private void removeNetworkAndVerifyFailure() throws Exception {
724        mLooper.startAutoDispatch();
725        assertFalse(mWsm.syncRemoveNetwork(mWsmAsyncChannel, 0));
726        mLooper.stopAutoDispatch();
727
728        mLooper.startAutoDispatch();
729        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
730        mLooper.stopAutoDispatch();
731        verify(mWifiNative, never()).removeNetwork(anyInt());
732    }
733
734    /**
735     * Verifies that the current foreground user is allowed to remove a network.
736     */
737    @Test
738    public void removeNetworkAsCurrentUser() throws Exception {
739        addNetworkAndVerifySuccess();
740        removeNetworkAndVerifySuccess();
741    }
742
743    /**
744     * Verifies that a managed profile of the current foreground user is allowed to remove a
745     * network.
746     */
747    @Test
748    public void removeNetworkAsCurrentUsersManagedProfile() throws Exception {
749        addNetworkAndVerifySuccess();
750        BinderUtil.setUid(MANAGED_PROFILE_UID);
751        removeNetworkAndVerifySuccess();
752    }
753
754    /**
755     * Verifies that a background user is not allowed to remove a network.
756     */
757    @Test
758    public void removeNetworkAsOtherUser() throws Exception {
759        addNetworkAndVerifySuccess();
760        BinderUtil.setUid(OTHER_USER_UID);
761        removeNetworkAndVerifyFailure();
762    }
763
764    private void enableNetworkAndVerifySuccess() throws Exception {
765        when(mWifiNative.selectNetwork(0)).thenReturn(true);
766
767        mLooper.startAutoDispatch();
768        assertTrue(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
769        mLooper.stopAutoDispatch();
770
771        verify(mWifiNative).selectNetwork(0);
772    }
773
774    private void enableNetworkAndVerifyFailure() throws Exception {
775        mLooper.startAutoDispatch();
776        assertFalse(mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true));
777        mLooper.stopAutoDispatch();
778
779        verify(mWifiNative, never()).selectNetwork(anyInt());
780    }
781
782    /**
783     * Verifies that the current foreground user is allowed to enable a network.
784     */
785    @Test
786    public void enableNetworkAsCurrentUser() throws Exception {
787        addNetworkAndVerifySuccess();
788        enableNetworkAndVerifySuccess();
789    }
790
791    /**
792     * Verifies that a managed profile of the current foreground user is allowed to enable a
793     * network.
794     */
795    @Test
796    public void enableNetworkAsCurrentUsersManagedProfile() throws Exception {
797        addNetworkAndVerifySuccess();
798        BinderUtil.setUid(MANAGED_PROFILE_UID);
799        enableNetworkAndVerifySuccess();
800    }
801
802    /**
803     * Verifies that a background user is not allowed to enable a network.
804     */
805    @Test
806    public void enableNetworkAsOtherUser() throws Exception {
807        addNetworkAndVerifySuccess();
808        BinderUtil.setUid(OTHER_USER_UID);
809        enableNetworkAndVerifyFailure();
810    }
811
812    private void forgetNetworkAndVerifySuccess() throws Exception {
813        when(mWifiNative.removeNetwork(0)).thenReturn(true);
814        mLooper.startAutoDispatch();
815        final Message result =
816                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
817        mLooper.stopAutoDispatch();
818        assertEquals(WifiManager.FORGET_NETWORK_SUCCEEDED, result.what);
819        result.recycle();
820        mLooper.startAutoDispatch();
821        assertTrue(mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).isEmpty());
822        mLooper.stopAutoDispatch();
823    }
824
825    private void forgetNetworkAndVerifyFailure() throws Exception {
826        mLooper.startAutoDispatch();
827        final Message result =
828                mWsmAsyncChannel.sendMessageSynchronously(WifiManager.FORGET_NETWORK, 0);
829        mLooper.stopAutoDispatch();
830        assertEquals(WifiManager.FORGET_NETWORK_FAILED, result.what);
831        result.recycle();
832        mLooper.startAutoDispatch();
833        assertEquals(1, mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel).size());
834        mLooper.stopAutoDispatch();
835        verify(mWifiNative, never()).removeNetwork(anyInt());
836    }
837
838    /**
839     * Helper method to retrieve WifiConfiguration by SSID.
840     *
841     * Returns the associated WifiConfiguration if it is found, null otherwise.
842     */
843    private WifiConfiguration getWifiConfigurationForNetwork(String ssid) {
844        mLooper.startAutoDispatch();
845        List<WifiConfiguration> configs = mWsm.syncGetConfiguredNetworks(-1, mWsmAsyncChannel);
846        mLooper.stopAutoDispatch();
847
848        for (WifiConfiguration checkConfig : configs) {
849            if (checkConfig.SSID.equals(ssid)) {
850                return checkConfig;
851            }
852        }
853        return null;
854    }
855
856    /**
857     * Verifies that the current foreground user is allowed to forget a network.
858     */
859    @Test
860    public void forgetNetworkAsCurrentUser() throws Exception {
861        addNetworkAndVerifySuccess();
862        forgetNetworkAndVerifySuccess();
863    }
864
865    /**
866     * Verifies that a managed profile of the current foreground user is allowed to forget a
867     * network.
868     */
869    @Test
870    public void forgetNetworkAsCurrentUsersManagedProfile() throws Exception {
871        addNetworkAndVerifySuccess();
872        BinderUtil.setUid(MANAGED_PROFILE_UID);
873        forgetNetworkAndVerifySuccess();
874    }
875
876    /**
877     * Verifies that a background user is not allowed to forget a network.
878     */
879    @Test
880    public void forgetNetworkAsOtherUser() throws Exception {
881        addNetworkAndVerifySuccess();
882        BinderUtil.setUid(OTHER_USER_UID);
883        forgetNetworkAndVerifyFailure();
884    }
885
886    private void verifyScan(int band, int reportEvents, Set<Integer> configuredNetworkIds) {
887        ArgumentCaptor<WifiScanner.ScanSettings> scanSettingsCaptor =
888                ArgumentCaptor.forClass(WifiScanner.ScanSettings.class);
889        ArgumentCaptor<WifiScanner.ScanListener> scanListenerCaptor =
890                ArgumentCaptor.forClass(WifiScanner.ScanListener.class);
891        verify(mWifiScanner).startScan(scanSettingsCaptor.capture(), scanListenerCaptor.capture(),
892                eq(null));
893        WifiScanner.ScanSettings actualSettings = scanSettingsCaptor.getValue();
894        assertEquals("band", band, actualSettings.band);
895        assertEquals("reportEvents", reportEvents, actualSettings.reportEvents);
896
897        if (configuredNetworkIds == null) {
898            configuredNetworkIds = new HashSet<>();
899        }
900        Set<Integer> actualConfiguredNetworkIds = new HashSet<>();
901        if (actualSettings.hiddenNetworkIds != null) {
902            for (int i = 0; i < actualSettings.hiddenNetworkIds.length; ++i) {
903                actualConfiguredNetworkIds.add(actualSettings.hiddenNetworkIds[i]);
904            }
905        }
906        assertEquals("configured networks", configuredNetworkIds, actualConfiguredNetworkIds);
907
908        when(mWifiNative.getScanResults()).thenReturn(getMockScanResults());
909        mWsm.sendMessage(WifiMonitor.SCAN_RESULTS_EVENT);
910
911        mLooper.dispatchAll();
912
913        List<ScanResult> reportedResults = mWsm.syncGetScanResultsList();
914        assertEquals(8, reportedResults.size());
915    }
916
917    @Test
918    public void scan() throws Exception {
919        addNetworkAndVerifySuccess();
920
921        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
922        mWsm.startScan(-1, 0, null, null);
923        mLooper.dispatchAll();
924
925        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
926                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
927                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT, null);
928    }
929
930    @Test
931    public void scanWithHiddenNetwork() throws Exception {
932        addNetworkAndVerifySuccess(true);
933
934        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
935        mWsm.startScan(-1, 0, null, null);
936        mLooper.dispatchAll();
937
938        verifyScan(WifiScanner.WIFI_BAND_BOTH_WITH_DFS,
939                WifiScanner.REPORT_EVENT_AFTER_EACH_SCAN
940                | WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT,
941                mWifiConfigManager.getHiddenConfiguredNetworkIds());
942    }
943
944    @Test
945    public void connect() throws Exception {
946        addNetworkAndVerifySuccess();
947
948        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
949        mLooper.dispatchAll();
950
951        mLooper.startAutoDispatch();
952        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
953        mLooper.stopAutoDispatch();
954
955        verify(mWifiNative).selectNetwork(0);
956
957        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
958        mLooper.dispatchAll();
959
960        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
961                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
962        mLooper.dispatchAll();
963
964        assertEquals("ObtainingIpState", getCurrentState().getName());
965
966        DhcpResults dhcpResults = new DhcpResults();
967        dhcpResults.setGateway("1.2.3.4");
968        dhcpResults.setIpAddress("192.168.1.100", 0);
969        dhcpResults.addDns("8.8.8.8");
970        dhcpResults.setLeaseDuration(3600);
971
972        mTestIpManager.injectDhcpSuccess(dhcpResults);
973        mLooper.dispatchAll();
974
975        assertEquals("ConnectedState", getCurrentState().getName());
976    }
977
978    @Test
979    public void testDhcpFailure() throws Exception {
980        addNetworkAndVerifySuccess();
981
982        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
983        mLooper.dispatchAll();
984
985        mLooper.startAutoDispatch();
986        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
987        mLooper.stopAutoDispatch();
988
989        verify(mWifiNative).selectNetwork(0);
990
991        mWsm.sendMessage(WifiMonitor.NETWORK_CONNECTION_EVENT, 0, 0, sBSSID);
992        mLooper.dispatchAll();
993
994        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
995                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
996        mLooper.dispatchAll();
997
998        assertEquals("ObtainingIpState", getCurrentState().getName());
999
1000        mTestIpManager.injectDhcpFailure();
1001        mLooper.dispatchAll();
1002
1003        assertEquals("DisconnectingState", getCurrentState().getName());
1004    }
1005
1006    @Test
1007    public void testBadNetworkEvent() throws Exception {
1008        addNetworkAndVerifySuccess();
1009
1010        mWsm.setOperationalMode(WifiStateMachine.CONNECT_MODE);
1011        mLooper.dispatchAll();
1012
1013        mLooper.startAutoDispatch();
1014        mWsm.syncEnableNetwork(mWsmAsyncChannel, 0, true);
1015        mLooper.stopAutoDispatch();
1016
1017        verify(mWifiNative).selectNetwork(0);
1018
1019        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, 0, 0, sBSSID);
1020        mLooper.dispatchAll();
1021
1022        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1023                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.COMPLETED));
1024        mLooper.dispatchAll();
1025
1026        assertEquals("DisconnectedState", getCurrentState().getName());
1027    }
1028
1029
1030    @Test
1031    public void smToString() throws Exception {
1032        assertEquals("CMD_CHANNEL_HALF_CONNECTED", mWsm.smToString(
1033                AsyncChannel.CMD_CHANNEL_HALF_CONNECTED));
1034        assertEquals("CMD_PRE_DHCP_ACTION", mWsm.smToString(
1035                DhcpClient.CMD_PRE_DHCP_ACTION));
1036        assertEquals("CMD_IP_REACHABILITY_LOST", mWsm.smToString(
1037                WifiStateMachine.CMD_IP_REACHABILITY_LOST));
1038    }
1039
1040    @Test
1041    public void disconnect() throws Exception {
1042        connect();
1043
1044        mWsm.sendMessage(WifiMonitor.NETWORK_DISCONNECTION_EVENT, -1, 3, "01:02:03:04:05:06");
1045        mLooper.dispatchAll();
1046        mWsm.sendMessage(WifiMonitor.SUPPLICANT_STATE_CHANGE_EVENT, 0, 0,
1047                new StateChangeResult(0, sWifiSsid, sBSSID, SupplicantState.DISCONNECTED));
1048        mLooper.dispatchAll();
1049
1050        assertEquals("DisconnectedState", getCurrentState().getName());
1051    }
1052
1053    /**
1054     * WifiConfigurations default to HasEverConnected to false,  creating and adding a config should
1055     * not update this value to true.
1056     *
1057     * Test: Successfully add a network. Check the config and verify
1058     * WifiConfiguration.getHasEverConnected() is false.
1059     */
1060    @Test
1061    public void addNetworkDoesNotSetHasEverConnectedTrue() throws Exception {
1062        addNetworkAndVerifySuccess();
1063
1064        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1065        assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1066    }
1067
1068    /**
1069     * Successfully connecting to a network will set WifiConfiguration's value of HasEverConnected
1070     * to true.
1071     *
1072     * Test: Successfully create and connect to a network. Check the config and verify
1073     * WifiConfiguration.getHasEverConnected() is true.
1074     */
1075    @Test
1076    public void setHasEverConnectedTrueOnConnect() throws Exception {
1077        connect();
1078
1079        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1080        assertTrue(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1081    }
1082
1083    /**
1084     * Fail network connection attempt and verify HasEverConnected remains false.
1085     *
1086     * Test: Successfully create a network but fail when connecting. Check the config and verify
1087     * WifiConfiguration.getHasEverConnected() is false.
1088     */
1089    @Test
1090    public void connectionFailureDoesNotSetHasEverConnectedTrue() throws Exception {
1091        testDhcpFailure();
1092
1093        WifiConfiguration checkConfig = getWifiConfigurationForNetwork(DEFAULT_TEST_SSID);
1094        assertFalse(checkConfig.getNetworkSelectionStatus().getHasEverConnected());
1095    }
1096
1097    @Test
1098    public void handleUserSwitch() throws Exception {
1099        assertEquals(UserHandle.USER_SYSTEM, mWifiConfigManager.getCurrentUserId());
1100
1101        mWsm.handleUserSwitch(10);
1102        mLooper.dispatchAll();
1103
1104        assertEquals(10, mWifiConfigManager.getCurrentUserId());
1105    }
1106
1107    @Test
1108    public void iconQueryTest() throws Exception {
1109        /* enable wi-fi */
1110        addNetworkAndVerifySuccess();
1111
1112        long bssid = 0x1234567800FFL;
1113        String filename = "iconFileName.png";
1114        String command = "REQ_HS20_ICON " + Utils.macToString(bssid) + " " + filename;
1115
1116        when(mWifiNative.doCustomSupplicantCommand(command)).thenReturn("OK");
1117
1118        mLooper.startAutoDispatch();
1119        boolean result = mWsm.syncQueryPasspointIcon(mWsmAsyncChannel, bssid, filename);
1120        mLooper.stopAutoDispatch();
1121
1122        verify(mWifiNative).doCustomSupplicantCommand(command);
1123        assertEquals(true, result);
1124    }
1125
1126    /**
1127     * Verifies that, by default, we allow only the "normal" number of log records.
1128     */
1129    @Test
1130    public void normalLogRecSizeIsUsedByDefault() {
1131        for (int i = 0; i < WifiStateMachine.NUM_LOG_RECS_NORMAL * 2; i++) {
1132            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1133        }
1134        mLooper.dispatchAll();
1135        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize());
1136    }
1137
1138    /**
1139     * Verifies that, in verbose mode, we allow a larger number of log records.
1140     */
1141    @Test
1142    public void enablingVerboseLoggingIncreasesLogRecSize() {
1143        assertTrue(LOG_REC_LIMIT_IN_VERBOSE_MODE > WifiStateMachine.NUM_LOG_RECS_NORMAL);
1144        mWsm.enableVerboseLogging(1);
1145        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE * 2; i++) {
1146            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1147        }
1148        mLooper.dispatchAll();
1149        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize());
1150    }
1151
1152    /**
1153     * Verifies that moving from verbose mode to normal mode resets the buffer, and limits new
1154     * records to a small number of entries.
1155     */
1156    @Test
1157    public void disablingVerboseLoggingClearsRecordsAndDecreasesLogRecSize() {
1158        mWsm.enableVerboseLogging(1);
1159        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) {
1160            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1161        }
1162        mLooper.dispatchAll();
1163        assertEquals(LOG_REC_LIMIT_IN_VERBOSE_MODE, mWsm.getLogRecSize());
1164
1165        mWsm.enableVerboseLogging(0);
1166        assertEquals(0, mWsm.getLogRecSize());
1167        for (int i = 0; i < LOG_REC_LIMIT_IN_VERBOSE_MODE; i++) {
1168            mWsm.sendMessage(WifiStateMachine.CMD_BOOT_COMPLETED);
1169        }
1170        mLooper.dispatchAll();
1171        assertEquals(WifiStateMachine.NUM_LOG_RECS_NORMAL, mWsm.getLogRecSize());
1172    }
1173
1174    /** Verifies that enabling verbose logging sets the hal log property in eng builds. */
1175    @Test
1176    public void enablingVerboseLoggingSetsHalLogPropertyInEngBuilds() {
1177        reset(mPropertyService);  // Ignore calls made in setUp()
1178        when(mBuildProperties.isEngBuild()).thenReturn(true);
1179        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1180        when(mBuildProperties.isUserBuild()).thenReturn(false);
1181        mWsm.enableVerboseLogging(1);
1182        verify(mPropertyService).set("log.tag.WifiHAL", "V");
1183    }
1184
1185    /** Verifies that enabling verbose logging sets the hal log property in userdebug builds. */
1186    @Test
1187    public void enablingVerboseLoggingSetsHalLogPropertyInUserdebugBuilds() {
1188        reset(mPropertyService);  // Ignore calls made in setUp()
1189        when(mBuildProperties.isUserdebugBuild()).thenReturn(true);
1190        when(mBuildProperties.isEngBuild()).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 does NOT set the hal log property in user builds. */
1197    @Test
1198    public void enablingVerboseLoggingDoeNotSetHalLogPropertyInUserBuilds() {
1199        reset(mPropertyService);  // Ignore calls made in setUp()
1200        when(mBuildProperties.isUserBuild()).thenReturn(true);
1201        when(mBuildProperties.isEngBuild()).thenReturn(false);
1202        when(mBuildProperties.isUserdebugBuild()).thenReturn(false);
1203        mWsm.enableVerboseLogging(1);
1204        verify(mPropertyService, never()).set(anyString(), anyString());
1205    }
1206}
1207