1 /* 2 * Copyright (C) 2017 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 17 package android.net.wifi; 18 19 import static android.net.wifi.WifiManager.HOTSPOT_FAILED; 20 import static android.net.wifi.WifiManager.HOTSPOT_STARTED; 21 import static android.net.wifi.WifiManager.HOTSPOT_STOPPED; 22 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_GENERIC; 23 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_INCOMPATIBLE_MODE; 24 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_NO_CHANNEL; 25 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.ERROR_TETHERING_DISALLOWED; 26 import static android.net.wifi.WifiManager.LocalOnlyHotspotCallback.REQUEST_REGISTERED; 27 28 import static org.junit.Assert.assertEquals; 29 import static org.junit.Assert.assertFalse; 30 import static org.junit.Assert.assertNotNull; 31 import static org.junit.Assert.assertTrue; 32 import static org.mockito.Mockito.*; 33 34 import android.content.Context; 35 import android.content.pm.ApplicationInfo; 36 import android.net.wifi.WifiManager.LocalOnlyHotspotCallback; 37 import android.net.wifi.WifiManager.LocalOnlyHotspotObserver; 38 import android.net.wifi.WifiManager.LocalOnlyHotspotReservation; 39 import android.net.wifi.WifiManager.LocalOnlyHotspotSubscription; 40 import android.os.Handler; 41 import android.os.IBinder; 42 import android.os.Message; 43 import android.os.Messenger; 44 import android.os.test.TestLooper; 45 import android.test.suitebuilder.annotation.SmallTest; 46 47 import org.junit.Before; 48 import org.junit.Test; 49 import org.mockito.ArgumentCaptor; 50 import org.mockito.Mock; 51 import org.mockito.MockitoAnnotations; 52 53 /** 54 * Unit tests for {@link android.net.wifi.WifiManager}. 55 */ 56 @SmallTest 57 public class WifiManagerTest { 58 59 private static final int ERROR_NOT_SET = -1; 60 private static final int ERROR_TEST_REASON = 5; 61 private static final String TEST_PACKAGE_NAME = "TestPackage"; 62 63 @Mock Context mContext; 64 @Mock IWifiManager mWifiService; 65 @Mock ApplicationInfo mApplicationInfo; 66 @Mock WifiConfiguration mApConfig; 67 @Mock IBinder mAppBinder; 68 69 private Handler mHandler; 70 private TestLooper mLooper; 71 private WifiManager mWifiManager; 72 private Messenger mWifiServiceMessenger; 73 final ArgumentCaptor<Messenger> mMessengerCaptor = ArgumentCaptor.forClass(Messenger.class); 74 75 @Before public void setUp() throws Exception { 76 MockitoAnnotations.initMocks(this); 77 mLooper = new TestLooper(); 78 mHandler = spy(new Handler(mLooper.getLooper())); 79 when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo); 80 when(mContext.getOpPackageName()).thenReturn(TEST_PACKAGE_NAME); 81 82 mWifiServiceMessenger = new Messenger(mHandler); 83 mWifiManager = new WifiManager(mContext, mWifiService, mLooper.getLooper()); 84 } 85 86 /** 87 * Check the call to startSoftAp calls WifiService to startSoftAp with the provided 88 * WifiConfiguration. Verify that the return value is propagated to the caller. 89 */ 90 @Test 91 public void testStartSoftApCallsServiceWithWifiConfig() throws Exception { 92 when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(true); 93 assertTrue(mWifiManager.startSoftAp(mApConfig)); 94 95 when(mWifiService.startSoftAp(eq(mApConfig))).thenReturn(false); 96 assertFalse(mWifiManager.startSoftAp(mApConfig)); 97 } 98 99 /** 100 * Check the call to startSoftAp calls WifiService to startSoftAp with a null config. Verify 101 * that the return value is propagated to the caller. 102 */ 103 @Test 104 public void testStartSoftApCallsServiceWithNullConfig() throws Exception { 105 when(mWifiService.startSoftAp(eq(null))).thenReturn(true); 106 assertTrue(mWifiManager.startSoftAp(null)); 107 108 when(mWifiService.startSoftAp(eq(null))).thenReturn(false); 109 assertFalse(mWifiManager.startSoftAp(null)); 110 } 111 112 /** 113 * Check the call to stopSoftAp calls WifiService to stopSoftAp. 114 */ 115 @Test 116 public void testStopSoftApCallsService() throws Exception { 117 when(mWifiService.stopSoftAp()).thenReturn(true); 118 assertTrue(mWifiManager.stopSoftAp()); 119 120 when(mWifiService.stopSoftAp()).thenReturn(false); 121 assertFalse(mWifiManager.stopSoftAp()); 122 } 123 124 /** 125 * Test creation of a LocalOnlyHotspotReservation and verify that close properly calls 126 * WifiService.stopLocalOnlyHotspot. 127 */ 128 @Test 129 public void testCreationAndCloseOfLocalOnlyHotspotReservation() throws Exception { 130 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 131 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 132 anyString())).thenReturn(REQUEST_REGISTERED); 133 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 134 135 callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig)); 136 137 assertEquals(mApConfig, callback.mRes.getWifiConfiguration()); 138 callback.mRes.close(); 139 verify(mWifiService).stopLocalOnlyHotspot(); 140 } 141 142 /** 143 * Verify stopLOHS is called when try-with-resources is used properly. 144 */ 145 @Test 146 public void testLocalOnlyHotspotReservationCallsStopProperlyInTryWithResources() 147 throws Exception { 148 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 149 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 150 anyString())).thenReturn(REQUEST_REGISTERED); 151 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 152 153 callback.onStarted(mWifiManager.new LocalOnlyHotspotReservation(mApConfig)); 154 155 try (WifiManager.LocalOnlyHotspotReservation res = callback.mRes) { 156 assertEquals(mApConfig, res.getWifiConfiguration()); 157 } 158 159 verify(mWifiService).stopLocalOnlyHotspot(); 160 } 161 162 /** 163 * Test creation of a LocalOnlyHotspotSubscription. 164 * TODO: when registrations are tracked, verify removal on close. 165 */ 166 @Test 167 public void testCreationOfLocalOnlyHotspotSubscription() throws Exception { 168 try (WifiManager.LocalOnlyHotspotSubscription sub = 169 mWifiManager.new LocalOnlyHotspotSubscription()) { 170 sub.close(); 171 } 172 } 173 174 public class TestLocalOnlyHotspotCallback extends LocalOnlyHotspotCallback { 175 public boolean mOnStartedCalled = false; 176 public boolean mOnStoppedCalled = false; 177 public int mFailureReason = -1; 178 public LocalOnlyHotspotReservation mRes = null; 179 public long mCallingThreadId = -1; 180 181 @Override 182 public void onStarted(LocalOnlyHotspotReservation r) { 183 mRes = r; 184 mOnStartedCalled = true; 185 mCallingThreadId = Thread.currentThread().getId(); 186 } 187 188 @Override 189 public void onStopped() { 190 mOnStoppedCalled = true; 191 mCallingThreadId = Thread.currentThread().getId(); 192 } 193 194 @Override 195 public void onFailed(int reason) { 196 mFailureReason = reason; 197 mCallingThreadId = Thread.currentThread().getId(); 198 } 199 } 200 201 /** 202 * Verify callback is properly plumbed when called. 203 */ 204 @Test 205 public void testLocalOnlyHotspotCallback() { 206 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 207 assertFalse(callback.mOnStartedCalled); 208 assertFalse(callback.mOnStoppedCalled); 209 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 210 assertEquals(null, callback.mRes); 211 212 // test onStarted 213 WifiManager.LocalOnlyHotspotReservation res = 214 mWifiManager.new LocalOnlyHotspotReservation(mApConfig); 215 callback.onStarted(res); 216 assertEquals(res, callback.mRes); 217 assertTrue(callback.mOnStartedCalled); 218 assertFalse(callback.mOnStoppedCalled); 219 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 220 221 // test onStopped 222 callback.onStopped(); 223 assertEquals(res, callback.mRes); 224 assertTrue(callback.mOnStartedCalled); 225 assertTrue(callback.mOnStoppedCalled); 226 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 227 228 // test onFailed 229 callback.onFailed(ERROR_TEST_REASON); 230 assertEquals(res, callback.mRes); 231 assertTrue(callback.mOnStartedCalled); 232 assertTrue(callback.mOnStoppedCalled); 233 assertEquals(ERROR_TEST_REASON, callback.mFailureReason); 234 } 235 236 public class TestLocalOnlyHotspotObserver extends LocalOnlyHotspotObserver { 237 public boolean mOnRegistered = false; 238 public boolean mOnStartedCalled = false; 239 public boolean mOnStoppedCalled = false; 240 public WifiConfiguration mConfig = null; 241 public LocalOnlyHotspotSubscription mSub = null; 242 public long mCallingThreadId = -1; 243 244 @Override 245 public void onRegistered(LocalOnlyHotspotSubscription sub) { 246 mOnRegistered = true; 247 mSub = sub; 248 mCallingThreadId = Thread.currentThread().getId(); 249 } 250 251 @Override 252 public void onStarted(WifiConfiguration config) { 253 mOnStartedCalled = true; 254 mConfig = config; 255 mCallingThreadId = Thread.currentThread().getId(); 256 } 257 258 @Override 259 public void onStopped() { 260 mOnStoppedCalled = true; 261 mCallingThreadId = Thread.currentThread().getId(); 262 } 263 } 264 265 /** 266 * Verify observer is properly plumbed when called. 267 */ 268 @Test 269 public void testLocalOnlyHotspotObserver() { 270 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 271 assertFalse(observer.mOnRegistered); 272 assertFalse(observer.mOnStartedCalled); 273 assertFalse(observer.mOnStoppedCalled); 274 assertEquals(null, observer.mConfig); 275 assertEquals(null, observer.mSub); 276 277 WifiManager.LocalOnlyHotspotSubscription sub = 278 mWifiManager.new LocalOnlyHotspotSubscription(); 279 observer.onRegistered(sub); 280 assertTrue(observer.mOnRegistered); 281 assertFalse(observer.mOnStartedCalled); 282 assertFalse(observer.mOnStoppedCalled); 283 assertEquals(null, observer.mConfig); 284 assertEquals(sub, observer.mSub); 285 286 observer.onStarted(mApConfig); 287 assertTrue(observer.mOnRegistered); 288 assertTrue(observer.mOnStartedCalled); 289 assertFalse(observer.mOnStoppedCalled); 290 assertEquals(mApConfig, observer.mConfig); 291 assertEquals(sub, observer.mSub); 292 293 observer.onStopped(); 294 assertTrue(observer.mOnRegistered); 295 assertTrue(observer.mOnStartedCalled); 296 assertTrue(observer.mOnStoppedCalled); 297 assertEquals(mApConfig, observer.mConfig); 298 assertEquals(sub, observer.mSub); 299 } 300 301 /** 302 * Verify call to startLocalOnlyHotspot goes to WifiServiceImpl. 303 */ 304 @Test 305 public void testStartLocalOnlyHotspot() throws Exception { 306 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 307 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 308 309 verify(mWifiService) 310 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString()); 311 } 312 313 /** 314 * Verify a SecurityException is thrown for callers without proper permissions for 315 * startLocalOnlyHotspot. 316 */ 317 @Test(expected = SecurityException.class) 318 public void testStartLocalOnlyHotspotThrowsSecurityException() throws Exception { 319 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 320 doThrow(new SecurityException()).when(mWifiService) 321 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString()); 322 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 323 } 324 325 /** 326 * Verify an IllegalStateException is thrown for callers that already have a pending request for 327 * startLocalOnlyHotspot. 328 */ 329 @Test(expected = IllegalStateException.class) 330 public void testStartLocalOnlyHotspotThrowsIllegalStateException() throws Exception { 331 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 332 doThrow(new IllegalStateException()).when(mWifiService) 333 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString()); 334 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 335 } 336 337 /** 338 * Verify that the handler provided by the caller is used for the callbacks. 339 */ 340 @Test 341 public void testCorrectLooperIsUsedForHandler() throws Exception { 342 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 343 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 344 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE); 345 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 346 mLooper.dispatchAll(); 347 assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason); 348 verify(mContext, never()).getMainLooper(); 349 } 350 351 /** 352 * Verify that the main looper's thread is used if a handler is not provided by the reqiestomg 353 * application. 354 */ 355 @Test 356 public void testMainLooperIsUsedWhenHandlerNotProvided() throws Exception { 357 // record thread from looper.getThread and check ids. 358 TestLooper altLooper = new TestLooper(); 359 when(mContext.getMainLooper()).thenReturn(altLooper.getLooper()); 360 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 361 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 362 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE); 363 mWifiManager.startLocalOnlyHotspot(callback, null); 364 altLooper.dispatchAll(); 365 assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason); 366 assertEquals(altLooper.getLooper().getThread().getId(), callback.mCallingThreadId); 367 verify(mContext).getMainLooper(); 368 } 369 370 /** 371 * Verify the LOHS onStarted callback is triggered when WifiManager receives a HOTSPOT_STARTED 372 * message from WifiServiceImpl. 373 */ 374 @Test 375 public void testOnStartedIsCalledWithReservation() throws Exception { 376 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 377 TestLooper callbackLooper = new TestLooper(); 378 Handler callbackHandler = new Handler(callbackLooper.getLooper()); 379 when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(), 380 any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED); 381 mWifiManager.startLocalOnlyHotspot(callback, callbackHandler); 382 callbackLooper.dispatchAll(); 383 mLooper.dispatchAll(); 384 assertFalse(callback.mOnStartedCalled); 385 assertEquals(null, callback.mRes); 386 // now trigger the callback 387 Message msg = new Message(); 388 msg.what = HOTSPOT_STARTED; 389 msg.obj = mApConfig; 390 mMessengerCaptor.getValue().send(msg); 391 mLooper.dispatchAll(); 392 callbackLooper.dispatchAll(); 393 assertTrue(callback.mOnStartedCalled); 394 assertEquals(mApConfig, callback.mRes.getWifiConfiguration()); 395 } 396 397 /** 398 * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_STARTED message with a null 399 * config. 400 */ 401 @Test 402 public void testOnStartedIsCalledWithNullConfig() throws Exception { 403 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 404 TestLooper callbackLooper = new TestLooper(); 405 Handler callbackHandler = new Handler(callbackLooper.getLooper()); 406 when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(), 407 any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED); 408 mWifiManager.startLocalOnlyHotspot(callback, callbackHandler); 409 callbackLooper.dispatchAll(); 410 mLooper.dispatchAll(); 411 assertFalse(callback.mOnStartedCalled); 412 assertEquals(null, callback.mRes); 413 // now trigger the callback 414 Message msg = new Message(); 415 msg.what = HOTSPOT_STARTED; 416 mMessengerCaptor.getValue().send(msg); 417 mLooper.dispatchAll(); 418 callbackLooper.dispatchAll(); 419 assertFalse(callback.mOnStartedCalled); 420 assertEquals(ERROR_GENERIC, callback.mFailureReason); 421 } 422 423 /** 424 * Verify onStopped is called if WifiServiceImpl sends a HOTSPOT_STOPPED message. 425 */ 426 @Test 427 public void testOnStoppedIsCalled() throws Exception { 428 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 429 TestLooper callbackLooper = new TestLooper(); 430 Handler callbackHandler = new Handler(callbackLooper.getLooper()); 431 when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(), 432 any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED); 433 mWifiManager.startLocalOnlyHotspot(callback, callbackHandler); 434 callbackLooper.dispatchAll(); 435 mLooper.dispatchAll(); 436 assertFalse(callback.mOnStoppedCalled); 437 // now trigger the callback 438 Message msg = new Message(); 439 msg.what = HOTSPOT_STOPPED; 440 mMessengerCaptor.getValue().send(msg); 441 mLooper.dispatchAll(); 442 callbackLooper.dispatchAll(); 443 assertTrue(callback.mOnStoppedCalled); 444 } 445 446 /** 447 * Verify onFailed is called if WifiServiceImpl sends a HOTSPOT_FAILED message. 448 */ 449 @Test 450 public void testOnFailedIsCalled() throws Exception { 451 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 452 TestLooper callbackLooper = new TestLooper(); 453 Handler callbackHandler = new Handler(callbackLooper.getLooper()); 454 when(mWifiService.startLocalOnlyHotspot(mMessengerCaptor.capture(), 455 any(IBinder.class), anyString())).thenReturn(REQUEST_REGISTERED); 456 mWifiManager.startLocalOnlyHotspot(callback, callbackHandler); 457 callbackLooper.dispatchAll(); 458 mLooper.dispatchAll(); 459 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 460 // now trigger the callback 461 Message msg = new Message(); 462 msg.what = HOTSPOT_FAILED; 463 msg.arg1 = ERROR_NO_CHANNEL; 464 mMessengerCaptor.getValue().send(msg); 465 mLooper.dispatchAll(); 466 callbackLooper.dispatchAll(); 467 assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason); 468 } 469 470 /** 471 * Verify callback triggered from startLocalOnlyHotspot with an incompatible mode failure. 472 */ 473 @Test 474 public void testLocalOnlyHotspotCallbackFullOnIncompatibleMode() throws Exception { 475 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 476 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 477 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE); 478 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 479 mLooper.dispatchAll(); 480 assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason); 481 assertFalse(callback.mOnStartedCalled); 482 assertFalse(callback.mOnStoppedCalled); 483 assertEquals(null, callback.mRes); 484 } 485 486 /** 487 * Verify callback triggered from startLocalOnlyHotspot with a tethering disallowed failure. 488 */ 489 @Test 490 public void testLocalOnlyHotspotCallbackFullOnTetheringDisallowed() throws Exception { 491 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 492 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 493 anyString())).thenReturn(ERROR_TETHERING_DISALLOWED); 494 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 495 mLooper.dispatchAll(); 496 assertEquals(ERROR_TETHERING_DISALLOWED, callback.mFailureReason); 497 assertFalse(callback.mOnStartedCalled); 498 assertFalse(callback.mOnStoppedCalled); 499 assertEquals(null, callback.mRes); 500 } 501 502 /** 503 * Verify a SecurityException resulting from an application without necessary permissions will 504 * bubble up through the call to start LocalOnlyHotspot and will not trigger other callbacks. 505 */ 506 @Test(expected = SecurityException.class) 507 public void testLocalOnlyHotspotCallbackFullOnSecurityException() throws Exception { 508 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 509 doThrow(new SecurityException()).when(mWifiService) 510 .startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), anyString()); 511 try { 512 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 513 } catch (SecurityException e) { 514 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 515 assertFalse(callback.mOnStartedCalled); 516 assertFalse(callback.mOnStoppedCalled); 517 assertEquals(null, callback.mRes); 518 throw e; 519 } 520 521 } 522 523 /** 524 * Verify the handler passed to startLocalOnlyHotspot is correctly used for callbacks when 525 * SoftApMode fails due to a underlying error. 526 */ 527 @Test 528 public void testLocalOnlyHotspotCallbackFullOnNoChannelError() throws Exception { 529 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 530 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 531 anyString())).thenReturn(REQUEST_REGISTERED); 532 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 533 mLooper.dispatchAll(); 534 //assertEquals(ERROR_NO_CHANNEL, callback.mFailureReason); 535 assertFalse(callback.mOnStartedCalled); 536 assertFalse(callback.mOnStoppedCalled); 537 assertEquals(null, callback.mRes); 538 } 539 540 /** 541 * Verify that the call to cancel a LOHS request does call stopLOHS. 542 */ 543 @Test 544 public void testCancelLocalOnlyHotspotRequestCallsStopOnWifiService() throws Exception { 545 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 546 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 547 anyString())).thenReturn(REQUEST_REGISTERED); 548 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 549 mWifiManager.cancelLocalOnlyHotspotRequest(); 550 verify(mWifiService).stopLocalOnlyHotspot(); 551 } 552 553 /** 554 * Verify that we do not crash if cancelLocalOnlyHotspotRequest is called without an existing 555 * callback stored. 556 */ 557 @Test 558 public void testCancelLocalOnlyHotspotReturnsWithoutExistingRequest() { 559 mWifiManager.cancelLocalOnlyHotspotRequest(); 560 } 561 562 /** 563 * Verify that the callback is not triggered if the LOHS request was already cancelled. 564 */ 565 @Test 566 public void testCallbackAfterLocalOnlyHotspotWasCancelled() throws Exception { 567 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 568 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 569 anyString())).thenReturn(REQUEST_REGISTERED); 570 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 571 mWifiManager.cancelLocalOnlyHotspotRequest(); 572 verify(mWifiService).stopLocalOnlyHotspot(); 573 mLooper.dispatchAll(); 574 assertEquals(ERROR_NOT_SET, callback.mFailureReason); 575 assertFalse(callback.mOnStartedCalled); 576 assertFalse(callback.mOnStoppedCalled); 577 assertEquals(null, callback.mRes); 578 } 579 580 /** 581 * Verify that calling cancel LOHS request does not crash if an error callback was already 582 * handled. 583 */ 584 @Test 585 public void testCancelAfterLocalOnlyHotspotCallbackTriggered() throws Exception { 586 TestLocalOnlyHotspotCallback callback = new TestLocalOnlyHotspotCallback(); 587 when(mWifiService.startLocalOnlyHotspot(any(Messenger.class), any(IBinder.class), 588 anyString())).thenReturn(ERROR_INCOMPATIBLE_MODE); 589 mWifiManager.startLocalOnlyHotspot(callback, mHandler); 590 mLooper.dispatchAll(); 591 assertEquals(ERROR_INCOMPATIBLE_MODE, callback.mFailureReason); 592 assertFalse(callback.mOnStartedCalled); 593 assertFalse(callback.mOnStoppedCalled); 594 assertEquals(null, callback.mRes); 595 mWifiManager.cancelLocalOnlyHotspotRequest(); 596 verify(mWifiService, never()).stopLocalOnlyHotspot(); 597 } 598 599 /** 600 * Verify the watchLocalOnlyHotspot call goes to WifiServiceImpl. 601 */ 602 public void testWatchLocalOnlyHotspot() throws Exception { 603 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 604 605 mWifiManager.watchLocalOnlyHotspot(observer, mHandler); 606 verify(mWifiService).startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)); 607 } 608 609 /** 610 * Verify a SecurityException is thrown for callers without proper permissions for 611 * startWatchLocalOnlyHotspot. 612 */ 613 @Test(expected = SecurityException.class) 614 public void testStartWatchLocalOnlyHotspotThrowsSecurityException() throws Exception { 615 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 616 doThrow(new SecurityException()).when(mWifiService) 617 .startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)); 618 mWifiManager.watchLocalOnlyHotspot(observer, mHandler); 619 } 620 621 /** 622 * Verify an IllegalStateException is thrown for callers that already have a pending request for 623 * watchLocalOnlyHotspot. 624 */ 625 @Test(expected = IllegalStateException.class) 626 public void testStartWatchLocalOnlyHotspotThrowsIllegalStateException() throws Exception { 627 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 628 doThrow(new IllegalStateException()).when(mWifiService) 629 .startWatchLocalOnlyHotspot(any(Messenger.class), any(IBinder.class)); 630 mWifiManager.watchLocalOnlyHotspot(observer, mHandler); 631 } 632 633 /** 634 * Verify that the handler provided by the caller is used for the observer. 635 */ 636 @Test 637 public void testCorrectLooperIsUsedForObserverHandler() throws Exception { 638 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 639 mWifiManager.watchLocalOnlyHotspot(observer, mHandler); 640 mLooper.dispatchAll(); 641 assertTrue(observer.mOnRegistered); 642 verify(mContext, never()).getMainLooper(); 643 } 644 645 /** 646 * Verify that the main looper's thread is used if a handler is not provided by the requesting 647 * application. 648 */ 649 @Test 650 public void testMainLooperIsUsedWhenHandlerNotProvidedForObserver() throws Exception { 651 // record thread from looper.getThread and check ids. 652 TestLooper altLooper = new TestLooper(); 653 when(mContext.getMainLooper()).thenReturn(altLooper.getLooper()); 654 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 655 mWifiManager.watchLocalOnlyHotspot(observer, null); 656 altLooper.dispatchAll(); 657 assertTrue(observer.mOnRegistered); 658 assertEquals(altLooper.getLooper().getThread().getId(), observer.mCallingThreadId); 659 verify(mContext).getMainLooper(); 660 } 661 662 /** 663 * Verify the LOHS onRegistered observer callback is triggered when WifiManager receives a 664 * HOTSPOT_OBSERVER_REGISTERED message from WifiServiceImpl. 665 */ 666 @Test 667 public void testOnRegisteredIsCalledWithSubscription() throws Exception { 668 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 669 TestLooper observerLooper = new TestLooper(); 670 Handler observerHandler = new Handler(observerLooper.getLooper()); 671 assertFalse(observer.mOnRegistered); 672 assertEquals(null, observer.mSub); 673 mWifiManager.watchLocalOnlyHotspot(observer, observerHandler); 674 verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(), 675 any(IBinder.class)); 676 // now trigger the callback 677 observerLooper.dispatchAll(); 678 mLooper.dispatchAll(); 679 assertTrue(observer.mOnRegistered); 680 assertNotNull(observer.mSub); 681 } 682 683 /** 684 * Verify the LOHS onStarted observer callback is triggered when WifiManager receives a 685 * HOTSPOT_STARTED message from WifiServiceImpl. 686 */ 687 @Test 688 public void testObserverOnStartedIsCalledWithWifiConfig() throws Exception { 689 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 690 TestLooper observerLooper = new TestLooper(); 691 Handler observerHandler = new Handler(observerLooper.getLooper()); 692 mWifiManager.watchLocalOnlyHotspot(observer, observerHandler); 693 verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(), 694 any(IBinder.class)); 695 observerLooper.dispatchAll(); 696 mLooper.dispatchAll(); 697 assertFalse(observer.mOnStartedCalled); 698 // now trigger the callback 699 Message msg = new Message(); 700 msg.what = HOTSPOT_STARTED; 701 msg.obj = mApConfig; 702 mMessengerCaptor.getValue().send(msg); 703 mLooper.dispatchAll(); 704 observerLooper.dispatchAll(); 705 assertTrue(observer.mOnStartedCalled); 706 assertEquals(mApConfig, observer.mConfig); 707 } 708 709 /** 710 * Verify the LOHS onStarted observer callback is triggered not when WifiManager receives a 711 * HOTSPOT_STARTED message from WifiServiceImpl with a null config. 712 */ 713 @Test 714 public void testObserverOnStartedNotCalledWithNullConfig() throws Exception { 715 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 716 TestLooper observerLooper = new TestLooper(); 717 Handler observerHandler = new Handler(observerLooper.getLooper()); 718 mWifiManager.watchLocalOnlyHotspot(observer, observerHandler); 719 verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(), 720 any(IBinder.class)); 721 observerLooper.dispatchAll(); 722 mLooper.dispatchAll(); 723 assertFalse(observer.mOnStartedCalled); 724 // now trigger the callback 725 Message msg = new Message(); 726 msg.what = HOTSPOT_STARTED; 727 mMessengerCaptor.getValue().send(msg); 728 mLooper.dispatchAll(); 729 observerLooper.dispatchAll(); 730 assertFalse(observer.mOnStartedCalled); 731 assertEquals(null, observer.mConfig); 732 } 733 734 735 /** 736 * Verify the LOHS onStopped observer callback is triggered when WifiManager receives a 737 * HOTSPOT_STOPPED message from WifiServiceImpl. 738 */ 739 @Test 740 public void testObserverOnStoppedIsCalled() throws Exception { 741 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 742 TestLooper observerLooper = new TestLooper(); 743 Handler observerHandler = new Handler(observerLooper.getLooper()); 744 mWifiManager.watchLocalOnlyHotspot(observer, observerHandler); 745 verify(mWifiService).startWatchLocalOnlyHotspot(mMessengerCaptor.capture(), 746 any(IBinder.class)); 747 observerLooper.dispatchAll(); 748 mLooper.dispatchAll(); 749 assertFalse(observer.mOnStoppedCalled); 750 // now trigger the callback 751 Message msg = new Message(); 752 msg.what = HOTSPOT_STOPPED; 753 mMessengerCaptor.getValue().send(msg); 754 mLooper.dispatchAll(); 755 observerLooper.dispatchAll(); 756 assertTrue(observer.mOnStoppedCalled); 757 } 758 759 /** 760 * Verify WifiServiceImpl is not called if there is not a registered LOHS observer callback. 761 */ 762 @Test 763 public void testUnregisterWifiServiceImplNotCalledWithoutRegisteredObserver() throws Exception { 764 mWifiManager.unregisterLocalOnlyHotspotObserver(); 765 verifyZeroInteractions(mWifiService); 766 } 767 768 /** 769 * Verify WifiServiceImpl is called when there is a registered LOHS observer callback. 770 */ 771 @Test 772 public void testUnregisterWifiServiceImplCalledWithRegisteredObserver() throws Exception { 773 TestLocalOnlyHotspotObserver observer = new TestLocalOnlyHotspotObserver(); 774 TestLooper observerLooper = new TestLooper(); 775 Handler observerHandler = new Handler(observerLooper.getLooper()); 776 mWifiManager.watchLocalOnlyHotspot(observer, observerHandler); 777 mWifiManager.unregisterLocalOnlyHotspotObserver(); 778 verify(mWifiService).stopWatchLocalOnlyHotspot(); 779 } 780 781 /** 782 * Verify that calls to setWifiApEnabled return false. 783 */ 784 @Test 785 public void testSetWifiApEnabledReturnsFalse() throws Exception { 786 assertFalse(mWifiManager.setWifiApEnabled(null, true)); 787 assertFalse(mWifiManager.setWifiApEnabled(null, false)); 788 verify(mWifiService, never()).setWifiApEnabled(any(), anyBoolean()); 789 } 790 } 791