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