• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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