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