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