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 import android.content.Context;
20 import android.content.Intent;
21 import android.location.Location;
22 import android.location.SettingInjectorService;
23 import android.os.Handler;
24 import android.os.IBinder;
25 import android.os.Looper;
26 import android.os.Message;
27 import android.os.Messenger;
28 import android.os.Bundle;
29 import android.os.Parcel;
30 import android.test.AndroidTestCase;
31 import android.util.Printer;
32 import android.util.StringBuilderPrinter;
33 
34 import java.text.DecimalFormat;
35 
36 public class LocationTest extends AndroidTestCase {
37     private static final float DELTA = 0.1f;
38     private final float TEST_ACCURACY = 1.0f;
39     private final float TEST_VERTICAL_ACCURACY = 2.0f;
40     private final float TEST_SPEED_ACCURACY = 3.0f;
41     private final float TEST_BEARING_ACCURACY = 4.0f;
42     private final double TEST_ALTITUDE = 1.0;
43     private final double TEST_LATITUDE = 50;
44     private final float TEST_BEARING = 1.0f;
45     private final double TEST_LONGITUDE = 20;
46     private final float TEST_SPEED = 5.0f;
47     private final long TEST_TIME = 100;
48     private final String TEST_PROVIDER = "LocationProvider";
49     private final String TEST_KEY1NAME = "key1";
50     private final String TEST_KEY2NAME = "key2";
51     private final boolean TEST_KEY1VALUE = false;
52     private final byte TEST_KEY2VALUE = 10;
53 
54     private static final String ENABLED_KEY = "enabled";
55     private static final String MESSENGER_KEY = "messenger";
56 
57 
testConstructor()58     public void testConstructor() {
59         new Location("LocationProvider");
60 
61         Location l = createTestLocation();
62         Location location = new Location(l);
63         assertTestLocation(location);
64 
65         try {
66             new Location((Location) null);
67             fail("should throw NullPointerException");
68         } catch (NullPointerException e) {
69             // expected.
70         }
71     }
72 
testDump()73     public void testDump() {
74         StringBuilder sb = new StringBuilder();
75         StringBuilderPrinter printer = new StringBuilderPrinter(sb);
76         Location location = new Location("LocationProvider");
77         location.dump(printer, "");
78         assertNotNull(sb.toString());
79     }
80 
testBearingTo()81     public void testBearingTo() {
82         Location location = new Location("");
83         Location dest = new Location("");
84 
85         // set the location to Beijing
86         location.setLatitude(39.9);
87         location.setLongitude(116.4);
88         // set the destination to Chengdu
89         dest.setLatitude(30.7);
90         dest.setLongitude(104.1);
91         assertEquals(-128.66, location.bearingTo(dest), DELTA);
92 
93         float bearing;
94         Location zeroLocation = new Location("");
95         zeroLocation.setLatitude(0);
96         zeroLocation.setLongitude(0);
97 
98         Location testLocation = new Location("");
99         testLocation.setLatitude(0);
100         testLocation.setLongitude(150);
101 
102         bearing = zeroLocation.bearingTo(zeroLocation);
103         assertEquals(0.0f, bearing, DELTA);
104 
105         bearing = zeroLocation.bearingTo(testLocation);
106         assertEquals(90.0f, bearing, DELTA);
107 
108         testLocation.setLatitude(90);
109         testLocation.setLongitude(0);
110         bearing = zeroLocation.bearingTo(testLocation);
111         assertEquals(0.0f, bearing, DELTA);
112 
113         try {
114             location.bearingTo(null);
115             fail("should throw NullPointerException");
116         } catch (NullPointerException e) {
117             // expected.
118         }
119     }
120 
testConvert_CoordinateToRepresentation()121     public void testConvert_CoordinateToRepresentation() {
122         DecimalFormat df = new DecimalFormat("###.#####");
123         String result;
124 
125         result = Location.convert(-80.0, Location.FORMAT_DEGREES);
126         assertEquals("-" + df.format(80.0), result);
127 
128         result = Location.convert(-80.085, Location.FORMAT_MINUTES);
129         assertEquals("-80:" + df.format(5.1), result);
130 
131         result = Location.convert(-80, Location.FORMAT_MINUTES);
132         assertEquals("-80:" + df.format(0), result);
133 
134         result = Location.convert(-80.075, Location.FORMAT_MINUTES);
135         assertEquals("-80:" + df.format(4.5), result);
136 
137         result = Location.convert(-80.075, Location.FORMAT_DEGREES);
138         assertEquals("-" + df.format(80.075), result);
139 
140         result = Location.convert(-80.075, Location.FORMAT_SECONDS);
141         assertEquals("-80:4:30", result);
142 
143         try {
144             Location.convert(-181, Location.FORMAT_SECONDS);
145             fail("should throw IllegalArgumentException.");
146         } catch (IllegalArgumentException e) {
147             // expected.
148         }
149 
150         try {
151             Location.convert(181, Location.FORMAT_SECONDS);
152             fail("should throw IllegalArgumentException.");
153         } catch (IllegalArgumentException e) {
154             // expected.
155         }
156 
157         try {
158             Location.convert(-80.075, -1);
159             fail("should throw IllegalArgumentException.");
160         } catch (IllegalArgumentException e) {
161             // expected.
162         }
163     }
164 
testConvert_RepresentationToCoordinate()165     public void testConvert_RepresentationToCoordinate() {
166         double result;
167 
168         result = Location.convert("-80.075");
169         assertEquals(-80.075, result);
170 
171         result = Location.convert("-80:05.10000");
172         assertEquals(-80.085, result);
173 
174         result = Location.convert("-80:04:03.00000");
175         assertEquals(-80.0675, result);
176 
177         result = Location.convert("-80:4:3");
178         assertEquals(-80.0675, result);
179 
180         try {
181             Location.convert(null);
182             fail("should throw NullPointerException.");
183         } catch (NullPointerException e){
184             // expected.
185         }
186 
187         try {
188             Location.convert(":");
189             fail("should throw IllegalArgumentException.");
190         } catch (IllegalArgumentException e){
191             // expected.
192         }
193 
194         try {
195             Location.convert("190:4:3");
196             fail("should throw IllegalArgumentException.");
197         } catch (IllegalArgumentException e){
198             // expected.
199         }
200 
201         try {
202             Location.convert("-80:60:3");
203             fail("should throw IllegalArgumentException.");
204         } catch (IllegalArgumentException e){
205             // expected.
206         }
207 
208         try {
209             Location.convert("-80:4:60");
210             fail("should throw IllegalArgumentException.");
211         } catch (IllegalArgumentException e){
212             // expected.
213         }
214     }
215 
testDescribeContents()216     public void testDescribeContents() {
217         Location location = new Location("");
218         location.describeContents();
219     }
220 
testDistanceBetween()221     public void testDistanceBetween() {
222         float[] result = new float[3];
223         Location.distanceBetween(0, 0, 0, 0, result);
224         assertEquals(0.0, result[0], DELTA);
225         assertEquals(0.0, result[1], DELTA);
226         assertEquals(0.0, result[2], DELTA);
227 
228         Location.distanceBetween(20, 30, -40, 140, result);
229         assertEquals(1.3094936E7, result[0], 1);
230         assertEquals(125.4538, result[1], DELTA);
231         assertEquals(93.3971, result[2], DELTA);
232 
233         try {
234             Location.distanceBetween(20, 30, -40, 140, null);
235             fail("should throw IllegalArgumentException");
236         } catch (IllegalArgumentException e) {
237             // expected.
238         }
239 
240         try {
241             Location.distanceBetween(20, 30, -40, 140, new float[0]);
242             fail("should throw IllegalArgumentException");
243         } catch (IllegalArgumentException e) {
244             // expected.
245         }
246     }
247 
testDistanceTo()248     public void testDistanceTo() {
249         float distance;
250         Location zeroLocation = new Location("");
251         zeroLocation.setLatitude(0);
252         zeroLocation.setLongitude(0);
253 
254         Location testLocation = new Location("");
255         testLocation.setLatitude(30);
256         testLocation.setLongitude(50);
257 
258         distance = zeroLocation.distanceTo(zeroLocation);
259         assertEquals(0, distance, DELTA);
260 
261         distance = zeroLocation.distanceTo(testLocation);
262         assertEquals(6244139.0, distance, 1);
263     }
264 
testAccessAccuracy()265     public void testAccessAccuracy() {
266         Location location = new Location("");
267         assertFalse(location.hasAccuracy());
268 
269         location.setAccuracy(1.0f);
270         assertEquals(1.0, location.getAccuracy(), DELTA);
271         assertTrue(location.hasAccuracy());
272 
273         location.removeAccuracy();
274         assertEquals(0.0, location.getAccuracy(), DELTA);
275         assertFalse(location.hasAccuracy());
276     }
277 
testAccessVerticalAccuracy()278     public void testAccessVerticalAccuracy() {
279         Location location = new Location("");
280         assertFalse(location.hasVerticalAccuracy());
281 
282         location.setVerticalAccuracyMeters(1.0f);
283         assertEquals(1.0, location.getVerticalAccuracyMeters(), DELTA);
284         assertTrue(location.hasVerticalAccuracy());
285     }
286 
testAccessSpeedAccuracy()287     public void testAccessSpeedAccuracy() {
288         Location location = new Location("");
289         assertFalse(location.hasSpeedAccuracy());
290 
291         location.setSpeedAccuracyMetersPerSecond(1.0f);
292         assertEquals(1.0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
293         assertTrue(location.hasSpeedAccuracy());
294     }
295 
testAccessBearingAccuracy()296     public void testAccessBearingAccuracy() {
297         Location location = new Location("");
298         assertFalse(location.hasBearingAccuracy());
299 
300         location.setBearingAccuracyDegrees(1.0f);
301         assertEquals(1.0, location.getBearingAccuracyDegrees(), DELTA);
302         assertTrue(location.hasBearingAccuracy());
303     }
304 
305 
testAccessAltitude()306     public void testAccessAltitude() {
307         Location location = new Location("");
308         assertFalse(location.hasAltitude());
309 
310         location.setAltitude(1.0);
311         assertEquals(1.0, location.getAltitude(), DELTA);
312         assertTrue(location.hasAltitude());
313 
314         location.removeAltitude();
315         assertEquals(0.0, location.getAltitude(), DELTA);
316         assertFalse(location.hasAltitude());
317     }
318 
testAccessBearing()319     public void testAccessBearing() {
320         Location location = new Location("");
321         assertFalse(location.hasBearing());
322 
323         location.setBearing(1.0f);
324         assertEquals(1.0, location.getBearing(), DELTA);
325         assertTrue(location.hasBearing());
326 
327         location.setBearing(371.0f);
328         assertEquals(11.0, location.getBearing(), DELTA);
329         assertTrue(location.hasBearing());
330 
331         location.setBearing(-361.0f);
332         assertEquals(359.0, location.getBearing(), DELTA);
333         assertTrue(location.hasBearing());
334 
335         location.removeBearing();
336         assertEquals(0.0, location.getBearing(), DELTA);
337         assertFalse(location.hasBearing());
338     }
339 
testAccessExtras()340     public void testAccessExtras() {
341         Location location = createTestLocation();
342 
343         assertTestBundle(location.getExtras());
344 
345         location.setExtras(null);
346         assertNull(location.getExtras());
347     }
348 
testAccessLatitude()349     public void testAccessLatitude() {
350         Location location = new Location("");
351 
352         location.setLatitude(0);
353         assertEquals(0, location.getLatitude(), DELTA);
354 
355         location.setLatitude(90);
356         assertEquals(90, location.getLatitude(), DELTA);
357 
358         location.setLatitude(-90);
359         assertEquals(-90, location.getLatitude(), DELTA);
360     }
361 
testAccessLongitude()362     public void testAccessLongitude() {
363         Location location = new Location("");
364 
365         location.setLongitude(0);
366         assertEquals(0, location.getLongitude(), DELTA);
367 
368         location.setLongitude(180);
369         assertEquals(180, location.getLongitude(), DELTA);
370 
371         location.setLongitude(-180);
372         assertEquals(-180, location.getLongitude(), DELTA);
373     }
374 
testAccessProvider()375     public void testAccessProvider() {
376         Location location = new Location("");
377 
378         String provider = "Location Provider";
379         location.setProvider(provider);
380         assertEquals(provider, location.getProvider());
381 
382         location.setProvider(null);
383         assertNull(location.getProvider());
384     }
385 
testAccessSpeed()386     public void testAccessSpeed() {
387         Location location = new Location("");
388         assertFalse(location.hasSpeed());
389 
390         location.setSpeed(234.0045f);
391         assertEquals(234.0045, location.getSpeed(), DELTA);
392         assertTrue(location.hasSpeed());
393 
394         location.removeSpeed();
395         assertEquals(0.0, location.getSpeed(), DELTA);
396         assertFalse(location.hasSpeed());
397     }
398 
testAccessTime()399     public void testAccessTime() {
400         Location location = new Location("");
401 
402         location.setTime(0);
403         assertEquals(0, location.getTime());
404 
405         location.setTime(Long.MAX_VALUE);
406         assertEquals(Long.MAX_VALUE, location.getTime());
407 
408         location.setTime(12000);
409         assertEquals(12000, location.getTime());
410     }
411 
testAccessElapsedRealtime()412     public void testAccessElapsedRealtime() {
413         Location location = new Location("");
414 
415         location.setElapsedRealtimeNanos(0);
416         assertEquals(0, location.getElapsedRealtimeNanos());
417 
418         location.setElapsedRealtimeNanos(Long.MAX_VALUE);
419         assertEquals(Long.MAX_VALUE, location.getElapsedRealtimeNanos());
420 
421         location.setElapsedRealtimeNanos(12000);
422         assertEquals(12000, location.getElapsedRealtimeNanos());
423     }
424 
testSet()425     public void testSet() {
426         Location location = new Location("");
427 
428         Location loc = createTestLocation();
429 
430         location.set(loc);
431         assertTestLocation(location);
432 
433         location.reset();
434         assertNull(location.getProvider());
435         assertEquals(0, location.getTime());
436         assertEquals(0, location.getLatitude(), DELTA);
437         assertEquals(0, location.getLongitude(), DELTA);
438         assertEquals(0, location.getAltitude(), DELTA);
439         assertFalse(location.hasAltitude());
440         assertEquals(0, location.getSpeed(), DELTA);
441         assertFalse(location.hasSpeed());
442         assertEquals(0, location.getBearing(), DELTA);
443         assertFalse(location.hasBearing());
444         assertEquals(0, location.getAccuracy(), DELTA);
445         assertFalse(location.hasAccuracy());
446 
447         assertEquals(0, location.getVerticalAccuracyMeters(), DELTA);
448         assertEquals(0, location.getSpeedAccuracyMetersPerSecond(), DELTA);
449         assertEquals(0, location.getBearingAccuracyDegrees(), DELTA);
450 
451         assertFalse(location.hasVerticalAccuracy());
452         assertFalse(location.hasSpeedAccuracy());
453         assertFalse(location.hasBearingAccuracy());
454 
455         assertNull(location.getExtras());
456     }
457 
testToString()458     public void testToString() {
459         Location location = createTestLocation();
460 
461         assertNotNull(location.toString());
462     }
463 
testWriteToParcel()464     public void testWriteToParcel() {
465         Location location = createTestLocation();
466 
467         Parcel parcel = Parcel.obtain();
468         location.writeToParcel(parcel, 0);
469         parcel.setDataPosition(0);
470         Location newLocation = Location.CREATOR.createFromParcel(parcel);
471         assertTestLocation(newLocation);
472     }
473 
testSettingInjectorService()474     public void testSettingInjectorService() {
475         Context c = getContext();
476         SettingInjectorServiceDerived service = new SettingInjectorServiceDerived();
477 
478         assertNotNull(c);
479 
480         Intent intent =
481             new Intent(c, android.location.SettingInjectorService.class);
482 
483         assertNotNull(c.getMainLooper());
484         SettingInjectorResultHandler resultHandler =
485             new SettingInjectorResultHandler(c.getMainLooper());
486 
487         Messenger m = new Messenger(resultHandler);
488         intent.putExtra(MESSENGER_KEY, m);
489 
490         int ret;
491         final long timeout = 500;
492 
493         // should refuse binding
494         IBinder binder = service.callOnBind(intent);
495         assertNull("onBind should always fail.", binder);
496 
497         // test if result consistent with the truth
498         // enabled == false case
499         service.setEnabled(false);
500         resultHandler.expectEnabled(false);
501         resultHandler.expectMessage(true);
502         ret = service.callOnStartCommand(intent, SettingInjectorService.START_NOT_STICKY, 0);
503         assertEquals("onStartCommand return value invalid in (enabled == false) case.",
504             ret, SettingInjectorService.START_NOT_STICKY);
505         assertTrue("Message time out in (enabled == false case).",
506             resultHandler.waitForMessage(timeout));
507 
508         // enabled == true case
509         service.setEnabled(true);
510         assertTrue(service.onGetEnabled());
511         assertEquals("Summary", service.onGetSummary());
512         resultHandler.expectEnabled(true);
513         resultHandler.expectMessage(true);
514         ret = service.callOnStartCommand(intent, SettingInjectorService.START_NOT_STICKY, 0);
515         assertEquals("onStartCommand return value invalid in (enabled == true) case.",
516             ret, SettingInjectorService.START_NOT_STICKY);
517         assertTrue("Message time out in (enabled == true) case.",
518             resultHandler.waitForMessage(timeout));
519 
520         // should not respond to the deprecated method
521         resultHandler.expectMessage(false);
522         service.callOnStart(intent, 0);
523         resultHandler.waitForMessage(timeout);
524     }
525 
assertTestLocation(Location l)526     private void assertTestLocation(Location l) {
527         assertNotNull(l);
528         assertEquals(TEST_PROVIDER, l.getProvider());
529         assertEquals(TEST_ACCURACY, l.getAccuracy(), DELTA);
530         assertEquals(TEST_VERTICAL_ACCURACY, l.getVerticalAccuracyMeters(), DELTA);
531         assertEquals(TEST_SPEED_ACCURACY, l.getSpeedAccuracyMetersPerSecond(), DELTA);
532         assertEquals(TEST_BEARING_ACCURACY, l.getBearingAccuracyDegrees(), DELTA);
533         assertEquals(TEST_ALTITUDE, l.getAltitude(), DELTA);
534         assertEquals(TEST_LATITUDE, l.getLatitude(), DELTA);
535         assertEquals(TEST_BEARING, l.getBearing(), DELTA);
536         assertEquals(TEST_LONGITUDE, l.getLongitude(), DELTA);
537         assertEquals(TEST_SPEED, l.getSpeed(), DELTA);
538         assertEquals(TEST_TIME, l.getTime());
539         assertTestBundle(l.getExtras());
540     }
541 
createTestLocation()542     private Location createTestLocation() {
543         Location l = new Location(TEST_PROVIDER);
544         l.setAccuracy(TEST_ACCURACY);
545         l.setVerticalAccuracyMeters(TEST_VERTICAL_ACCURACY);
546         l.setSpeedAccuracyMetersPerSecond(TEST_SPEED_ACCURACY);
547         l.setBearingAccuracyDegrees(TEST_BEARING_ACCURACY);
548 
549         l.setAltitude(TEST_ALTITUDE);
550         l.setLatitude(TEST_LATITUDE);
551         l.setBearing(TEST_BEARING);
552         l.setLongitude(TEST_LONGITUDE);
553         l.setSpeed(TEST_SPEED);
554         l.setTime(TEST_TIME);
555         Bundle bundle = new Bundle();
556         bundle.putBoolean(TEST_KEY1NAME, TEST_KEY1VALUE);
557         bundle.putByte(TEST_KEY2NAME, TEST_KEY2VALUE);
558         l.setExtras(bundle);
559 
560         return l;
561     }
562 
assertTestBundle(Bundle bundle)563     private void assertTestBundle(Bundle bundle) {
564         assertFalse(bundle.getBoolean(TEST_KEY1NAME));
565         assertEquals(TEST_KEY2VALUE, bundle.getByte(TEST_KEY2NAME));
566     }
567 
568     private class SettingInjectorResultHandler extends Handler {
569         private boolean mEnabledShouldBe;
570         private boolean mExpectingMessage;
571         private boolean mMessageArrived;
572 
SettingInjectorResultHandler(Looper l)573         SettingInjectorResultHandler(Looper l) {
574             super(l);
575         }
576 
577         @Override
handleMessage(Message m)578         public void handleMessage(Message m) {
579 
580             assertTrue("Unexpected message.", mExpectingMessage);
581 
582             boolean enabled = m.getData().getBoolean(ENABLED_KEY);
583 
584             assertEquals(String.format(
585                     "Message value (%s) inconsistent with service state (%s).",
586                     String.valueOf(enabled), String.valueOf(mEnabledShouldBe) ),
587                     mEnabledShouldBe, enabled);
588 
589             synchronized (this) {
590                 mMessageArrived = true;
591                 notify();
592             }
593         }
594 
expectEnabled(boolean enabled)595         public void expectEnabled(boolean enabled) {
596             mEnabledShouldBe = enabled;
597         }
598 
expectMessage(boolean expecting)599         public void expectMessage(boolean expecting) {
600             mMessageArrived = false;
601             mExpectingMessage = expecting;
602         }
603 
waitForMessage(long millis)604         public synchronized boolean waitForMessage(long millis) {
605             synchronized (this) {
606                 try {
607                     wait(millis);
608                 } catch (InterruptedException e) {
609                     e.printStackTrace();
610                 }
611                 return mMessageArrived;
612             }
613         }
614     }
615 
616 
617     private class SettingInjectorServiceDerived extends SettingInjectorService {
618 
619         private boolean mEnabled;
620 
SettingInjectorServiceDerived()621         SettingInjectorServiceDerived() {
622             super("SettingInjectorServiceDerived");
623             setEnabled(false);
624         }
625 
626         @Override
627         // Deprecated API
onGetSummary()628         protected String onGetSummary() {
629             return "Summary";
630         }
631 
632         @Override
onGetEnabled()633         protected boolean onGetEnabled() {
634             return mEnabled;
635         }
636 
setEnabled(boolean enabled)637         public void setEnabled(boolean enabled) {
638             mEnabled = enabled;
639         }
640 
641         // API coverage dashboard will not count method call from derived class.
642         // Thus, it is necessary to make explicit call to SettingInjectorService public methods.
callOnBind(Intent intent)643         public IBinder callOnBind(Intent intent) {
644             return super.onBind(intent);
645         }
646 
callOnStart(Intent intent, int startId)647         public void callOnStart(Intent intent, int startId) {
648             super.onStart(intent, startId);
649         }
650 
callOnStartCommand(Intent intent, int flags, int startId)651         public int callOnStartCommand(Intent intent, int flags, int startId) {
652             return super.onStartCommand(intent, flags, startId);
653         }
654     }
655 
656 }
657