WifiServiceImplTest.java revision 92d08fb607bcf4d9f0dac478f4c14ec45363bfc6
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.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 20import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 21import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED; 22import static android.provider.Settings.Secure.LOCATION_MODE_HIGH_ACCURACY; 23import static android.provider.Settings.Secure.LOCATION_MODE_OFF; 24 25import static com.android.server.wifi.WifiController.CMD_SET_AP; 26import static com.android.server.wifi.WifiController.CMD_WIFI_TOGGLED; 27 28import static org.junit.Assert.assertEquals; 29import static org.junit.Assert.assertFalse; 30import static org.junit.Assert.assertTrue; 31import static org.mockito.Matchers.any; 32import static org.mockito.Matchers.anyString; 33import static org.mockito.Matchers.eq; 34import static org.mockito.Mockito.*; 35 36import android.app.ActivityManager; 37import android.app.AppOpsManager; 38import android.content.ContentResolver; 39import android.content.Context; 40import android.content.res.Resources; 41import android.net.IpConfiguration; 42import android.net.wifi.ScanSettings; 43import android.net.wifi.WifiConfiguration; 44import android.net.wifi.WifiManager; 45import android.os.Handler; 46import android.os.HandlerThread; 47import android.os.IBinder; 48import android.os.IPowerManager; 49import android.os.Looper; 50import android.os.Message; 51import android.os.Messenger; 52import android.os.PowerManager; 53import android.os.UserManager; 54import android.os.WorkSource; 55import android.os.test.TestLooper; 56import android.provider.Settings; 57import android.test.suitebuilder.annotation.SmallTest; 58 59import com.android.internal.util.AsyncChannel; 60import com.android.server.wifi.util.WifiAsyncChannel; 61import com.android.server.wifi.util.WifiPermissionsUtil; 62 63import org.junit.Before; 64import org.junit.Test; 65import org.mockito.Mock; 66import org.mockito.MockitoAnnotations; 67import org.mockito.Spy; 68 69import java.io.FileDescriptor; 70import java.io.PrintWriter; 71import java.io.StringWriter; 72 73/** 74 * Unit tests for {@link WifiServiceImpl}. 75 * 76 * Note: this is intended to build up over time and will not immediately cover the entire file. 77 */ 78@SmallTest 79public class WifiServiceImplTest { 80 81 private static final String TAG = "WifiServiceImplTest"; 82 private static final String SCAN_PACKAGE_NAME = "scanPackage"; 83 private static final String WHITE_LIST_SCAN_PACKAGE_NAME = "whiteListScanPackage"; 84 private static final int DEFAULT_VERBOSE_LOGGING = 0; 85 private static final long WIFI_BACKGROUND_SCAN_INTERVAL = 10000; 86 private static final String ANDROID_SYSTEM_PACKAGE = "android"; 87 private static final String TEST_PACKAGE_NAME = "TestPackage"; 88 private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; 89 private static final String SYSUI_PACKAGE_NAME = "com.android.systemui"; 90 91 private WifiServiceImpl mWifiServiceImpl; 92 private TestLooper mLooper; 93 private PowerManager mPowerManager; 94 private Handler mHandler; 95 private Messenger mAppMessenger; 96 97 @Mock Context mContext; 98 @Mock WifiInjector mWifiInjector; 99 @Mock Clock mClock; 100 @Mock WifiController mWifiController; 101 @Mock WifiTrafficPoller mWifiTrafficPoller; 102 @Mock WifiStateMachine mWifiStateMachine; 103 @Mock HandlerThread mHandlerThread; 104 @Mock AsyncChannel mAsyncChannel; 105 @Mock Resources mResources; 106 @Mock FrameworkFacade mFrameworkFacade; 107 @Mock WifiLockManager mLockManager; 108 @Mock WifiMulticastLockManager mWifiMulticastLockManager; 109 @Mock WifiLastResortWatchdog mWifiLastResortWatchdog; 110 @Mock WifiBackupRestore mWifiBackupRestore; 111 @Mock WifiMetrics mWifiMetrics; 112 @Mock WifiPermissionsUtil mWifiPermissionsUtil; 113 @Mock WifiSettingsStore mSettingsStore; 114 @Mock ContentResolver mContentResolver; 115 @Mock UserManager mUserManager; 116 @Mock WifiConfiguration mApConfig; 117 @Mock ActivityManager mActivityManager; 118 @Mock AppOpsManager mAppOpsManager; 119 @Mock IBinder mAppBinder; 120 @Mock WifiNotificationController mWifiNotificationController; 121 122 @Spy FakeWifiLog mLog; 123 124 private class WifiAsyncChannelTester { 125 private static final String TAG = "WifiAsyncChannelTester"; 126 public static final int CHANNEL_STATE_FAILURE = -1; 127 public static final int CHANNEL_STATE_DISCONNECTED = 0; 128 public static final int CHANNEL_STATE_HALF_CONNECTED = 1; 129 public static final int CHANNEL_STATE_FULLY_CONNECTED = 2; 130 131 private int mState = CHANNEL_STATE_DISCONNECTED; 132 private WifiAsyncChannel mChannel; 133 private WifiLog mAsyncTestLog; 134 135 WifiAsyncChannelTester(WifiInjector wifiInjector) { 136 mAsyncTestLog = wifiInjector.makeLog(TAG); 137 } 138 139 public int getChannelState() { 140 return mState; 141 } 142 143 public void connect(final Looper looper, final Messenger messenger, 144 final Handler incomingMessageHandler) { 145 assertEquals("AsyncChannel must be in disconnected state", 146 CHANNEL_STATE_DISCONNECTED, mState); 147 mChannel = new WifiAsyncChannel(TAG); 148 mChannel.setWifiLog(mLog); 149 Handler handler = new Handler(mLooper.getLooper()) { 150 @Override 151 public void handleMessage(Message msg) { 152 switch (msg.what) { 153 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 154 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 155 mChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); 156 mState = CHANNEL_STATE_HALF_CONNECTED; 157 } else { 158 mState = CHANNEL_STATE_FAILURE; 159 } 160 break; 161 case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED: 162 mState = CHANNEL_STATE_FULLY_CONNECTED; 163 break; 164 case AsyncChannel.CMD_CHANNEL_DISCONNECTED: 165 mState = CHANNEL_STATE_DISCONNECTED; 166 break; 167 default: 168 incomingMessageHandler.handleMessage(msg); 169 break; 170 } 171 } 172 }; 173 mChannel.connect(null, handler, messenger); 174 } 175 } 176 177 @Before public void setUp() { 178 MockitoAnnotations.initMocks(this); 179 mLooper = new TestLooper(); 180 mHandler = new Handler(mLooper.getLooper()); 181 mAppMessenger = new Messenger(mHandler); 182 183 when(mWifiInjector.getUserManager()).thenReturn(mUserManager); 184 when(mWifiInjector.getWifiController()).thenReturn(mWifiController); 185 when(mWifiInjector.getWifiMetrics()).thenReturn(mWifiMetrics); 186 when(mWifiInjector.getWifiStateMachine()).thenReturn(mWifiStateMachine); 187 when(mWifiStateMachine.syncInitialize(any())).thenReturn(true); 188 when(mWifiInjector.getWifiServiceHandlerThread()).thenReturn(mHandlerThread); 189 when(mHandlerThread.getLooper()).thenReturn(mLooper.getLooper()); 190 when(mContext.getResources()).thenReturn(mResources); 191 when(mContext.getContentResolver()).thenReturn(mContentResolver); 192 doNothing().when(mFrameworkFacade).registerContentObserver(eq(mContext), any(), 193 anyBoolean(), any()); 194 when(mContext.getSystemService(Context.ACTIVITY_SERVICE)).thenReturn(mActivityManager); 195 when(mContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mAppOpsManager); 196 when(mFrameworkFacade.getLongSetting( 197 eq(mContext), 198 eq(Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_INTERVAL_MS), 199 anyLong())) 200 .thenReturn(WIFI_BACKGROUND_SCAN_INTERVAL); 201 when(mFrameworkFacade.getStringSetting( 202 eq(mContext), 203 eq(Settings.Global.WIFI_SCAN_BACKGROUND_THROTTLE_PACKAGE_WHITELIST))) 204 .thenReturn(WHITE_LIST_SCAN_PACKAGE_NAME); 205 IPowerManager powerManagerService = mock(IPowerManager.class); 206 mPowerManager = new PowerManager(mContext, powerManagerService, new Handler()); 207 when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE); 208 when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager); 209 WifiAsyncChannel wifiAsyncChannel = new WifiAsyncChannel("WifiServiceImplTest"); 210 wifiAsyncChannel.setWifiLog(mLog); 211 when(mFrameworkFacade.makeWifiAsyncChannel(anyString())).thenReturn(wifiAsyncChannel); 212 when(mWifiInjector.getFrameworkFacade()).thenReturn(mFrameworkFacade); 213 when(mWifiInjector.getWifiLockManager()).thenReturn(mLockManager); 214 when(mWifiInjector.getWifiMulticastLockManager()).thenReturn(mWifiMulticastLockManager); 215 when(mWifiInjector.getWifiLastResortWatchdog()).thenReturn(mWifiLastResortWatchdog); 216 when(mWifiInjector.getWifiBackupRestore()).thenReturn(mWifiBackupRestore); 217 when(mWifiInjector.makeLog(anyString())).thenReturn(mLog); 218 WifiTrafficPoller wifiTrafficPoller = new WifiTrafficPoller(mContext, 219 mLooper.getLooper(), "mockWlan"); 220 when(mWifiInjector.getWifiTrafficPoller()).thenReturn(wifiTrafficPoller); 221 when(mWifiInjector.getWifiPermissionsUtil()).thenReturn(mWifiPermissionsUtil); 222 when(mWifiInjector.getWifiSettingsStore()).thenReturn(mSettingsStore); 223 when(mWifiInjector.getClock()).thenReturn(mClock); 224 when(mWifiInjector.getWifiNotificationController()).thenReturn(mWifiNotificationController); 225 mWifiServiceImpl = new WifiServiceImpl(mContext, mWifiInjector, mAsyncChannel); 226 mWifiServiceImpl.setWifiHandlerLogForTest(mLog); 227 } 228 229 @Test 230 public void testRemoveNetworkUnknown() { 231 assertFalse(mWifiServiceImpl.removeNetwork(-1)); 232 } 233 234 @Test 235 public void testAsyncChannelHalfConnected() { 236 WifiAsyncChannelTester channelTester = new WifiAsyncChannelTester(mWifiInjector); 237 Handler handler = mock(Handler.class); 238 TestLooper looper = new TestLooper(); 239 channelTester.connect(looper.getLooper(), mWifiServiceImpl.getWifiServiceMessenger(), 240 handler); 241 mLooper.dispatchAll(); 242 assertEquals("AsyncChannel must be half connected", 243 WifiAsyncChannelTester.CHANNEL_STATE_HALF_CONNECTED, 244 channelTester.getChannelState()); 245 } 246 247 /** 248 * Tests the isValid() check for StaticIpConfigurations, ensuring that configurations with null 249 * ipAddress are rejected, and configurations with ipAddresses are valid. 250 */ 251 @Test 252 public void testStaticIpConfigurationValidityCheck() { 253 WifiConfiguration conf = WifiConfigurationTestUtil.createOpenNetwork(); 254 IpConfiguration ipConf = 255 WifiConfigurationTestUtil.createStaticIpConfigurationWithStaticProxy(); 256 conf.setIpConfiguration(ipConf); 257 // Ensure staticIpConfiguration with IP Address is valid 258 assertTrue(mWifiServiceImpl.isValid(conf)); 259 ipConf.staticIpConfiguration.ipAddress = null; 260 // Ensure staticIpConfiguration with null IP Address it is not valid 261 conf.setIpConfiguration(ipConf); 262 assertFalse(mWifiServiceImpl.isValid(conf)); 263 } 264 265 /** 266 * Ensure WifiMetrics.dump() is the only dump called when 'dumpsys wifi WifiMetricsProto' is 267 * called. This is required to support simple metrics collection via dumpsys 268 */ 269 @Test 270 public void testWifiMetricsDump() { 271 mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), 272 new String[]{mWifiMetrics.PROTO_DUMP_ARG}); 273 verify(mWifiMetrics) 274 .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class)); 275 verify(mWifiStateMachine, never()) 276 .dump(any(FileDescriptor.class), any(PrintWriter.class), any(String[].class)); 277 } 278 279 280 /** 281 * Ensure WifiServiceImpl.dump() doesn't throw an NPE when executed with null args 282 */ 283 @Test 284 public void testDumpNullArgs() { 285 mWifiServiceImpl.dump(new FileDescriptor(), new PrintWriter(new StringWriter()), null); 286 } 287 288 /** 289 * Verify that wifi can be enabled by a caller with WIFI_STATE_CHANGE permission when wifi is 290 * off (no hotspot, no airplane mode). 291 */ 292 @Test 293 public void testSetWifiEnabledSuccess() throws Exception { 294 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 295 when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); 296 assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); 297 verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED)); 298 } 299 300 /** 301 * Verify that the CMD_TOGGLE_WIFI message won't be sent if wifi is already on. 302 */ 303 @Test 304 public void testSetWifiEnabledNoToggle() throws Exception { 305 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 306 when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(false); 307 assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); 308 verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED)); 309 } 310 311 /** 312 * Verify a SecurityException is thrown if a caller does not have the correct permission to 313 * toggle wifi. 314 */ 315 @Test(expected = SecurityException.class) 316 public void testSetWifiEnableWithoutPermission() throws Exception { 317 doThrow(new SecurityException()).when(mContext) 318 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), 319 eq("WifiService")); 320 mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true); 321 verify(mWifiStateMachine, never()).syncGetWifiApState(); 322 } 323 324 /** 325 * Verify that a call from Settings can enable wifi if we are in softap mode. 326 */ 327 @Test 328 public void testSetWifiEnabledFromSettingsWhenApEnabled() throws Exception { 329 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED); 330 when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); 331 assertTrue(mWifiServiceImpl.setWifiEnabled(SETTINGS_PACKAGE_NAME, true)); 332 verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED)); 333 } 334 335 /** 336 * Verify that a call from SysUI can enable wifi if we are in softap mode. 337 */ 338 @Test 339 public void testSetWifiEnabledFromSysUiWhenApEnabled() throws Exception { 340 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED); 341 when(mSettingsStore.handleWifiToggled(eq(true))).thenReturn(true); 342 assertTrue(mWifiServiceImpl.setWifiEnabled(SYSUI_PACKAGE_NAME, true)); 343 verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED)); 344 } 345 346 /** 347 * Verify that a call from an app cannot enable wifi if we are in softap mode. 348 */ 349 @Test 350 public void testSetWifiEnabledFromAppFailsWhenApEnabled() throws Exception { 351 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED); 352 assertFalse(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, true)); 353 verify(mSettingsStore, never()).handleWifiToggled(anyBoolean()); 354 verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED)); 355 } 356 357 /** 358 * Verify that wifi can be disabled by a caller with WIFI_STATE_CHANGE permission when wifi is 359 * on. 360 */ 361 @Test 362 public void testSetWifiDisabledSuccess() throws Exception { 363 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 364 when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(true); 365 assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); 366 verify(mWifiController).sendMessage(eq(CMD_WIFI_TOGGLED)); 367 } 368 369 /** 370 * Verify that CMD_TOGGLE_WIFI message won't be sent if wifi is already off. 371 */ 372 @Test 373 public void testSetWifiDisabledNoToggle() throws Exception { 374 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 375 when(mSettingsStore.handleWifiToggled(eq(false))).thenReturn(false); 376 assertTrue(mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false)); 377 verify(mWifiController, never()).sendMessage(eq(CMD_WIFI_TOGGLED)); 378 } 379 380 /** 381 * Verify a SecurityException is thrown if a caller does not have the correct permission to 382 * toggle wifi. 383 */ 384 @Test(expected = SecurityException.class) 385 public void testSetWifiDisabledWithoutPermission() throws Exception { 386 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 387 doThrow(new SecurityException()).when(mContext) 388 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), 389 eq("WifiService")); 390 mWifiServiceImpl.setWifiEnabled(TEST_PACKAGE_NAME, false); 391 } 392 393 /** 394 * Ensure unpermitted callers cannot write the SoftApConfiguration. 395 * 396 * @throws SecurityException 397 */ 398 @Test(expected = SecurityException.class) 399 public void testSetWifiApConfigurationNotSavedWithoutPermission() { 400 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); 401 WifiConfiguration apConfig = new WifiConfiguration(); 402 mWifiServiceImpl.setWifiApConfiguration(apConfig); 403 verify(mWifiStateMachine, never()).setWifiApConfiguration(eq(apConfig)); 404 } 405 406 /** 407 * Ensure softap config is written when the caller has the correct permission. 408 */ 409 @Test 410 public void testSetWifiApConfigurationSuccess() { 411 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 412 WifiConfiguration apConfig = new WifiConfiguration(); 413 mWifiServiceImpl.setWifiApConfiguration(apConfig); 414 verify(mWifiStateMachine).setWifiApConfiguration(eq(apConfig)); 415 } 416 417 /** 418 * Ensure that a null config does not overwrite the saved ap config. 419 */ 420 @Test 421 public void testSetWifiApConfigurationNullConfigNotSaved() { 422 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 423 mWifiServiceImpl.setWifiApConfiguration(null); 424 verify(mWifiStateMachine, never()).setWifiApConfiguration(isNull(WifiConfiguration.class)); 425 } 426 427 /** 428 * Ensure unpermitted callers are not able to retrieve the softap config. 429 * 430 * @throws SecurityException 431 */ 432 @Test(expected = SecurityException.class) 433 public void testGetWifiApConfigurationNotReturnedWithoutPermission() { 434 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(false); 435 mWifiServiceImpl.getWifiApConfiguration(); 436 verify(mWifiStateMachine, never()).syncGetWifiApConfiguration(); 437 } 438 439 /** 440 * Ensure permitted callers are able to retrieve the softap config. 441 */ 442 @Test 443 public void testGetWifiApConfigurationSuccess() { 444 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 445 WifiConfiguration apConfig = new WifiConfiguration(); 446 when(mWifiStateMachine.syncGetWifiApConfiguration()).thenReturn(apConfig); 447 assertEquals(apConfig, mWifiServiceImpl.getWifiApConfiguration()); 448 } 449 450 /** 451 * Make sure we do not start wifi if System services have to be restarted to decrypt the device. 452 */ 453 @Test 454 public void testWifiControllerDoesNotStartWhenDeviceTriggerResetMainAtBoot() { 455 when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(true); 456 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 457 mWifiServiceImpl.checkAndStartWifi(); 458 verify(mWifiController, never()).start(); 459 } 460 461 /** 462 * Make sure we do start WifiController (wifi disabled) if the device is already decrypted. 463 */ 464 @Test 465 public void testWifiControllerStartsWhenDeviceIsDecryptedAtBootWithWifiDisabled() { 466 when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false); 467 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(false); 468 mWifiServiceImpl.checkAndStartWifi(); 469 verify(mWifiController).start(); 470 verify(mWifiController, never()).sendMessage(CMD_WIFI_TOGGLED); 471 } 472 473 /** 474 * Make sure we do start WifiController (wifi enabled) if the device is already decrypted. 475 */ 476 @Test 477 public void testWifiFullyStartsWhenDeviceIsDecryptedAtBootWithWifiEnabled() { 478 when(mFrameworkFacade.inStorageManagerCryptKeeperBounce()).thenReturn(false); 479 when(mSettingsStore.handleWifiToggled(true)).thenReturn(true); 480 when(mSettingsStore.isWifiToggleEnabled()).thenReturn(true); 481 when(mWifiStateMachine.syncGetWifiState()).thenReturn(WIFI_STATE_DISABLED); 482 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 483 when(mContext.getPackageName()).thenReturn(ANDROID_SYSTEM_PACKAGE); 484 mWifiServiceImpl.checkAndStartWifi(); 485 verify(mWifiController).start(); 486 verify(mWifiController).sendMessage(CMD_WIFI_TOGGLED); 487 } 488 489 /** 490 * Verify setWifiApEnabled works with the correct permissions and a null config. 491 */ 492 @Test 493 public void testSetWifiApEnabledWithProperPermissionsWithNullConfig() { 494 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 495 when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING))) 496 .thenReturn(false); 497 mWifiServiceImpl.setWifiApEnabled(null, true); 498 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(null)); 499 } 500 501 /** 502 * Verify setWifiApEnabled works with correct permissions and a valid config. 503 * 504 * TODO: should really validate that ap configs have a set of basic config settings b/37280779 505 */ 506 @Test 507 public void testSetWifiApEnabledWithProperPermissionsWithValidConfig() { 508 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 509 when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING))) 510 .thenReturn(false); 511 WifiConfiguration apConfig = new WifiConfiguration(); 512 mWifiServiceImpl.setWifiApEnabled(apConfig, true); 513 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(apConfig)); 514 } 515 516 /** 517 * Verify setWifiApEnabled when disabling softap with correct permissions sends the correct 518 * message to WifiController. 519 */ 520 @Test 521 public void testSetWifiApEnabledFalseWithProperPermissionsWithNullConfig() { 522 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 523 when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING))) 524 .thenReturn(false); 525 mWifiServiceImpl.setWifiApEnabled(null, false); 526 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0), eq(null)); 527 } 528 529 /** 530 * setWifiApEnabled should fail if the provided config is not valid. 531 */ 532 @Test 533 public void testSetWifiApEnabledWithProperPermissionInvalidConfigFails() { 534 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 535 when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING))) 536 .thenReturn(false); 537 // mApConfig is a mock and the values are not set - triggering the invalid config. Testing 538 // will be improved when we actually do test softap configs in b/37280779 539 mWifiServiceImpl.setWifiApEnabled(mApConfig, true); 540 verify(mWifiController, never()).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(mApConfig)); 541 } 542 543 /** 544 * setWifiApEnabled should throw a security exception when the caller does not have the correct 545 * permissions. 546 */ 547 @Test(expected = SecurityException.class) 548 public void testSetWifiApEnabledThrowsSecurityExceptionWithoutConfigOverridePermission() 549 throws Exception { 550 doThrow(new SecurityException()).when(mContext) 551 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), 552 eq("WifiService")); 553 mWifiServiceImpl.setWifiApEnabled(null, true); 554 } 555 556 /** 557 * setWifiApEnabled should throw a SecurityException when disallow tethering is set for the 558 * user. 559 */ 560 @Test(expected = SecurityException.class) 561 public void testSetWifiApEnabledThrowsSecurityExceptionWithDisallowTethering() 562 throws Exception { 563 when(mWifiPermissionsUtil.checkConfigOverridePermission(anyInt())).thenReturn(true); 564 when(mUserManager.hasUserRestriction(eq(UserManager.DISALLOW_CONFIG_TETHERING))) 565 .thenReturn(true); 566 mWifiServiceImpl.setWifiApEnabled(null, true); 567 568 } 569 570 /** 571 * Verify caller with proper permission can call startSoftAp. 572 */ 573 @Test 574 public void testStartSoftApWithPermissionsAndNullConfig() { 575 boolean result = mWifiServiceImpl.startSoftAp(null); 576 assertTrue(result); 577 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(null)); 578 } 579 580 /** 581 * Verify caller with proper permissions but an invalid config does not start softap. 582 */ 583 @Test 584 public void testStartSoftApWithPermissionsAndInvalidConfig() { 585 boolean result = mWifiServiceImpl.startSoftAp(mApConfig); 586 assertFalse(result); 587 verifyZeroInteractions(mWifiController); 588 } 589 590 /** 591 * Verify caller with proper permission and valid config does start softap. 592 */ 593 @Test 594 public void testStartSoftApWithPermissionsAndValidConfig() { 595 WifiConfiguration config = new WifiConfiguration(); 596 boolean result = mWifiServiceImpl.startSoftAp(config); 597 assertTrue(result); 598 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(1), eq(0), eq(config)); 599 } 600 601 /** 602 * Verify a SecurityException is thrown when a caller without the correct permission attempts to 603 * start softap. 604 */ 605 @Test(expected = SecurityException.class) 606 public void testStartSoftApWithoutPermissionThrowsException() throws Exception { 607 doThrow(new SecurityException()).when(mContext) 608 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_STACK), 609 eq("WifiService")); 610 mWifiServiceImpl.startSoftAp(null); 611 } 612 613 /** 614 * Verify caller with proper permission can call stopSoftAp. 615 */ 616 @Test 617 public void testStopSoftApWithPermissions() { 618 boolean result = mWifiServiceImpl.stopSoftAp(); 619 assertTrue(result); 620 verify(mWifiController).sendMessage(eq(CMD_SET_AP), eq(0), eq(0)); 621 } 622 623 /** 624 * Verify SecurityException is thrown when a caller without the correct permission attempts to 625 * stop softap. 626 */ 627 @Test(expected = SecurityException.class) 628 public void testStopSoftApWithoutPermissionThrowsException() throws Exception { 629 doThrow(new SecurityException()).when(mContext) 630 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.NETWORK_STACK), 631 eq("WifiService")); 632 mWifiServiceImpl.stopSoftAp(); 633 } 634 635 /** 636 * Ensure foreground apps can always do wifi scans. 637 */ 638 @Test 639 public void testWifiScanStartedForeground() { 640 when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn( 641 ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE); 642 mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME); 643 verify(mWifiStateMachine).startScan( 644 anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class)); 645 } 646 647 /** 648 * Ensure background apps get throttled when the previous scan is too close. 649 */ 650 @Test 651 public void testWifiScanBackgroundThrottled() { 652 when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn( 653 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 654 long startMs = 1000; 655 when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs); 656 mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME); 657 verify(mWifiStateMachine).startScan( 658 anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class)); 659 660 when(mClock.getElapsedSinceBootMillis()).thenReturn( 661 startMs + WIFI_BACKGROUND_SCAN_INTERVAL - 1000); 662 mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME); 663 verify(mWifiStateMachine, times(1)).startScan( 664 anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class)); 665 } 666 667 /** 668 * Ensure background apps can do wifi scan when the throttle interval reached. 669 */ 670 @Test 671 public void testWifiScanBackgroundNotThrottled() { 672 when(mActivityManager.getPackageImportance(SCAN_PACKAGE_NAME)).thenReturn( 673 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 674 long startMs = 1000; 675 when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs); 676 mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME); 677 verify(mWifiStateMachine).startScan( 678 anyInt(), eq(0), (ScanSettings) eq(null), any(WorkSource.class)); 679 680 when(mClock.getElapsedSinceBootMillis()).thenReturn( 681 startMs + WIFI_BACKGROUND_SCAN_INTERVAL + 1000); 682 mWifiServiceImpl.startScan(null, null, SCAN_PACKAGE_NAME); 683 verify(mWifiStateMachine).startScan( 684 anyInt(), eq(1), (ScanSettings) eq(null), any(WorkSource.class)); 685 } 686 687 /** 688 * Ensure background apps can do wifi scan when the throttle interval reached. 689 */ 690 @Test 691 public void testWifiScanBackgroundWhiteListed() { 692 when(mActivityManager.getPackageImportance(WHITE_LIST_SCAN_PACKAGE_NAME)).thenReturn( 693 ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED); 694 long startMs = 1000; 695 when(mClock.getElapsedSinceBootMillis()).thenReturn(startMs); 696 mWifiServiceImpl.startScan(null, null, WHITE_LIST_SCAN_PACKAGE_NAME); 697 verify(mWifiStateMachine).startScan( 698 anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class)); 699 700 when(mClock.getElapsedSinceBootMillis()).thenReturn( 701 startMs + WIFI_BACKGROUND_SCAN_INTERVAL - 1000); 702 mWifiServiceImpl.startScan(null, null, WHITE_LIST_SCAN_PACKAGE_NAME); 703 verify(mWifiStateMachine, times(2)).startScan( 704 anyInt(), anyInt(), (ScanSettings) eq(null), any(WorkSource.class)); 705 } 706 707 /** 708 * Verify that the call to startLocalOnlyHotspot throws the UnsupportedOperationException 709 * until the implementation is complete. 710 */ 711 @Test(expected = UnsupportedOperationException.class) 712 public void testStartLocalOnlyHotspotNotSupported() { 713 // allow test to proceed without a permission check failure 714 when(mSettingsStore.getLocationModeSetting(mContext)) 715 .thenReturn(LOCATION_MODE_HIGH_ACCURACY); 716 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) 717 .thenReturn(false); 718 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_DISABLED); 719 mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 720 } 721 722 /** 723 * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not 724 * have the CHANGE_WIFI_STATE permission. 725 */ 726 @Test(expected = SecurityException.class) 727 public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() { 728 doThrow(new SecurityException()).when(mContext) 729 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), 730 eq("WifiService")); 731 mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 732 } 733 734 /** 735 * Verify that a call to startLocalOnlyHotspot throws a SecurityException if the caller does not 736 * have Location permission. 737 */ 738 @Test(expected = SecurityException.class) 739 public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationPermission() { 740 when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); 741 doThrow(new SecurityException()) 742 .when(mWifiPermissionsUtil).enforceLocationPermission(eq(TEST_PACKAGE_NAME), 743 anyInt()); 744 mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 745 } 746 747 /** 748 * Verify that a call to startLocalOnlyHotspot throws a SecurityException if Location mode is 749 * disabled. 750 */ 751 @Test(expected = SecurityException.class) 752 public void testStartLocalOnlyHotspotThrowsSecurityExceptionWithoutLocationEnabled() { 753 when(mSettingsStore.getLocationModeSetting(mContext)).thenReturn(LOCATION_MODE_OFF); 754 mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 755 } 756 757 /** 758 * Only start LocalOnlyHotspot if we are not tethering. 759 */ 760 @Test 761 public void testHotspotDoesNotStartWhenAlreadyTethering() { 762 when(mSettingsStore.getLocationModeSetting(mContext)) 763 .thenReturn(LOCATION_MODE_HIGH_ACCURACY); 764 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED); 765 int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 766 assertEquals(ERROR_INCOMPATIBLE_MODE, returnCode); 767 } 768 769 /** 770 * Only start LocalOnlyHotspot if admin setting does not disallow tethering. 771 */ 772 @Test 773 public void testHotspotDoesNotStartWhenTetheringDisallowed() { 774 when(mSettingsStore.getLocationModeSetting(mContext)) 775 .thenReturn(LOCATION_MODE_HIGH_ACCURACY); 776 when(mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) 777 .thenReturn(true); 778 when(mWifiStateMachine.syncGetWifiApState()).thenReturn(WifiManager.WIFI_AP_STATE_ENABLED); 779 int returnCode = mWifiServiceImpl.startLocalOnlyHotspot(mAppMessenger, mAppBinder); 780 assertEquals(ERROR_TETHERING_DISALLOWED, returnCode); 781 } 782 783 /** 784 * Verify that the call to stopLocalOnlyHotspot throws the UnsupportedOperationException until 785 * the implementation is complete. 786 */ 787 @Test(expected = UnsupportedOperationException.class) 788 public void testStopLocalOnlyHotspotNotSupported() { 789 // allow test to proceed without a permission check failure 790 mWifiServiceImpl.stopLocalOnlyHotspot(); 791 } 792 793 /** 794 * Verify that a call to stopLocalOnlyHotspot throws a SecurityException if the caller does not 795 * have the CHANGE_WIFI_STATE permission. 796 */ 797 @Test(expected = SecurityException.class) 798 public void testStopLocalOnlyHotspotThrowsSecurityExceptionWithoutCorrectPermission() { 799 doThrow(new SecurityException()).when(mContext) 800 .enforceCallingOrSelfPermission(eq(android.Manifest.permission.CHANGE_WIFI_STATE), 801 eq("WifiService")); 802 mWifiServiceImpl.stopLocalOnlyHotspot(); 803 } 804 805 /** 806 * Verify that the call to startWatchLocalOnlyHotspot throws the UnsupportedOperationException 807 * until the implementation is complete. 808 */ 809 @Test(expected = UnsupportedOperationException.class) 810 public void testStartWatchLocalOnlyHotspotNotSupported() { 811 mWifiServiceImpl.startWatchLocalOnlyHotspot(mAppMessenger, mAppBinder); 812 } 813 814 /** 815 * Verify that the call to stopWatchLocalOnlyHotspot throws the UnsupportedOperationException 816 * until the implementation is complete. 817 */ 818 @Test(expected = UnsupportedOperationException.class) 819 public void testStopWatchLocalOnlyHotspotNotSupported() { 820 mWifiServiceImpl.stopWatchLocalOnlyHotspot(); 821 } 822} 823