1 /* 2 * Copyright (C) 2008 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.location.cts; 18 19 20 import android.app.PendingIntent; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.content.pm.PackageManager; 26 import android.location.Criteria; 27 import android.location.GpsStatus; 28 import android.location.Location; 29 import android.location.LocationListener; 30 import android.location.LocationManager; 31 import android.location.LocationProvider; 32 import android.location.GpsStatus.Listener; 33 import android.os.Bundle; 34 import android.os.HandlerThread; 35 import android.os.Looper; 36 import android.provider.Settings; 37 import android.test.InstrumentationTestCase; 38 39 import java.util.List; 40 41 /** 42 * Requires the permissions 43 * android.permission.ACCESS_MOCK_LOCATION to mock provider 44 * android.permission.ACCESS_COARSE_LOCATION to access network provider 45 * android.permission.ACCESS_FINE_LOCATION to access GPS provider 46 * android.permission.ACCESS_LOCATION_EXTRA_COMMANDS to send extra commands to GPS provider 47 */ 48 public class LocationManagerTest extends InstrumentationTestCase { 49 private static final long TEST_TIME_OUT = 5000; 50 51 private static final String TEST_MOCK_PROVIDER_NAME = "test_provider"; 52 53 private static final String UNKNOWN_PROVIDER_NAME = "unknown_provider"; 54 55 private LocationManager mManager; 56 57 private Context mContext; 58 59 private PendingIntent mPendingIntent; 60 61 private TestIntentReceiver mIntentReceiver; 62 63 @Override setUp()64 protected void setUp() throws Exception { 65 super.setUp(); 66 mContext = getInstrumentation().getTargetContext(); 67 68 mManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); 69 70 // test that mock locations are allowed so a more descriptive error message can be logged 71 if (Settings.Secure.getInt(mContext.getContentResolver(), 72 Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 0) { 73 fail("Mock locations are currently disabled in Settings - this test requires " 74 + "mock locations"); 75 } 76 77 // remove test provider if left over from an aborted run 78 LocationProvider lp = mManager.getProvider(TEST_MOCK_PROVIDER_NAME); 79 if (lp != null) { 80 mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME); 81 } 82 83 addTestProvider(TEST_MOCK_PROVIDER_NAME); 84 } 85 86 /** 87 * Helper method to add a test provider with given name. 88 */ addTestProvider(final String providerName)89 private void addTestProvider(final String providerName) { 90 mManager.addTestProvider(providerName, true, //requiresNetwork, 91 false, // requiresSatellite, 92 true, // requiresCell, 93 false, // hasMonetaryCost, 94 false, // supportsAltitude, 95 false, // supportsSpeed, 96 false, // supportsBearing, 97 Criteria.POWER_MEDIUM, // powerRequirement 98 Criteria.ACCURACY_FINE); // accuracy 99 mManager.setTestProviderEnabled(providerName, true); 100 } 101 102 @Override tearDown()103 protected void tearDown() throws Exception { 104 LocationProvider provider = mManager.getProvider(TEST_MOCK_PROVIDER_NAME); 105 if (provider != null) { 106 mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME); 107 } 108 if (mPendingIntent != null) { 109 mManager.removeProximityAlert(mPendingIntent); 110 } 111 if (mIntentReceiver != null) { 112 mContext.unregisterReceiver(mIntentReceiver); 113 } 114 super.tearDown(); 115 } 116 testRemoveTestProvider()117 public void testRemoveTestProvider() { 118 // this test assumes TEST_MOCK_PROVIDER_NAME was created in setUp. 119 LocationProvider provider = mManager.getProvider(TEST_MOCK_PROVIDER_NAME); 120 assertNotNull(provider); 121 122 try { 123 mManager.addTestProvider(TEST_MOCK_PROVIDER_NAME, true, //requiresNetwork, 124 false, // requiresSatellite, 125 true, // requiresCell, 126 false, // hasMonetaryCost, 127 false, // supportsAltitude, 128 false, // supportsSpeed, 129 false, // supportsBearing, 130 Criteria.POWER_MEDIUM, // powerRequirement 131 Criteria.ACCURACY_FINE); // accuracy 132 fail("Should throw IllegalArgumentException when provider already exists!"); 133 } catch (IllegalArgumentException e) { 134 // expected 135 } 136 137 mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME); 138 provider = mManager.getProvider(TEST_MOCK_PROVIDER_NAME); 139 assertNull(provider); 140 141 try { 142 mManager.removeTestProvider(UNKNOWN_PROVIDER_NAME); 143 fail("Should throw IllegalArgumentException when no provider exists!"); 144 } catch (IllegalArgumentException e) { 145 // expected 146 } 147 } 148 testGetProviders()149 public void testGetProviders() { 150 List<String> providers = mManager.getAllProviders(); 151 assertTrue(providers.size() >= 2); 152 assertTrue(hasTestProvider(providers)); 153 154 assertEquals(hasGpsFeature(), hasGpsProvider(providers)); 155 156 int oldSizeAllProviders = providers.size(); 157 158 providers = mManager.getProviders(false); 159 assertEquals(oldSizeAllProviders, providers.size()); 160 assertTrue(hasTestProvider(providers)); 161 162 providers = mManager.getProviders(true); 163 assertTrue(providers.size() >= 1); 164 assertTrue(hasTestProvider(providers)); 165 int oldSizeTrueProviders = providers.size(); 166 167 mManager.setTestProviderEnabled(TEST_MOCK_PROVIDER_NAME, false); 168 providers = mManager.getProviders(true); 169 assertEquals(oldSizeTrueProviders - 1, providers.size()); 170 assertFalse(hasTestProvider(providers)); 171 172 providers = mManager.getProviders(false); 173 assertEquals(oldSizeAllProviders, providers.size()); 174 assertTrue(hasTestProvider(providers)); 175 176 mManager.removeTestProvider(TEST_MOCK_PROVIDER_NAME); 177 providers = mManager.getAllProviders(); 178 assertEquals(oldSizeAllProviders - 1, providers.size()); 179 assertFalse(hasTestProvider(providers)); 180 } 181 hasTestProvider(List<String> providers)182 private boolean hasTestProvider(List<String> providers) { 183 return hasProvider(providers, TEST_MOCK_PROVIDER_NAME); 184 } 185 hasGpsProvider(List<String> providers)186 private boolean hasGpsProvider(List<String> providers) { 187 return hasProvider(providers, LocationManager.GPS_PROVIDER); 188 } 189 hasGpsFeature()190 private boolean hasGpsFeature() { 191 return mContext.getPackageManager().hasSystemFeature( 192 PackageManager.FEATURE_LOCATION_GPS); 193 } 194 hasProvider(List<String> providers, String providerName)195 private boolean hasProvider(List<String> providers, String providerName) { 196 for (String provider : providers) { 197 if (provider != null && provider.equals(providerName)) { 198 return true; 199 } 200 } 201 return false; 202 } 203 testGetProvider()204 public void testGetProvider() { 205 LocationProvider p = mManager.getProvider(TEST_MOCK_PROVIDER_NAME); 206 assertNotNull(p); 207 assertEquals(TEST_MOCK_PROVIDER_NAME, p.getName()); 208 209 p = mManager.getProvider(LocationManager.GPS_PROVIDER); 210 if (hasGpsFeature()) { 211 assertNotNull(p); 212 assertEquals(LocationManager.GPS_PROVIDER, p.getName()); 213 } else { 214 assertNull(p); 215 } 216 217 p = mManager.getProvider(UNKNOWN_PROVIDER_NAME); 218 assertNull(p); 219 220 try { 221 mManager.getProvider(null); 222 fail("Should throw IllegalArgumentException when provider is null!"); 223 } catch (IllegalArgumentException e) { 224 // expected 225 } 226 } 227 testGetProvidersWithCriteria()228 public void testGetProvidersWithCriteria() { 229 Criteria criteria = new Criteria(); 230 List<String> providers = mManager.getProviders(criteria, true); 231 assertTrue(providers.size() >= 1); 232 assertTrue(hasTestProvider(providers)); 233 234 criteria = new Criteria(); 235 criteria.setPowerRequirement(Criteria.POWER_HIGH); 236 String p = mManager.getBestProvider(criteria, true); 237 if (p != null) { // we may not have any enabled providers 238 assertTrue(mManager.isProviderEnabled(p)); 239 } 240 241 criteria.setPowerRequirement(Criteria.POWER_MEDIUM); 242 p = mManager.getBestProvider(criteria, false); 243 assertNotNull(p); 244 245 criteria.setPowerRequirement(Criteria.POWER_LOW); 246 p = mManager.getBestProvider(criteria, true); 247 if (p != null) { // we may not have any enabled providers 248 assertTrue(mManager.isProviderEnabled(p)); 249 } 250 251 criteria.setPowerRequirement(Criteria.NO_REQUIREMENT); 252 p = mManager.getBestProvider(criteria, false); 253 assertNotNull(p); 254 } 255 testLocationUpdatesWithLocationListener()256 public void testLocationUpdatesWithLocationListener() throws InterruptedException { 257 doLocationUpdatesWithLocationListener(TEST_MOCK_PROVIDER_NAME); 258 259 try { 260 mManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, 261 (LocationListener) null); 262 fail("Should throw IllegalArgumentException if param listener is null!"); 263 } catch (IllegalArgumentException e) { 264 // expected 265 } 266 267 try { 268 mManager.requestLocationUpdates(null, 0, 0, new MockLocationListener()); 269 fail("Should throw IllegalArgumentException if param provider is null!"); 270 } catch (IllegalArgumentException e) { 271 // expected 272 } 273 274 try { 275 mManager.removeUpdates( (LocationListener) null ); 276 fail("Should throw IllegalArgumentException if listener is null!"); 277 } catch (IllegalArgumentException e) { 278 // expected 279 } 280 281 try { 282 mManager.clearTestProviderLocation(UNKNOWN_PROVIDER_NAME); 283 fail("Should throw IllegalArgumentException if provider is unknown!"); 284 } catch (IllegalArgumentException e) { 285 // expected 286 } 287 } 288 289 /** 290 * Helper method to test a location update with given provider 291 * 292 * @param providerName name of provider to test. Must already exist. 293 * @throws InterruptedException 294 */ doLocationUpdatesWithLocationListener(final String providerName)295 private void doLocationUpdatesWithLocationListener(final String providerName) 296 throws InterruptedException { 297 final double latitude1 = 10; 298 final double longitude1 = 40; 299 final double latitude2 = 35; 300 final double longitude2 = 80; 301 final MockLocationListener listener = new MockLocationListener(); 302 303 // update location and notify listener 304 new Thread(new Runnable() { 305 public void run() { 306 Looper.prepare(); 307 mManager.requestLocationUpdates(providerName, 0, 0, listener); 308 listener.setLocationRequested(); 309 Looper.loop(); 310 } 311 }).start(); 312 // wait for location requested to be called first, otherwise setLocation can be called 313 // before there is a listener attached 314 assertTrue(listener.hasCalledLocationRequested(TEST_TIME_OUT)); 315 updateLocation(providerName, latitude1, longitude1); 316 assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT)); 317 Location location = listener.getLocation(); 318 assertEquals(providerName, location.getProvider()); 319 assertEquals(latitude1, location.getLatitude()); 320 assertEquals(longitude1, location.getLongitude()); 321 322 // update location without notifying listener 323 listener.reset(); 324 assertFalse(listener.hasCalledOnLocationChanged(0)); 325 mManager.removeUpdates(listener); 326 updateLocation(providerName, latitude2, longitude2); 327 assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT)); 328 } 329 330 /** 331 * Verifies that all real location providers can be replaced by a mock provider. 332 * <p/> 333 * This feature is quite useful for developer automated testing. 334 * This test may fail if another unknown test provider already exists, because there is no 335 * known way to determine if a given provider is a test provider. 336 * @throws InterruptedException 337 */ testReplaceRealProvidersWithMocks()338 public void testReplaceRealProvidersWithMocks() throws InterruptedException { 339 for (String providerName : mManager.getAllProviders()) { 340 if (!providerName.equals(TEST_MOCK_PROVIDER_NAME) && 341 !providerName.equals(LocationManager.PASSIVE_PROVIDER)) { 342 addTestProvider(providerName); 343 try { 344 // run the update location test logic to ensure location updates can be injected 345 doLocationUpdatesWithLocationListener(providerName); 346 } finally { 347 mManager.removeTestProvider(providerName); 348 } 349 } 350 } 351 } 352 testLocationUpdatesWithLocationListenerAndLooper()353 public void testLocationUpdatesWithLocationListenerAndLooper() throws InterruptedException { 354 double latitude1 = 60; 355 double longitude1 = 20; 356 double latitude2 = 40; 357 double longitude2 = 30; 358 final MockLocationListener listener = new MockLocationListener(); 359 360 // update location and notify listener 361 HandlerThread handlerThread = new HandlerThread("testLocationUpdates"); 362 handlerThread.start(); 363 mManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 0, 0, listener, 364 handlerThread.getLooper()); 365 366 updateLocation(latitude1, longitude1); 367 assertTrue(listener.hasCalledOnLocationChanged(TEST_TIME_OUT)); 368 Location location = listener.getLocation(); 369 assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider()); 370 assertEquals(latitude1, location.getLatitude()); 371 assertEquals(longitude1, location.getLongitude()); 372 373 // update location without notifying listener 374 mManager.removeUpdates(listener); 375 listener.reset(); 376 updateLocation(latitude2, longitude2); 377 assertFalse(listener.hasCalledOnLocationChanged(TEST_TIME_OUT)); 378 379 try { 380 mManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, 381 (LocationListener) null, Looper.myLooper()); 382 fail("Should throw IllegalArgumentException if param listener is null!"); 383 } catch (IllegalArgumentException e) { 384 // expected 385 } 386 387 try { 388 mManager.requestLocationUpdates(null, 0, 0, listener, Looper.myLooper()); 389 fail("Should throw IllegalArgumentException if param provider is null!"); 390 } catch (IllegalArgumentException e) { 391 // expected 392 } 393 394 try { 395 mManager.removeUpdates( (LocationListener) null ); 396 fail("Should throw IllegalArgumentException if listener is null!"); 397 } catch (IllegalArgumentException e) { 398 // expected 399 } 400 } 401 testLocationUpdatesWithPendingIntent()402 public void testLocationUpdatesWithPendingIntent() throws InterruptedException { 403 double latitude1 = 20; 404 double longitude1 = 40; 405 double latitude2 = 30; 406 double longitude2 = 50; 407 408 // update location and receive broadcast. 409 registerIntentReceiver(); 410 mManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 0, 0, mPendingIntent); 411 updateLocation(latitude1, longitude1); 412 waitForReceiveBroadcast(); 413 414 assertNotNull(mIntentReceiver.getLastReceivedIntent()); 415 Location location = mManager.getLastKnownLocation(TEST_MOCK_PROVIDER_NAME); 416 assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider()); 417 assertEquals(latitude1, location.getLatitude()); 418 assertEquals(longitude1, location.getLongitude()); 419 420 // update location without receiving broadcast. 421 mManager.removeUpdates(mPendingIntent); 422 mIntentReceiver.clearReceivedIntents(); 423 updateLocation(latitude2, longitude2); 424 waitForReceiveBroadcast(); 425 assertNull(mIntentReceiver.getLastReceivedIntent()); 426 427 try { 428 mManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, 429 (PendingIntent) null); 430 fail("Should throw IllegalArgumentException if param intent is null!"); 431 } catch (IllegalArgumentException e) { 432 // expected 433 } 434 435 try { 436 mManager.requestLocationUpdates(null, 0, 0, mPendingIntent); 437 fail("Should throw IllegalArgumentException if param provider is null!"); 438 } catch (IllegalArgumentException e) { 439 // expected 440 } 441 442 try { 443 mManager.removeUpdates( (PendingIntent) null ); 444 fail("Should throw IllegalArgumentException if intent is null!"); 445 } catch (IllegalArgumentException e) { 446 // expected 447 } 448 } 449 testAddProximityAlert()450 public void testAddProximityAlert() { 451 Intent i = new Intent(); 452 i.setAction("android.location.cts.TEST_GET_GPS_STATUS_ACTION"); 453 PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_ONE_SHOT); 454 455 mManager.addProximityAlert(0, 0, 0, 5000, pi); 456 mManager.removeProximityAlert(pi); 457 } 458 testIsProviderEnabled()459 public void testIsProviderEnabled() { 460 // this test assumes enabled TEST_MOCK_PROVIDER_NAME was created in setUp. 461 assertNotNull(mManager.getProvider(TEST_MOCK_PROVIDER_NAME)); 462 assertTrue(mManager.isProviderEnabled(TEST_MOCK_PROVIDER_NAME)); 463 464 mManager.clearTestProviderEnabled(TEST_MOCK_PROVIDER_NAME); 465 assertFalse(mManager.isProviderEnabled(TEST_MOCK_PROVIDER_NAME)); 466 467 mManager.setTestProviderEnabled(TEST_MOCK_PROVIDER_NAME, true); 468 assertTrue(mManager.isProviderEnabled(TEST_MOCK_PROVIDER_NAME)); 469 470 try { 471 mManager.isProviderEnabled(null); 472 fail("Should throw IllegalArgumentException if provider is null!"); 473 } catch (IllegalArgumentException e) { 474 // expected 475 } 476 477 try { 478 mManager.clearTestProviderEnabled(UNKNOWN_PROVIDER_NAME); 479 fail("Should throw IllegalArgumentException if provider is unknown!"); 480 } catch (IllegalArgumentException e) { 481 // expected 482 } 483 484 try { 485 mManager.setTestProviderEnabled(UNKNOWN_PROVIDER_NAME, false); 486 fail("Should throw IllegalArgumentException if provider is unknown!"); 487 } catch (IllegalArgumentException e) { 488 // expected 489 } 490 } 491 testGetLastKnownLocation()492 public void testGetLastKnownLocation() throws InterruptedException { 493 double latitude1 = 20; 494 double longitude1 = 40; 495 double latitude2 = 10; 496 double longitude2 = 70; 497 498 registerIntentReceiver(); 499 mManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 0, 0, mPendingIntent); 500 updateLocation(latitude1, longitude1); 501 waitForReceiveBroadcast(); 502 503 assertNotNull(mIntentReceiver.getLastReceivedIntent()); 504 Location location = mManager.getLastKnownLocation(TEST_MOCK_PROVIDER_NAME); 505 assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider()); 506 assertEquals(latitude1, location.getLatitude()); 507 assertEquals(longitude1, location.getLongitude()); 508 509 mIntentReceiver.clearReceivedIntents(); 510 updateLocation(latitude2, longitude2); 511 waitForReceiveBroadcast(); 512 513 assertNotNull(mIntentReceiver.getLastReceivedIntent()); 514 location = mManager.getLastKnownLocation(TEST_MOCK_PROVIDER_NAME); 515 assertEquals(TEST_MOCK_PROVIDER_NAME, location.getProvider()); 516 assertEquals(latitude2, location.getLatitude()); 517 assertEquals(longitude2, location.getLongitude()); 518 519 try { 520 mManager.getLastKnownLocation(null); 521 fail("Should throw IllegalArgumentException if provider is null!"); 522 } catch (IllegalArgumentException e) { 523 // expected 524 } 525 } 526 testGpsStatusListener()527 public void testGpsStatusListener() { 528 MockGpsStatusListener listener = new MockGpsStatusListener(); 529 mManager.addGpsStatusListener(listener); 530 mManager.removeGpsStatusListener(listener); 531 532 mManager.addGpsStatusListener(null); 533 mManager.removeGpsStatusListener(null); 534 } 535 testGetGpsStatus()536 public void testGetGpsStatus() { 537 GpsStatus status = mManager.getGpsStatus(null); 538 assertNotNull(status); 539 assertSame(status, mManager.getGpsStatus(status)); 540 } 541 testSendExtraCommand()542 public void testSendExtraCommand() { 543 // this test assumes TEST_MOCK_PROVIDER_NAME was created in setUp. 544 assertNotNull(mManager.getProvider(TEST_MOCK_PROVIDER_NAME)); 545 // Unknown command 546 assertFalse(mManager.sendExtraCommand(TEST_MOCK_PROVIDER_NAME, "unknown", new Bundle())); 547 548 assertNull(mManager.getProvider(UNKNOWN_PROVIDER_NAME)); 549 assertFalse(mManager.sendExtraCommand(UNKNOWN_PROVIDER_NAME, "unknown", new Bundle())); 550 } 551 testSetTestProviderStatus()552 public void testSetTestProviderStatus() throws InterruptedException { 553 final int status = LocationProvider.TEMPORARILY_UNAVAILABLE; 554 final long updateTime = 1000; 555 final MockLocationListener listener = new MockLocationListener(); 556 557 HandlerThread handlerThread = new HandlerThread("testStatusUpdates"); 558 handlerThread.start(); 559 560 // set status successfully 561 mManager.requestLocationUpdates(TEST_MOCK_PROVIDER_NAME, 0, 0, listener, 562 handlerThread.getLooper()); 563 mManager.setTestProviderStatus(TEST_MOCK_PROVIDER_NAME, status, null, updateTime); 564 // setting the status alone is not sufficient to trigger a status update 565 updateLocation(10, 30); 566 assertTrue(listener.hasCalledOnStatusChanged(TEST_TIME_OUT)); 567 assertEquals(TEST_MOCK_PROVIDER_NAME, listener.getProvider()); 568 assertEquals(status, listener.getStatus()); 569 570 try { 571 mManager.setTestProviderStatus(UNKNOWN_PROVIDER_NAME, 0, null, 572 System.currentTimeMillis()); 573 fail("Should throw IllegalArgumentException if provider is unknown!"); 574 } catch (IllegalArgumentException e) { 575 // expected 576 } 577 578 try { 579 mManager.clearTestProviderStatus(UNKNOWN_PROVIDER_NAME); 580 fail("Should throw IllegalArgumentException if provider is unknown!"); 581 } catch (IllegalArgumentException e) { 582 // expected 583 } 584 } 585 586 /** 587 * Tests basic proximity alert when entering proximity 588 */ testEnterProximity()589 public void testEnterProximity() throws Exception { 590 doTestEnterProximity(10000); 591 } 592 593 /** 594 * Tests proximity alert when entering proximity, with no expiration 595 */ testEnterProximity_noexpire()596 public void testEnterProximity_noexpire() throws Exception { 597 doTestEnterProximity(-1); 598 } 599 600 /** 601 * Tests basic proximity alert when exiting proximity 602 */ testExitProximity()603 public void testExitProximity() throws Exception { 604 // first do enter proximity scenario 605 doTestEnterProximity(-1); 606 607 // now update to trigger exit proximity proximity 608 mIntentReceiver.clearReceivedIntents(); 609 updateLocation(20, 20); 610 waitForReceiveBroadcast(); 611 assertProximityType(false); 612 } 613 614 /** 615 * Helper variant for testing enter proximity scenario 616 * TODO: add additional parameters as more scenarios are added 617 * 618 * @param expiration - expiration of proximity alert 619 */ doTestEnterProximity(long expiration)620 private void doTestEnterProximity(long expiration) throws Exception { 621 // update location to outside proximity range 622 updateLocation(30, 30); 623 registerProximityListener(0, 0, 1000, expiration); 624 updateLocation(0, 0); 625 waitForReceiveBroadcast(); 626 assertProximityType(true); 627 } 628 registerIntentReceiver()629 private void registerIntentReceiver() { 630 String intentKey = "LocationManagerTest"; 631 Intent proximityIntent = new Intent(intentKey); 632 mPendingIntent = PendingIntent.getBroadcast(mContext, 0, proximityIntent, 633 PendingIntent.FLAG_CANCEL_CURRENT); 634 mIntentReceiver = new TestIntentReceiver(intentKey); 635 mContext.registerReceiver(mIntentReceiver, mIntentReceiver.getFilter()); 636 } 637 638 /** 639 * Registers the proximity intent receiver 640 */ registerProximityListener(double latitude, double longitude, float radius, long expiration)641 private void registerProximityListener(double latitude, double longitude, float radius, 642 long expiration) { 643 registerIntentReceiver(); 644 mManager.addProximityAlert(latitude, longitude, radius, expiration, mPendingIntent); 645 } 646 647 /** 648 * Blocks until receive intent notification or time out. 649 * 650 * @throws InterruptedException 651 */ waitForReceiveBroadcast()652 private void waitForReceiveBroadcast() throws InterruptedException { 653 synchronized (mIntentReceiver) { 654 mIntentReceiver.wait(TEST_TIME_OUT); 655 } 656 } 657 658 /** 659 * Asserts that the received intent had the enter proximity property set as 660 * expected 661 * 662 * @param expectedEnterProximity - true if enter proximity expected, false 663 * if exit expected 664 */ assertProximityType(boolean expectedEnterProximity)665 private void assertProximityType(boolean expectedEnterProximity) throws Exception { 666 boolean proximityTest = mIntentReceiver.getLastReceivedIntent().getBooleanExtra( 667 LocationManager.KEY_PROXIMITY_ENTERING, !expectedEnterProximity); 668 assertEquals("proximity alert not set to expected enter proximity value", 669 expectedEnterProximity, proximityTest); 670 } 671 updateLocation(final String providerName, final double latitude, final double longitude)672 private void updateLocation(final String providerName, final double latitude, 673 final double longitude) { 674 Location location = new Location(providerName); 675 location.setLatitude(latitude); 676 location.setLongitude(longitude); 677 678 location.setTime(java.lang.System.currentTimeMillis()); 679 mManager.setTestProviderLocation(providerName, location); 680 } 681 updateLocation(final double latitude, final double longitude)682 private void updateLocation(final double latitude, final double longitude) { 683 updateLocation(TEST_MOCK_PROVIDER_NAME, latitude, longitude); 684 } 685 686 /** 687 * Helper class that receives a proximity intent and notifies the main class 688 * when received 689 */ 690 private static class TestIntentReceiver extends BroadcastReceiver { 691 private String mExpectedAction; 692 693 private Intent mLastReceivedIntent; 694 TestIntentReceiver(String expectedAction)695 public TestIntentReceiver(String expectedAction) { 696 mExpectedAction = expectedAction; 697 mLastReceivedIntent = null; 698 } 699 getFilter()700 public IntentFilter getFilter() { 701 IntentFilter filter = new IntentFilter(mExpectedAction); 702 return filter; 703 } 704 705 @Override onReceive(Context context, Intent intent)706 public void onReceive(Context context, Intent intent) { 707 if (intent != null && mExpectedAction.equals(intent.getAction())) { 708 synchronized (this) { 709 mLastReceivedIntent = intent; 710 notify(); 711 } 712 } 713 } 714 getLastReceivedIntent()715 public Intent getLastReceivedIntent() { 716 return mLastReceivedIntent; 717 } 718 clearReceivedIntents()719 public void clearReceivedIntents() { 720 mLastReceivedIntent = null; 721 } 722 } 723 724 private static class MockLocationListener implements LocationListener { 725 private String mProvider; 726 private int mStatus; 727 private Location mLocation; 728 private Object mStatusLock = new Object(); 729 private Object mLocationLock = new Object(); 730 private Object mLocationRequestLock = new Object(); 731 732 private boolean mHasCalledOnLocationChanged; 733 734 private boolean mHasCalledOnProviderDisabled; 735 736 private boolean mHasCalledOnProviderEnabled; 737 738 private boolean mHasCalledOnStatusChanged; 739 740 private boolean mHasCalledRequestLocation; 741 reset()742 public void reset(){ 743 mHasCalledOnLocationChanged = false; 744 mHasCalledOnProviderDisabled = false; 745 mHasCalledOnProviderEnabled = false; 746 mHasCalledOnStatusChanged = false; 747 mHasCalledRequestLocation = false; 748 mProvider = null; 749 mStatus = 0; 750 } 751 752 /** 753 * Call to inform listener that location has been updates have been requested 754 */ setLocationRequested()755 public void setLocationRequested() { 756 synchronized (mLocationRequestLock) { 757 mHasCalledRequestLocation = true; 758 mLocationRequestLock.notify(); 759 } 760 } 761 hasCalledLocationRequested(long timeout)762 public boolean hasCalledLocationRequested(long timeout) throws InterruptedException { 763 synchronized (mLocationRequestLock) { 764 if (timeout > 0 && !mHasCalledRequestLocation) { 765 mLocationRequestLock.wait(timeout); 766 } 767 } 768 return mHasCalledRequestLocation; 769 } 770 771 /** 772 * Check whether onLocationChanged() has been called. Wait up to timeout milliseconds 773 * for the callback. 774 * @param timeout Maximum time to wait for the callback, 0 to return immediately. 775 */ hasCalledOnLocationChanged(long timeout)776 public boolean hasCalledOnLocationChanged(long timeout) throws InterruptedException { 777 synchronized (mLocationLock) { 778 if (timeout > 0 && !mHasCalledOnLocationChanged) { 779 mLocationLock.wait(timeout); 780 } 781 } 782 return mHasCalledOnLocationChanged; 783 } 784 hasCalledOnProviderDisabled()785 public boolean hasCalledOnProviderDisabled() { 786 return mHasCalledOnProviderDisabled; 787 } 788 hasCalledOnProviderEnabled()789 public boolean hasCalledOnProviderEnabled() { 790 return mHasCalledOnProviderEnabled; 791 } 792 hasCalledOnStatusChanged(long timeout)793 public boolean hasCalledOnStatusChanged(long timeout) throws InterruptedException { 794 synchronized(mStatusLock) { 795 // wait(0) would wait forever 796 if (timeout > 0 && !mHasCalledOnStatusChanged) { 797 mStatusLock.wait(timeout); 798 } 799 } 800 return mHasCalledOnStatusChanged; 801 } 802 onLocationChanged(Location location)803 public void onLocationChanged(Location location) { 804 mLocation = location; 805 synchronized (mLocationLock) { 806 mHasCalledOnLocationChanged = true; 807 mLocationLock.notify(); 808 } 809 } 810 onProviderDisabled(String provider)811 public void onProviderDisabled(String provider) { 812 mHasCalledOnProviderDisabled = true; 813 } 814 onProviderEnabled(String provider)815 public void onProviderEnabled(String provider) { 816 mHasCalledOnProviderEnabled = true; 817 } 818 onStatusChanged(String provider, int status, Bundle extras)819 public void onStatusChanged(String provider, int status, Bundle extras) { 820 mProvider = provider; 821 mStatus = status; 822 synchronized (mStatusLock) { 823 mHasCalledOnStatusChanged = true; 824 mStatusLock.notify(); 825 } 826 } 827 getProvider()828 public String getProvider() { 829 return mProvider; 830 } 831 getStatus()832 public int getStatus() { 833 return mStatus; 834 } 835 getLocation()836 public Location getLocation() { 837 return mLocation; 838 } 839 } 840 841 private static class MockGpsStatusListener implements Listener { 842 private boolean mHasCallOnGpsStatusChanged; 843 hasCallOnGpsStatusChanged()844 public boolean hasCallOnGpsStatusChanged() { 845 return mHasCallOnGpsStatusChanged; 846 } 847 reset()848 public void reset(){ 849 mHasCallOnGpsStatusChanged = false; 850 } 851 onGpsStatusChanged(int event)852 public void onGpsStatusChanged(int event) { 853 mHasCallOnGpsStatusChanged = true; 854 } 855 } 856 } 857