WifiServiceImplTest.java revision a6e534fc17203d535ec786b25aad9ff65afdbbea
1/*
2 * Copyright (C) 2016 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 android.net.wifi.WifiManager.HOTSPOT_FAILED;
20import static android.net.wifi.WifiManager.HOTSPOT_STARTED;
21import static android.net.wifi.WifiManager.HOTSPOT_STOPPED;
22import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
23import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
24import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
25import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC;
26import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE;
27import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL;
28import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED;
29import static android.net.wifi.WifiManager.SAP_START_FAILURE_GENERAL;
30import static android.net.wifi.WifiManager.SAP_START_FAILURE_NO_CHANNEL;
31import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
32import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLING;
33import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
34import static android.net.wifi.WifiManager.WIFI_AP_STATE_FAILED;
35import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
36import static android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
37import static android.provider.Settings.Secure.LOCATION_MODE_OFF;
38
39import static com.android.server.wifi.LocalOnlyHotspotRequestInfo.HOTSPOT_NO_ERROR;
40import static com.android.server.wifi.WifiController.CMD_SET_AP;
41import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED;
42
43import static org.junit.Assert.assertEquals;
44import static org.junit.Assert.assertFalse;
45import static org.junit.Assert.assertNotNull;
46import static org.junit.Assert.assertNull;
47import static org.junit.Assert.assertTrue;
48import static org.mockito.Matchers.any;
49import static org.mockito.Matchers.anyString;
50import static org.mockito.Matchers.eq;
51import static org.mockito.Mockito.*;
52
53import android.app.ActivityManager;
54import android.app.AppOpsManager;
55import android.content.BroadcastReceiver;
56import android.content.ContentResolver;
57import android.content.Context;
58import android.content.IntentFilter;
59import android.content.pm.PackageManager;
60import android.content.res.Resources;
61import android.net.IpConfiguration;
62import android.net.wifi.ScanSettings;
63import android.net.wifi.WifiConfiguration;
64import android.net.wifi.WifiEnterpriseConfig;
65import android.net.wifi.WifiManager;
66import android.net.wifi.WifiManager.LocalOnlyHotspotCallback;
67import android.net.wifi.hotspot2.PasspointConfiguration;
68import android.os.Handler;
69import android.os.HandlerThread;
70import android.os.IBinder;
71import android.os.IPowerManager;
72import android.os.Looper;
73import android.os.Message;
74import android.os.Messenger;
75import android.os.PowerManager;
76import android.os.Process;
77import android.os.RemoteException;
78import android.os.UserManager;
79import android.os.WorkSource;
80import android.os.test.TestLooper;
81import android.provider.Settings;
82import android.test.suitebuilder.annotation.SmallTest;
83
84import com.android.internal.util.AsyncChannel;
85import com.android.server.wifi.WifiServiceImpl.LocalOnlyRequestorCallback;
86import com.android.server.wifi.util.WifiAsyncChannel;
87import com.android.server.wifi.util.WifiPermissionsUtil;
88
89
90import org.junit.Before;
91import org.junit.Test;
92import org.mockito.ArgumentCaptor;
93import org.mockito.ArgumentMatcher;
94import org.mockito.Mock;
95import org.mockito.MockitoAnnotations;
96import org.mockito.Spy;
97
98import java.io.FileDescriptor;
99import java.io.PrintWriter;
100import java.io.StringWriter;
101
102/**
103 * Unit tests for {@link WifiServiceImpl}.
104 *
105 * Note: this is intended to build up over time and will not immediately cover the entire file.
106 */
107@SmallTest
108public class WifiServiceImplTest {
109
110    private static final String TAG = "WifiServiceImplTest";
111    private static final String SCAN_PACKAGE_NAME = "scanPackage";
112    private static final String WHITE_LIST_SCAN_PACKAGE_NAME = "whiteListScanPackage";
113    private static final int DEFAULT_VERBOSE_LOGGING = 0;
114    private static final long WIFI_BACKGROUND_SCAN_INTERVAL = 10000;
115    private static final String ANDROID_SYSTEM_PACKAGE = "android";
116    private static final String TEST_PACKAGE_NAME = "TestPackage";
117    private static final String SYSUI_PACKAGE_NAME = "com.android.systemui";
118    private static final int TEST_PID = 6789;
119    private static final int TEST_PID2 = 9876;
120    private static final String WIFI_IFACE_NAME = "wlan0";
121
122    private WifiServiceImpl mWifiServiceImpl;
123    private TestLooper mLooper;
124    private PowerManager mPowerManager;
125    private Handler mHandler;
126    private Messenger mAppMessenger;
127    private int mPid;
128    private int mPid2 = Process.myPid();
129
130    final ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor =
131            ArgumentCaptor.forClass(BroadcastReceiver.class);
132    final ArgumentCaptor<IntentFilter> mIntentFilterCaptor =
133            ArgumentCaptor.forClass(IntentFilter.class);
134
135    final ArgumentCaptor<Message> mMessageCaptor = ArgumentCaptor.forClass(Message.class);
136    final ArgumentCaptor<SoftApModeConfiguration> mSoftApModeConfigCaptor =
137            ArgumentCaptor.forClass(SoftApModeConfiguration.class);
138
139    @Mock Context mContext;
140    @Mock WifiInjector mWifiInjector;
141    @Mock Clock mClock;
142    @Mock WifiController mWifiController;
143    @Mock WifiTrafficPoller mWifiTrafficPoller;
144    @Mock WifiStateMachine mWifiStateMachine;
145    @Mock HandlerThread mHandlerThread;
146    @Mock AsyncChannel mAsyncChannel;
147    @Mock Resources mResources;
148    @Mock FrameworkFacade mFrameworkFacade;
149    @Mock WifiLockManager mLockManager;
150    @Mock WifiMulticastLockManager mWifiMulticastLockManager;
151    @Mock WifiLastResortWatchdog mWifiLastResortWatchdog;
152    @Mock WifiBackupRestore mWifiBackupRestore;
153    @Mock WifiMetrics mWifiMetrics;
154    @Mock WifiPermissionsUtil mWifiPermissionsUtil;
155    @Mock WifiSettingsStore mSettingsStore;
156    @Mock ContentResolver mContentResolver;
157    @Mock UserManager mUserManager;
158    @Mock WifiConfiguration mApConfig;
159    @Mock ActivityManager mActivityManager;
160    @Mock AppOpsManager mAppOpsManager;
161    @Mock IBinder mAppBinder;
162    @Mock WifiNotificationController mWifiNotificationController;
163    @Mock LocalOnlyHotspotRequestInfo mRequestInfo;
164    @Mock LocalOnlyHotspotRequestInfo mRequestInfo2;
165
166    @Spy FakeWifiLog mLog;
167
168    private class WifiAsyncChannelTester {
169        private static final String TAG = "WifiAsyncChannelTester";
170        public static final int CHANNEL_STATE_FAILURE = -1;
171        public static final int CHANNEL_STATE_DISCONNECTED = 0;
172        public static final int CHANNEL_STATE_HALF_CONNECTED = 1;
173        public static final int CHANNEL_STATE_FULLY_CONNECTED = 2;
174
175        private int mState = CHANNEL_STATE_DISCONNECTED;
176        private WifiAsyncChannel mChannel;
177        private WifiLog mAsyncTestLog;
178
179        WifiAsyncChannelTester(WifiInjector wifiInjector) {
180            mAsyncTestLog = wifiInjector.makeLog(TAG);
181        }
182
183        public int getChannelState() {
184            return mState;
185        }
186
187        public void connect(final Looper looper, final Messenger messenger,
188                final Handler incomingMessageHandler) {
189            assertEquals("AsyncChannel must be in disconnected state",
190                    CHANNEL_STATE_DISCONNECTED, mState);
191            mChannel = new WifiAsyncChannel(TAG);
192            mChannel.setWifiLog(mLog);
193            Handler handler = new Handler(mLooper.getLooper()) {
194                @Override
195                public void handleMessage(Message msg) {
196                    switch (msg.what) {
197                        case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
198                            if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
199                                mChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
200                                mState = CHANNEL_STATE_HALF_CONNECTED;
201                            } else {
202                                mState = CHANNEL_STATE_FAILURE;
203                            }
204                            break;
205                        case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
206                            mState = CHANNEL_STATE_FULLY_CONNECTED;
207                            break;
208                        case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
209                            mState = CHANNEL_STATE_DISCONNECTED;
210                            break;
211                        default:
212                            incomingMessageHandler.handleMessage(msg);
213                            break;
214                    }
215                }
216            };
217            mChannel.connect(null, handler, messenger);
218        }
219    }
220
221    @Before public void setUp() {
222        MockitoAnnotations.initMocks(this);
223        mLooper = new TestLooper();
224        mHandler = spy(new Handler(mLooper.getLooper()));
225        mAppMessenger = new Messenger(mHandler);
226
227        when(mRequestInfo.getPid()).thenReturn(mPid);
228        when(mRequestInfo2.getPid()).thenReturn(mPid2);
229        when(mWifiInjector.getUserManager()).thenReturn(mUserManager);
230        when(mWifiInjector.getWifiController()).thenReturn(mWifiController);
231        when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics);
232        when(mWifiInjector.getWifiStateMachine()).thenReturn(mWifiStateMachine);
233        when(mWifiStateMachine.syncInitialize(any())).thenReturn(true);
234        when(mWifiInjector.getWifiServiceHandlerThread()).thenReturn(mHandlerThread);
235        when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper());
236        when(mContext.getResources()).thenReturn(mResources);
237        when(mContext.getContentResolver()).thenReturn(mContentResolver);
238        doNothing().when(mFrameworkFacade).registerContentObserver(eq(mContext), any(),
239                anyBoolean(), any());
240        when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager);
241        when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager);
242        when(mFrameworkFacade.getLongSetting(
243                eq(mContext),
244                eq(Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS),
245                anyLong()))
246                .thenReturn(WIFI_BACKGROUND_SCAN_INTERVAL);
247        when(mFrameworkFacade.getStringSetting(
248                eq(mContext),
249                eq(Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST)))
250                .thenReturn(WHITE_LIST_SCAN_PACKAGE_NAME);
251        IPowerManager powerManagerService = mock(IPowerManager.class);
252        mPowerManager = new PowerManager(mContext, powerManagerService, new Handler());
253        when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE);
254        when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
255        WifiAsyncChannel wifiAsyncChannel = new WifiAsyncChannel("WifiServiceImplTest");
256        wifiAsyncChannel.setWifiLog(mLog);
257        when(mFrameworkFacade.makeWifiAsyncChannel(anyString())).thenReturn(wifiAsyncChannel);
258        when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade);
259        when(mWifiInjector.getWifiLockManager()).thenReturn(mLockManager);
260        when(mWifiInjector.getWifiMulticastLockManager()).thenReturn(mWifiMulticastLockManager);
261        when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog);
262        when(mWifiInjector.getWifiBackupRestore()).thenReturn(mWifiBackupRestore);
263        when(mWifiInjector.makeLog(anyString())).thenReturn(mLog);
264        WifiTrafficPoller wifiTrafficPoller = new WifiTrafficPoller(mContext,
265                mLooper.getLooper(), "mockWlan");
266        when(mWifiInjector.getWifiTrafficPoller()).thenReturn(wifiTrafficPoller);
267        when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil);
268        when(mWifiInjector.getWifiSettingsStore()).thenReturn(mSettingsStore);
269        when(mWifiInjector.getClock()).thenReturn(mClock);
270        when(mWifiInjector.getWifiNotificationController()).thenReturn(mWifiNotificationController);
271        mWifiServiceImpl = new WifiServiceImpl(mContext, mWifiInjector, mAsyncChannel);
272        mWifiServiceImpl.setWifiHandlerLogForTest(mLog);
273    }
274
275    @Test
276    public void testRemoveNetworkUnknown() {
277        assertFalse(mWifiServiceImpl.removeNetwork(-1));
278    }
279
280    @Test
281    public void testAsyncChannelHalfConnected() {
282        WifiAsyncChannelTester channelTester = new WifiAsyncChannelTester(mWifiInjector);
283        Handler handler = mock(Handler.class);
284        TestLooper looper = new TestLooper();
285        channelTester.connect(looper.getLooper(), mWifiServiceImpl.getWifiServiceMessenger(),
286                handler);
287        mLooper.dispatchAll();
288        assertEquals("AsyncChannel must be half connected",
289                WifiAsyncChannelTester.CHANNEL_STATE_HALF_CONNECTED,
290                channelTester.getChannelState());
291    }
292
293    /**
294     * Tests the isValid() check for StaticIpConfigurations, ensuring that configurations with null
295     * ipAddress are rejected, and configurations with ipAddresses are valid.
296     */
297    @Test
298    public void testStaticIpConfigurationValidityCheck() {
299        WifiConfiguration conf = WifiConfigurationTestUtil.createOpenNetwork();
300        IpConfiguration ipConf =
301                WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy();
302        conf.setIpConfiguration(ipConf);
303        // Ensure staticIpConfiguration with IP Address is valid
304        assertTrue(mWifiServiceImpl.isValid(conf));
305        ipConf.staticIpConfiguration.ipAddress = null;
306        // Ensure staticIpConfiguration with null IP Address it is not valid
307        conf.setIpConfiguration(ipConf);
308        assertFalse(mWifiServiceImpl.isValid(conf));
309    }
310
311    /**
312     * Ensure WifiMetrics.dump() is the only dump called when 'dumpsys wifi WifiMetricsProto' is
313     * called. This is required to support simple metrics collection via dumpsys
314     */
315    @Test
316    public void testWifiMetricsDump() {
317        mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()),
318                new String[]{mWifiMetrics.PROTO_DUMP_ARG});
319        verify(mWifiMetrics)
320                .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class));
321        verify(mWifiStateMachine, never())
322                .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class));
323    }
324
325
326    /**
327     * Ensure WifiServiceImpl.dump() doesn't throw an NPE when executed with null args
328     */
329    @Test
330    public void testDumpNullArgs() {
331        mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null);
332    }
333
334    /**
335     * Verify that wifi can be enabled by a caller with WIFI_STATE_CHANGE permission when wifi is
336     * off (no hotspot, no airplane mode).
337     */
338    @Test
339    public void testSetWifiEnabledSuccess() throws Exception {
340        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
341        when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
342        assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
343        verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
344    }
345
346    /**
347     * Verify that the CMD_TOGGLE_WIFI message won't be sent if wifi is already on.
348     */
349    @Test
350    public void testSetWifiEnabledNoToggle() throws Exception {
351        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
352        when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false);
353        assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
354        verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
355    }
356
357    /**
358     * Verify a SecurityException is thrown if a caller does not have the correct permission to
359     * toggle wifi.
360     */
361    @Test(expected = SecurityException.class)
362    public void testSetWifiEnableWithoutPermission() throws Exception {
363        doThrow(new SecurityException()).when(mContext)
364                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
365                                                eq("WifiService"));
366        mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true);
367        verify(mWifiStateMachine, never()).syncGetWifiApState();
368    }
369
370    /**
371     * Verify that a call from an app with the NETWORK_SETTINGS permission can enable wifi if we
372     * are in softap mode.
373     */
374    @Test
375    public void testSetWifiEnabledFromNetworkSettingsHolderWhenApEnabled() throws Exception {
376        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
377        when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true);
378        when(mContext.checkCallingOrSelfPermission(
379                eq(android.Manifest.permission.NETWORK_SETTINGS)))
380                        .thenReturn(PackageManager.PERMISSION_GRANTED);
381        assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true));
382        verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
383    }
384
385    /**
386     * Verify that a call from an app cannot enable wifi if we are in softap mode.
387     */
388    @Test
389    public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception {
390        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED);
391        when(mContext.checkCallingOrSelfPermission(
392                eq(android.Manifest.permission.NETWORK_SETTINGS)))
393                        .thenReturn(PackageManager.PERMISSION_DENIED);
394        assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true));
395        verify(mSettingsStore, never()).handleWifiToggled(anyBoolean());
396        verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
397    }
398
399    /**
400     * Verify that wifi can be disabled by a caller with WIFI_STATE_CHANGE permission when wifi is
401     * on.
402     */
403    @Test
404    public void testSetWifiDisabledSuccess() throws Exception {
405        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
406        when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true);
407        assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
408        verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED));
409    }
410
411    /**
412     * Verify that CMD_TOGGLE_WIFI message won't be sent if wifi is already off.
413     */
414    @Test
415    public void testSetWifiDisabledNoToggle() throws Exception {
416        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
417        when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false);
418        assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false));
419        verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED));
420    }
421
422    /**
423     * Verify a SecurityException is thrown if a caller does not have the correct permission to
424     * toggle wifi.
425     */
426    @Test(expected = SecurityException.class)
427    public void testSetWifiDisabledWithoutPermission() throws Exception {
428        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
429        doThrow(new SecurityException()).when(mContext)
430                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
431                                                eq("WifiService"));
432        mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false);
433    }
434
435    /**
436     * Ensure unpermitted callers cannot write the SoftApConfiguration.
437     *
438     * @throws SecurityException
439     */
440    @Test(expected = SecurityException.class)
441    public void testSetWifiApConfigurationNotSavedWithoutPermission() {
442        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
443        WifiConfiguration apConfig = new WifiConfiguration();
444        mWifiServiceImpl.setWifiApConfiguration(apConfig);
445        verify(mWifiStateMachine, never()).setWifiApConfiguration(eq(apConfig));
446    }
447
448    /**
449     * Ensure softap config is written when the caller has the correct permission.
450     */
451    @Test
452    public void testSetWifiApConfigurationSuccess() {
453        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
454        WifiConfiguration apConfig = new WifiConfiguration();
455        mWifiServiceImpl.setWifiApConfiguration(apConfig);
456        verify(mWifiStateMachine).setWifiApConfiguration(eq(apConfig));
457    }
458
459    /**
460     * Ensure that a null config does not overwrite the saved ap config.
461     */
462    @Test
463    public void testSetWifiApConfigurationNullConfigNotSaved() {
464        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
465        mWifiServiceImpl.setWifiApConfiguration(null);
466        verify(mWifiStateMachine, never()).setWifiApConfiguration(isNull(WifiConfiguration.class));
467    }
468
469    /**
470     * Ensure unpermitted callers are not able to retrieve the softap config.
471     *
472     * @throws SecurityException
473     */
474    @Test(expected = SecurityException.class)
475    public void testGetWifiApConfigurationNotReturnedWithoutPermission() {
476        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false);
477        mWifiServiceImpl.getWifiApConfiguration();
478        verify(mWifiStateMachine, never()).syncGetWifiApConfiguration();
479    }
480
481    /**
482     * Ensure permitted callers are able to retrieve the softap config.
483     */
484    @Test
485    public void testGetWifiApConfigurationSuccess() {
486        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
487        WifiConfiguration apConfig = new WifiConfiguration();
488        when(mWifiStateMachine.syncGetWifiApConfiguration()).thenReturn(apConfig);
489        assertEquals(apConfig, mWifiServiceImpl.getWifiApConfiguration());
490    }
491
492    /**
493     * Make sure we do not start wifi if System services have to be restarted to decrypt the device.
494     */
495    @Test
496    public void testWifiControllerDoesNotStartWhenDeviceTriggerResetMainAtBoot() {
497        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(true);
498        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
499        mWifiServiceImpl.checkAndStartWifi();
500        verify(mWifiController, never()).start();
501    }
502
503    /**
504     * Make sure we do start WifiController (wifi disabled) if the device is already decrypted.
505     */
506    @Test
507    public void testWifiControllerStartsWhenDeviceIsDecryptedAtBootWithWifiDisabled() {
508        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
509        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
510        mWifiServiceImpl.checkAndStartWifi();
511        verify(mWifiController).start();
512        verify(mWifiController, never()).sendMessage(CMD_WIFI_TOGGLED);
513    }
514
515    /**
516     * Make sure we do start WifiController (wifi enabled) if the device is already decrypted.
517     */
518    @Test
519    public void testWifiFullyStartsWhenDeviceIsDecryptedAtBootWithWifiEnabled() {
520        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
521        when(mSettingsStore.handleWifiToggled(true)).thenReturn(true);
522        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true);
523        when(mWifiStateMachine.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED);
524        when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED);
525        when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE);
526        mWifiServiceImpl.checkAndStartWifi();
527        verify(mWifiController).start();
528        verify(mWifiController).sendMessage(CMD_WIFI_TOGGLED);
529    }
530
531    /**
532     * Verify setWifiApEnabled works with the correct permissions and a null config.
533     */
534    @Test
535    public void testSetWifiApEnabledWithProperPermissionsWithNullConfig() {
536        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
537        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
538                .thenReturn(false);
539        mWifiServiceImpl.setWifiApEnabled(null, true);
540        verify(mWifiController)
541                .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
542        assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
543    }
544
545    /**
546     * Verify setWifiApEnabled works with correct permissions and a valid config.
547     *
548     * TODO: should really validate that ap configs have a set of basic config settings b/37280779
549     */
550    @Test
551    public void testSetWifiApEnabledWithProperPermissionsWithValidConfig() {
552        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
553        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
554                .thenReturn(false);
555        WifiConfiguration apConfig = new WifiConfiguration();
556        mWifiServiceImpl.setWifiApEnabled(apConfig, true);
557        verify(mWifiController).sendMessage(
558                eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
559        assertEquals(apConfig, mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
560    }
561
562    /**
563     * Verify setWifiApEnabled when disabling softap with correct permissions sends the correct
564     * message to WifiController.
565     */
566    @Test
567    public void testSetWifiApEnabledFalseWithProperPermissionsWithNullConfig() {
568        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
569        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
570                .thenReturn(false);
571        mWifiServiceImpl.setWifiApEnabled(null, false);
572        verify(mWifiController)
573                .sendMessage(eq(CMD_SET_AP), eq(0), eq(0), mSoftApModeConfigCaptor.capture());
574        assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
575    }
576
577    /**
578     * setWifiApEnabled should fail if the provided config is not valid.
579     */
580    @Test
581    public void testSetWifiApEnabledWithProperPermissionInvalidConfigFails() {
582        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
583        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
584                .thenReturn(false);
585        // mApConfig is a mock and the values are not set - triggering the invalid config.  Testing
586        // will be improved when we actually do test softap configs in b/37280779
587        mWifiServiceImpl.setWifiApEnabled(mApConfig, true);
588        verify(mWifiController, never())
589                .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), any(SoftApModeConfiguration.class));
590    }
591
592    /**
593     * setWifiApEnabled should throw a security exception when the caller does not have the correct
594     * permissions.
595     */
596    @Test(expected = SecurityException.class)
597    public void testSetWifiApEnabledThrowsSecurityExceptionWithoutConfigOverridePermission()
598            throws Exception {
599        doThrow(new SecurityException()).when(mContext)
600                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
601                        eq("WifiService"));
602        mWifiServiceImpl.setWifiApEnabled(null, true);
603    }
604
605    /**
606     * setWifiApEnabled should throw a SecurityException when disallow tethering is set for the
607     * user.
608     */
609    @Test(expected = SecurityException.class)
610    public void testSetWifiApEnabledThrowsSecurityExceptionWithDisallowTethering()
611            throws Exception {
612        when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true);
613        when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING)))
614                .thenReturn(true);
615        mWifiServiceImpl.setWifiApEnabled(null, true);
616
617    }
618
619    /**
620     * Verify caller with proper permission can call startSoftAp.
621     */
622    @Test
623    public void testStartSoftApWithPermissionsAndNullConfig() {
624        boolean result = mWifiServiceImpl.startSoftAp(null);
625        assertTrue(result);
626        verify(mWifiController)
627                .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
628        assertNull(mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
629    }
630
631    /**
632     * Verify caller with proper permissions but an invalid config does not start softap.
633     */
634    @Test
635    public void testStartSoftApWithPermissionsAndInvalidConfig() {
636        boolean result = mWifiServiceImpl.startSoftAp(mApConfig);
637        assertFalse(result);
638        verifyZeroInteractions(mWifiController);
639    }
640
641    /**
642     * Verify caller with proper permission and valid config does start softap.
643     */
644    @Test
645    public void testStartSoftApWithPermissionsAndValidConfig() {
646        WifiConfiguration config = new WifiConfiguration();
647        boolean result = mWifiServiceImpl.startSoftAp(config);
648        assertTrue(result);
649        verify(mWifiController)
650                .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), mSoftApModeConfigCaptor.capture());
651        assertEquals(config, mSoftApModeConfigCaptor.getValue().getWifiConfiguration());
652    }
653
654    /**
655     * Verify a SecurityException is thrown when a caller without the correct permission attempts to
656     * start softap.
657     */
658    @Test(expected = SecurityException.class)
659    public void testStartSoftApWithoutPermissionThrowsException() throws Exception {
660        doThrow(new SecurityException()).when(mContext)
661                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_STACK),
662                                                eq("WifiService"));
663        mWifiServiceImpl.startSoftAp(null);
664    }
665
666    /**
667     * Verify caller with proper permission can call stopSoftAp.
668     */
669    @Test
670    public void testStopSoftApWithPermissions() {
671        boolean result = mWifiServiceImpl.stopSoftAp();
672        assertTrue(result);
673        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
674    }
675
676    /**
677     * Verify SecurityException is thrown when a caller without the correct permission attempts to
678     * stop softap.
679     */
680    @Test(expected = SecurityException.class)
681    public void testStopSoftApWithoutPermissionThrowsException() throws Exception {
682        doThrow(new SecurityException()).when(mContext)
683                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_STACK),
684                                                eq("WifiService"));
685        mWifiServiceImpl.stopSoftAp();
686    }
687
688    /**
689     * Ensure foreground apps can always do wifi scans.
690     */
691    @Test
692    public void testWifiScanStartedForeground() {
693        when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn(
694                ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE);
695        mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME);
696        verify(mWifiStateMachine).startScan(
697                anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class));
698    }
699
700    /**
701     * Ensure background apps get throttled when the previous scan is too close.
702     */
703    @Test
704    public void testWifiScanBackgroundThrottled() {
705        when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn(
706                ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
707        long startMs = 1000;
708        when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs);
709        mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME);
710        verify(mWifiStateMachine).startScan(
711                anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class));
712
713        when(mClock.getElapsedSinceBootMillis()).thenReturn(
714                startMs + WIFI_BACKGROUND_SCAN_INTERVAL - 1000);
715        mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME);
716        verify(mWifiStateMachine, times(1)).startScan(
717                anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class));
718    }
719
720    /**
721     * Ensure background apps can do wifi scan when the throttle interval reached.
722     */
723    @Test
724    public void testWifiScanBackgroundNotThrottled() {
725        when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn(
726                ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
727        long startMs = 1000;
728        when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs);
729        mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME);
730        verify(mWifiStateMachine).startScan(
731                anyInt(), eq(0), (ScanSettings) eq(null), any(WorkSource.class));
732
733        when(mClock.getElapsedSinceBootMillis()).thenReturn(
734                startMs + WIFI_BACKGROUND_SCAN_INTERVAL + 1000);
735        mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME);
736        verify(mWifiStateMachine).startScan(
737                anyInt(), eq(1), (ScanSettings) eq(null), any(WorkSource.class));
738    }
739
740    /**
741     * Ensure background apps can do wifi scan when the throttle interval reached.
742     */
743    @Test
744    public void testWifiScanBackgroundWhiteListed() {
745        when(mActivityManager.getPackageImportance(WHITE_LIST_SCAN_PACKAGE_NAME)).thenReturn(
746                ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED);
747        long startMs = 1000;
748        when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs);
749        mWifiServiceImpl.startScan(null, null, WHITE_LIST_SCAN_PACKAGE_NAME);
750        verify(mWifiStateMachine).startScan(
751                anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class));
752
753        when(mClock.getElapsedSinceBootMillis()).thenReturn(
754                startMs + WIFI_BACKGROUND_SCAN_INTERVAL - 1000);
755        mWifiServiceImpl.startScan(null, null, WHITE_LIST_SCAN_PACKAGE_NAME);
756        verify(mWifiStateMachine, times(2)).startScan(
757                anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class));
758    }
759
760    private void registerLOHSRequestFull() {
761        // allow test to proceed without a permission check failure
762        when(mSettingsStore.getLocationModeSetting(mContext))
763                .thenReturn(LOCATION_MODE_HIGH_ACCURACY);
764        try {
765            when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
766        } catch (RemoteException e) { }
767        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING))
768                .thenReturn(false);
769        int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder,
770                TEST_PACKAGE_NAME);
771        assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
772    }
773
774    /**
775     * Verify that the call to startLocalOnlyHotspot returns REQUEST_REGISTERED when successfully
776     * called.
777     */
778    @Test
779    public void testStartLocalOnlyHotspotSingleRegistrationReturnsRequestRegistered() {
780        registerLOHSRequestFull();
781    }
782
783    /**
784     * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not
785     * have the CHANGE_WIFI_STATE permission.
786     */
787    @Test(expected = SecurityException.class)
788    public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() {
789        doThrow(new SecurityException()).when(mContext)
790                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
791                                                eq("WifiService"));
792        mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
793    }
794
795    /**
796     * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not
797     * have Location permission.
798     */
799    @Test(expected = SecurityException.class)
800    public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationPermission() {
801        when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME);
802        doThrow(new SecurityException())
803                .when(mWifiPermissionsUtil).enforceLocationPermission(eq(TEST_PACKAGE_NAME),
804                                                                      anyInt());
805        mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
806    }
807
808    /**
809     * Verify that a call to startLocalOnlyHotspot throws a SecurityException if Location mode is
810     * disabled.
811     */
812    @Test(expected = SecurityException.class)
813    public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationEnabled() {
814        when(mSettingsStore.getLocationModeSetting(mContext)).thenReturn(LOCATION_MODE_OFF);
815        mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
816    }
817
818    /**
819     * Only start LocalOnlyHotspot if the caller is the foreground app at the time of the request.
820     */
821    @Test
822    public void testStartLocalOnlyHotspotFailsIfRequestorNotForegroundApp() throws Exception {
823        when(mSettingsStore.getLocationModeSetting(mContext))
824                .thenReturn(LOCATION_MODE_HIGH_ACCURACY);
825
826        when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(false);
827        int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder,
828                TEST_PACKAGE_NAME);
829        assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result);
830    }
831
832    /**
833     * Do not register the LocalOnlyHotspot request if the caller app cannot be verified as the
834     * foreground app at the time of the request (ie, throws an exception in the check).
835     */
836    @Test
837    public void testStartLocalOnlyHotspotFailsIfForegroundAppCheckThrowsRemoteException()
838            throws Exception {
839        when(mSettingsStore.getLocationModeSetting(mContext))
840                .thenReturn(LOCATION_MODE_HIGH_ACCURACY);
841
842        when(mFrameworkFacade.isAppForeground(anyInt())).thenThrow(new RemoteException());
843        int result = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder,
844                TEST_PACKAGE_NAME);
845        assertEquals(LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE, result);
846    }
847
848    /**
849     * Only start LocalOnlyHotspot if we are not tethering.
850     */
851    @Test
852    public void testHotspotDoesNotStartWhenAlreadyTethering() throws Exception {
853        when(mSettingsStore.getLocationModeSetting(mContext))
854                            .thenReturn(LOCATION_MODE_HIGH_ACCURACY);
855        when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
856        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
857        mLooper.dispatchAll();
858        int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
859                mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
860        assertEquals(ERROR_INCOMPATIBLE_MODE, returnCode);
861    }
862
863    /**
864     * Only start LocalOnlyHotspot if admin setting does not disallow tethering.
865     */
866    @Test
867    public void testHotspotDoesNotStartWhenTetheringDisallowed() throws Exception {
868        when(mSettingsStore.getLocationModeSetting(mContext))
869                .thenReturn(LOCATION_MODE_HIGH_ACCURACY);
870        when(mFrameworkFacade.isAppForeground(anyInt())).thenReturn(true);
871        when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING))
872                .thenReturn(true);
873        int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(
874                mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
875        assertEquals(ERROR_TETHERING_DISALLOWED, returnCode);
876    }
877
878    /**
879     * Verify that callers can only have one registered LOHS request.
880     */
881    @Test(expected = IllegalStateException.class)
882    public void testStartLocalOnlyHotspotThrowsExceptionWhenCallerAlreadyRegistered() {
883        registerLOHSRequestFull();
884
885        // now do the second request that will fail
886        mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder, TEST_PACKAGE_NAME);
887    }
888
889    /**
890     * Verify that the call to stopLocalOnlyHotspot does not do anything when there aren't any
891     * registered callers.
892     */
893    @Test
894    public void testStopLocalOnlyHotspotDoesNothingWithoutRegisteredRequests() {
895        // allow test to proceed without a permission check failure
896        mWifiServiceImpl.stopLocalOnlyHotspot();
897        // there is nothing registered, so this shouldn't do anything
898        verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), anyInt(), anyInt());
899    }
900
901    /**
902     * Verify that the call to stopLocalOnlyHotspot does not do anything when one caller unregisters
903     * but there is still an active request
904     */
905    @Test
906    public void testStopLocalOnlyHotspotDoesNothingWithARemainingRegisteredRequest() {
907        // register a request that will remain after the stopLOHS call
908        mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo);
909
910        registerLOHSRequestFull();
911
912        // Since we are calling with the same pid, the second register call will be removed
913        mWifiServiceImpl.stopLocalOnlyHotspot();
914        // there is still a valid registered request - do not tear down LOHS
915        verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), anyInt(), anyInt());
916    }
917
918    /**
919     * Verify that the call to stopLocalOnlyHotspot sends a message to WifiController to stop
920     * the softAp when there is one registered caller when that caller is removed.
921     */
922    @Test
923    public void testStopLocalOnlyHotspotTriggersSoftApStopWithOneRegisteredRequest() {
924        registerLOHSRequestFull();
925        verify(mWifiController)
926                .sendMessage(eq(CMD_SET_AP), eq(1), eq(0), any(SoftApModeConfiguration.class));
927
928        mWifiServiceImpl.stopLocalOnlyHotspot();
929        // there is was only one request registered, we should tear down softap
930        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
931    }
932
933    /**
934     * Verify that a call to stopLocalOnlyHotspot throws a SecurityException if the caller does not
935     * have the CHANGE_WIFI_STATE permission.
936     */
937    @Test(expected = SecurityException.class)
938    public void testStopLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() {
939        doThrow(new SecurityException()).when(mContext)
940                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE),
941                                                eq("WifiService"));
942        mWifiServiceImpl.stopLocalOnlyHotspot();
943    }
944
945    /**
946     * Verify that WifiServiceImpl does not send the stop ap message if there were no
947     * pending LOHS requests upon a binder death callback.
948     */
949    @Test
950    public void testServiceImplNotCalledWhenBinderDeathTriggeredNoRequests() {
951        LocalOnlyRequestorCallback binderDeathCallback =
952                mWifiServiceImpl.new LocalOnlyRequestorCallback();
953
954        binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo);
955        verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
956    }
957
958    /**
959     * Verify that WifiServiceImpl does not send the stop ap message if there are remaining
960     * registered LOHS requests upon a binder death callback.  Additionally verify that softap mode
961     * will be stopped if that remaining request is removed (to verify the binder death properly
962     * cleared the requestor that died).
963     */
964    @Test
965    public void testServiceImplNotCalledWhenBinderDeathTriggeredWithRegisteredRequests() {
966        LocalOnlyRequestorCallback binderDeathCallback =
967                mWifiServiceImpl.new LocalOnlyRequestorCallback();
968
969        // registering a request directly from the test will not trigger a message to start
970        // softap mode
971        mWifiServiceImpl.registerLOHSForTest(mPid, mRequestInfo);
972
973        registerLOHSRequestFull();
974
975        binderDeathCallback.onLocalOnlyHotspotRequestorDeath(mRequestInfo);
976        verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), anyInt(), anyInt());
977
978        reset(mWifiController);
979
980        // now stop as the second request and confirm CMD_SET_AP will be sent to make sure binder
981        // death requestor was removed
982        mWifiServiceImpl.stopLocalOnlyHotspot();
983        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
984    }
985
986    private class IntentFilterMatcher implements ArgumentMatcher<IntentFilter> {
987        @Override
988        public boolean matches(IntentFilter filter) {
989            return filter.hasAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
990        }
991    }
992
993    /**
994     * Verify that onFailed is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
995     * broadcast is received.
996     */
997    @Test
998    public void testRegisteredCallbacksTriggeredOnSoftApFailureGeneric() throws Exception {
999        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1000        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1001        mWifiServiceImpl.checkAndStartWifi();
1002
1003        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1004                (IntentFilter) argThat(new IntentFilterMatcher()));
1005
1006        registerLOHSRequestFull();
1007
1008        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1009                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_GENERAL,
1010                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1011        mLooper.dispatchAll();
1012        verify(mHandler).handleMessage(mMessageCaptor.capture());
1013        Message message = mMessageCaptor.getValue();
1014        assertEquals(HOTSPOT_FAILED, message.what);
1015        assertEquals(ERROR_GENERIC, message.arg1);
1016    }
1017
1018    /**
1019     * Verify that onFailed is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
1020     * broadcast is received with the SAP_START_FAILURE_NO_CHANNEL error.
1021     */
1022    @Test
1023    public void testRegisteredCallbacksTriggeredOnSoftApFailureNoChannel() throws Exception {
1024        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1025        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1026        mWifiServiceImpl.checkAndStartWifi();
1027
1028        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1029                (IntentFilter) argThat(new IntentFilterMatcher()));
1030
1031        registerLOHSRequestFull();
1032
1033        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1034                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_DISABLED, SAP_START_FAILURE_NO_CHANNEL,
1035                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1036
1037        mLooper.dispatchAll();
1038        verify(mHandler).handleMessage(mMessageCaptor.capture());
1039        Message message = mMessageCaptor.getValue();
1040        assertEquals(HOTSPOT_FAILED, message.what);
1041        assertEquals(ERROR_NO_CHANNEL, message.arg1);
1042    }
1043
1044    /**
1045     * Verify that onStopped is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
1046     * broadcast is received with WIFI_AP_STATE_DISABLING and LOHS was active.
1047     */
1048    @Test
1049    public void testRegisteredCallbacksTriggeredOnSoftApDisabling() throws Exception {
1050        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1051        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1052        mWifiServiceImpl.checkAndStartWifi();
1053
1054        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1055                (IntentFilter) argThat(new IntentFilterMatcher()));
1056
1057        registerLOHSRequestFull();
1058
1059        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1060        mLooper.dispatchAll();
1061        verify(mHandler).handleMessage(mMessageCaptor.capture());
1062        Message message = mMessageCaptor.getValue();
1063        assertEquals(HOTSPOT_STARTED, message.what);
1064        reset(mHandler);
1065
1066        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1067                WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
1068                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1069
1070        mLooper.dispatchAll();
1071        verify(mHandler).handleMessage(mMessageCaptor.capture());
1072        message = mMessageCaptor.getValue();
1073        assertEquals(HOTSPOT_STOPPED, message.what);
1074    }
1075
1076
1077    /**
1078     * Verify that onStopped is called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
1079     * broadcast is received with WIFI_AP_STATE_DISABLED and LOHS was enabled.
1080     */
1081    @Test
1082    public void testRegisteredCallbacksTriggeredOnSoftApDisabled() throws Exception {
1083        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1084        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1085        mWifiServiceImpl.checkAndStartWifi();
1086
1087        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1088                (IntentFilter) argThat(new IntentFilterMatcher()));
1089
1090        registerLOHSRequestFull();
1091
1092        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1093        mLooper.dispatchAll();
1094        verify(mHandler).handleMessage(mMessageCaptor.capture());
1095        Message message = mMessageCaptor.getValue();
1096        assertEquals(HOTSPOT_STARTED, message.what);
1097        reset(mHandler);
1098
1099        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1100                WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
1101                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1102
1103        mLooper.dispatchAll();
1104        verify(mHandler).handleMessage(mMessageCaptor.capture());
1105        message = mMessageCaptor.getValue();
1106        assertEquals(HOTSPOT_STOPPED, message.what);
1107    }
1108
1109    /**
1110     * Verify that no callbacks are called for registered LOHS callers when a WIFI_AP_STATE_CHANGE
1111     * broadcast is received and the softap started.
1112     */
1113    @Test
1114    public void testRegisteredCallbacksNotTriggeredOnSoftApStart() throws Exception {
1115        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1116        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1117        mWifiServiceImpl.checkAndStartWifi();
1118
1119        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1120                (IntentFilter) argThat(new IntentFilterMatcher()));
1121
1122        registerLOHSRequestFull();
1123
1124        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1125                WIFI_AP_STATE_ENABLED, WIFI_AP_STATE_DISABLED, HOTSPOT_NO_ERROR, WIFI_IFACE_NAME,
1126                IFACE_IP_MODE_LOCAL_ONLY);
1127
1128        mLooper.dispatchAll();
1129        verifyNoMoreInteractions(mHandler);
1130    }
1131
1132    /**
1133     * Verify that onStopped is called only once for registered LOHS callers when
1134     * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_DISABLING and
1135     * WIFI_AP_STATE_DISABLED when LOHS was enabled.
1136     */
1137    @Test
1138    public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApDisabling() throws Exception {
1139        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1140        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1141        mWifiServiceImpl.checkAndStartWifi();
1142
1143        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1144                (IntentFilter) argThat(new IntentFilterMatcher()));
1145
1146        registerLOHSRequestFull();
1147
1148        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1149        mLooper.dispatchAll();
1150        verify(mHandler).handleMessage(mMessageCaptor.capture());
1151        Message message = mMessageCaptor.getValue();
1152        assertEquals(HOTSPOT_STARTED, message.what);
1153        reset(mHandler);
1154
1155        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1156                WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
1157                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1158        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1159                WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
1160                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1161
1162        mLooper.dispatchAll();
1163        verify(mHandler).handleMessage(mMessageCaptor.capture());
1164        message = mMessageCaptor.getValue();
1165        assertEquals(HOTSPOT_STOPPED, message.what);
1166    }
1167
1168    /**
1169     * Verify that onFailed is called only once for registered LOHS callers when
1170     * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_FAILED twice.
1171     */
1172    @Test
1173    public void testRegisteredCallbacksTriggeredOnlyOnceWhenSoftApFailsTwice() throws Exception {
1174        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1175        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1176        mWifiServiceImpl.checkAndStartWifi();
1177
1178        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1179                (IntentFilter) argThat(new IntentFilterMatcher()));
1180
1181        registerLOHSRequestFull();
1182
1183        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1184                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
1185                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1186        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1187                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
1188                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1189
1190        mLooper.dispatchAll();
1191        verify(mHandler).handleMessage(mMessageCaptor.capture());
1192        Message message = mMessageCaptor.getValue();
1193        assertEquals(HOTSPOT_FAILED, message.what);
1194        assertEquals(ERROR_GENERIC, message.arg1);
1195    }
1196
1197    /**
1198     * Verify that onFailed is called for all registered LOHS callers when
1199     * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_FAILED.
1200     */
1201    @Test
1202    public void testAllRegisteredCallbacksTriggeredWhenSoftApFails() throws Exception {
1203        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1204        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1205        mWifiServiceImpl.checkAndStartWifi();
1206
1207        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1208                (IntentFilter) argThat(new IntentFilterMatcher()));
1209
1210        // make an additional request for this test
1211        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1212
1213        registerLOHSRequestFull();
1214
1215        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1216                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
1217                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1218        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1219                WIFI_AP_STATE_FAILED, WIFI_AP_STATE_FAILED, ERROR_GENERIC,
1220                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1221
1222        verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
1223        mLooper.dispatchAll();
1224        verify(mHandler).handleMessage(mMessageCaptor.capture());
1225        Message message = mMessageCaptor.getValue();
1226        assertEquals(HOTSPOT_FAILED, message.what);
1227        assertEquals(ERROR_GENERIC, message.arg1);
1228    }
1229
1230    /**
1231     * Verify that onStopped is called for all registered LOHS callers when
1232     * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_DISABLED when LOHS was
1233     * active.
1234     */
1235    @Test
1236    public void testAllRegisteredCallbacksTriggeredWhenSoftApStops() throws Exception {
1237        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1238        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1239        mWifiServiceImpl.checkAndStartWifi();
1240
1241        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1242                (IntentFilter) argThat(new IntentFilterMatcher()));
1243
1244        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1245
1246        registerLOHSRequestFull();
1247
1248        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1249        mLooper.dispatchAll();
1250        verify(mRequestInfo).sendHotspotStartedMessage(any());
1251        verify(mHandler).handleMessage(mMessageCaptor.capture());
1252        Message message = mMessageCaptor.getValue();
1253        assertEquals(HOTSPOT_STARTED, message.what);
1254        reset(mHandler);
1255
1256        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1257                WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
1258                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1259        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1260                WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
1261                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1262
1263        verify(mRequestInfo).sendHotspotStoppedMessage();
1264        mLooper.dispatchAll();
1265        verify(mHandler).handleMessage(mMessageCaptor.capture());
1266        message = mMessageCaptor.getValue();
1267        assertEquals(HOTSPOT_STOPPED, message.what);
1268    }
1269
1270    /**
1271     * Verify that onFailed is called for all registered LOHS callers when
1272     * WIFI_AP_STATE_CHANGE broadcasts are received with WIFI_AP_STATE_DISABLED when LOHS was
1273     * not active.
1274     */
1275    @Test
1276    public void testAllRegisteredCallbacksTriggeredWhenSoftApStopsLOHSNotActive() throws Exception {
1277        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1278        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1279        mWifiServiceImpl.checkAndStartWifi();
1280
1281        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1282                (IntentFilter) argThat(new IntentFilterMatcher()));
1283
1284        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1285        mWifiServiceImpl.registerLOHSForTest(TEST_PID2, mRequestInfo2);
1286
1287        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1288                WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
1289                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1290        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1291                WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
1292                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1293
1294        verify(mRequestInfo).sendHotspotFailedMessage(ERROR_GENERIC);
1295        verify(mRequestInfo2).sendHotspotFailedMessage(ERROR_GENERIC);
1296    }
1297
1298    /**
1299     * Verify that if we do not have registered LOHS requestors and we receive an update that LOHS
1300     * is up and ready for use, we tell WifiController to tear it down.  This can happen if softap
1301     * mode fails to come up properly and we get an onFailed message for a tethering call and we
1302     * had registered callers for LOHS.
1303     */
1304    @Test
1305    public void testLOHSReadyWithoutRegisteredRequestsStopsSoftApMode() {
1306        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1307        mLooper.dispatchAll();
1308
1309        verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0));
1310    }
1311
1312    /**
1313     * Verify that all registered LOHS requestors are notified via a HOTSPOT_STARTED message that
1314     * the hotspot is up and ready to use.
1315     */
1316    @Test
1317    public void testRegisteredLocalOnlyHotspotRequestorsGetOnStartedCallbackWhenReady()
1318            throws Exception {
1319        registerLOHSRequestFull();
1320
1321        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1322
1323        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1324        mLooper.dispatchAll();
1325        verify(mRequestInfo).sendHotspotStartedMessage(any(WifiConfiguration.class));
1326
1327        mLooper.dispatchAll();
1328        verify(mHandler).handleMessage(mMessageCaptor.capture());
1329        Message message = mMessageCaptor.getValue();
1330        assertEquals(HOTSPOT_STARTED, message.what);
1331        assertNotNull((WifiConfiguration) message.obj);
1332    }
1333
1334    /**
1335     * Verify that if a LOHS is already active, a new call to register a request will trigger the
1336     * onStarted callback.
1337     */
1338    @Test
1339    public void testRegisterLocalOnlyHotspotRequestAfterAlreadyStartedGetsOnStartedCallback()
1340            throws Exception {
1341        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1342
1343        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1344        mLooper.dispatchAll();
1345
1346        registerLOHSRequestFull();
1347
1348        mLooper.dispatchAll();
1349
1350        verify(mHandler).handleMessage(mMessageCaptor.capture());
1351        Message message = mMessageCaptor.getValue();
1352        assertEquals(HOTSPOT_STARTED, message.what);
1353        // since the first request was registered out of band, the config will be null
1354        assertNull((WifiConfiguration) message.obj);
1355    }
1356
1357    /**
1358     * Verify that if a LOHS request is active and we receive an update with an ip mode
1359     * configuration error, callers are notified via the onFailed callback with the generic
1360     * error and are unregistered.
1361     */
1362    @Test
1363    public void testCallOnFailedLocalOnlyHotspotRequestWhenIpConfigFails() throws Exception {
1364        registerLOHSRequestFull();
1365
1366        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR);
1367        mLooper.dispatchAll();
1368
1369        verify(mHandler).handleMessage(mMessageCaptor.capture());
1370        Message message = mMessageCaptor.getValue();
1371        assertEquals(HOTSPOT_FAILED, message.what);
1372        assertEquals(ERROR_GENERIC, message.arg1);
1373
1374        // sendMessage should only happen once since the requestor should be unregistered
1375        reset(mHandler);
1376
1377        // send HOTSPOT_FAILED message should only happen once since the requestor should be
1378        // unregistered
1379        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_CONFIGURATION_ERROR);
1380        mLooper.dispatchAll();
1381        verify(mHandler, never()).handleMessage(any(Message.class));
1382    }
1383
1384    /**
1385     * Verify that if a LOHS request is active and tethering starts, callers are notified on the
1386     * incompatible mode and are unregistered.
1387     */
1388    @Test
1389    public void testCallOnFailedLocalOnlyHotspotRequestWhenTetheringStarts() throws Exception {
1390        registerLOHSRequestFull();
1391
1392        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
1393        mLooper.dispatchAll();
1394
1395        verify(mHandler).handleMessage(mMessageCaptor.capture());
1396        Message message = mMessageCaptor.getValue();
1397        assertEquals(HOTSPOT_FAILED, message.what);
1398        assertEquals(ERROR_INCOMPATIBLE_MODE, message.arg1);
1399
1400        // sendMessage should only happen once since the requestor should be unregistered
1401        reset(mHandler);
1402
1403        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_TETHERED);
1404        mLooper.dispatchAll();
1405        verify(mHandler, never()).handleMessage(any(Message.class));
1406    }
1407
1408    /**
1409     * Verify that if LOHS is disabled, a new call to register a request will not trigger the
1410     * onStopped callback.
1411     */
1412    @Test
1413    public void testRegisterLocalOnlyHotspotRequestWhenStoppedDoesNotGetOnStoppedCallback()
1414            throws Exception {
1415        registerLOHSRequestFull();
1416        mLooper.dispatchAll();
1417
1418        verify(mHandler, never()).handleMessage(any(Message.class));
1419    }
1420
1421    /**
1422     * Verify that if a LOHS was active and then stopped, a new call to register a request will
1423     * not trigger the onStarted callback.
1424     */
1425    @Test
1426    public void testRegisterLocalOnlyHotspotRequestAfterStoppedNoOnStartedCallback()
1427            throws Exception {
1428        when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false);
1429        when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false);
1430        mWifiServiceImpl.checkAndStartWifi();
1431        verify(mContext).registerReceiver(mBroadcastReceiverCaptor.capture(),
1432                (IntentFilter) argThat(new IntentFilterMatcher()));
1433
1434        // register a request so we don't drop the LOHS interface ip update
1435        mWifiServiceImpl.registerLOHSForTest(TEST_PID, mRequestInfo);
1436
1437        mWifiServiceImpl.updateInterfaceIpState(WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1438        mLooper.dispatchAll();
1439
1440        registerLOHSRequestFull();
1441        mLooper.dispatchAll();
1442
1443        verify(mHandler).handleMessage(mMessageCaptor.capture());
1444        assertEquals(HOTSPOT_STARTED, mMessageCaptor.getValue().what);
1445
1446        reset(mHandler);
1447
1448        // now stop the hotspot
1449        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1450                WIFI_AP_STATE_DISABLING, WIFI_AP_STATE_ENABLED, HOTSPOT_NO_ERROR,
1451                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1452        TestUtil.sendWifiApStateChanged(mBroadcastReceiverCaptor.getValue(), mContext,
1453                WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING, HOTSPOT_NO_ERROR,
1454                WIFI_IFACE_NAME, IFACE_IP_MODE_LOCAL_ONLY);
1455        mLooper.dispatchAll();
1456        verify(mHandler).handleMessage(mMessageCaptor.capture());
1457        assertEquals(HOTSPOT_STOPPED, mMessageCaptor.getValue().what);
1458
1459        reset(mHandler);
1460
1461        // now register a new caller - they should not get the onStarted callback
1462        Messenger messenger2 = new Messenger(mHandler);
1463        IBinder binder2 = mock(IBinder.class);
1464
1465        int result = mWifiServiceImpl.startLocalOnlyHotspot(messenger2, binder2, TEST_PACKAGE_NAME);
1466        assertEquals(LocalOnlyHotspotCallback.REQUEST_REGISTERED, result);
1467        mLooper.dispatchAll();
1468
1469        verify(mHandler, never()).handleMessage(any(Message.class));
1470    }
1471
1472    /**
1473     * Verify that a call to startWatchLocalOnlyHotspot is only allowed from callers with the
1474     * signature only NETWORK_SETTINGS permission.
1475     *
1476     * This test is expecting the permission check to enforce the permission and throw a
1477     * SecurityException for callers without the permission.  This exception should be bubbled up to
1478     * the caller of startLocalOnlyHotspot.
1479     */
1480    @Test(expected = SecurityException.class)
1481    public void testStartWatchLocalOnlyHotspotNotApprovedCaller() {
1482        doThrow(new SecurityException()).when(mContext)
1483                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
1484                                                eq("WifiService"));
1485        mWifiServiceImpl.startWatchLocalOnlyHotspot(mAppMessenger, mAppBinder);
1486    }
1487
1488    /**
1489     * Verify that the call to startWatchLocalOnlyHotspot throws the UnsupportedOperationException
1490     * when called until the implementation is complete.
1491     */
1492    @Test(expected = UnsupportedOperationException.class)
1493    public void testStartWatchLocalOnlyHotspotNotSupported() {
1494        mWifiServiceImpl.startWatchLocalOnlyHotspot(mAppMessenger, mAppBinder);
1495    }
1496
1497    /**
1498     * Verify that a call to stopWatchLocalOnlyHotspot is only allowed from callers with the
1499     * signature only NETWORK_SETTINGS permission.
1500     */
1501    @Test(expected = SecurityException.class)
1502    public void testStopWatchLocalOnlyHotspotNotApprovedCaller() {
1503        doThrow(new SecurityException()).when(mContext)
1504                .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_SETTINGS),
1505                                                eq("WifiService"));
1506        mWifiServiceImpl.stopWatchLocalOnlyHotspot();
1507    }
1508
1509    /**
1510     * Verify that the call to stopWatchLocalOnlyHotspot throws the UnsupportedOperationException
1511     * until the implementation is complete.
1512     */
1513    @Test(expected = UnsupportedOperationException.class)
1514    public void testStopWatchLocalOnlyHotspotNotSupported() {
1515        mWifiServiceImpl.stopWatchLocalOnlyHotspot();
1516    }
1517
1518    /**
1519     * Verify that the call to addOrUpdateNetwork for installing Passpoint profile is redirected
1520     * to the Passpoint specific API addOrUpdatePasspointConfiguration.
1521     */
1522    @Test
1523    public void testAddPasspointProfileViaAddNetwork() throws Exception {
1524        WifiConfiguration config = WifiConfigurationTestUtil.createPasspointNetwork();
1525        config.enterpriseConfig.setEapMethod(WifiEnterpriseConfig.Eap.TLS);
1526        when(mResources.getBoolean(com.android.internal.R.bool.config_wifi_hotspot2_enabled))
1527                .thenReturn(true);
1528
1529        when(mWifiStateMachine.syncAddOrUpdatePasspointConfig(any(),
1530                any(PasspointConfiguration.class), anyInt())).thenReturn(true);
1531        assertEquals(0, mWifiServiceImpl.addOrUpdateNetwork(config));
1532        verify(mWifiStateMachine).syncAddOrUpdatePasspointConfig(any(),
1533                any(PasspointConfiguration.class), anyInt());
1534        reset(mWifiStateMachine);
1535
1536        when(mWifiStateMachine.syncAddOrUpdatePasspointConfig(any(),
1537                any(PasspointConfiguration.class), anyInt())).thenReturn(false);
1538        assertEquals(-1, mWifiServiceImpl.addOrUpdateNetwork(config));
1539        verify(mWifiStateMachine).syncAddOrUpdatePasspointConfig(any(),
1540                any(PasspointConfiguration.class), anyInt());
1541    }
1542}
1543