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 
testAccessElapsedRealtime()380     public void testAccessElapsedRealtime() {
381         Location location = new Location("");
382 
383         location.setElapsedRealtimeNanos(0);
384         assertEquals(0, location.getElapsedRealtimeNanos());
385 
386         location.setElapsedRealtimeNanos(Long.MAX_VALUE);
387         assertEquals(Long.MAX_VALUE, location.getElapsedRealtimeNanos());
388 
389         location.setElapsedRealtimeNanos(12000);
390         assertEquals(12000, location.getElapsedRealtimeNanos());
391     }
392 
testSet()393     public void testSet() {
394         Location location = new Location("");
395 
396         Location loc = createTestLocation();
397 
398         location.set(loc);
399         assertTestLocation(location);
400 
401         location.reset();
402         assertNull(location.getProvider());
403         assertEquals(0, location.getTime());
404         assertEquals(0, location.getLatitude(), DELTA);
405         assertEquals(0, location.getLongitude(), DELTA);
406         assertEquals(0, location.getAltitude(), DELTA);
407         assertFalse(location.hasAltitude());
408         assertEquals(0, location.getSpeed(), DELTA);
409         assertFalse(location.hasSpeed());
410         assertEquals(0, location.getBearing(), DELTA);
411         assertFalse(location.hasBearing());
412         assertEquals(0, location.getAccuracy(), DELTA);
413         assertFalse(location.hasAccuracy());
414         assertNull(location.getExtras());
415     }
416 
testToString()417     public void testToString() {
418         Location location = createTestLocation();
419 
420         assertNotNull(location.toString());
421     }
422 
testWriteToParcel()423     public void testWriteToParcel() {
424         Location location = createTestLocation();
425 
426         Parcel parcel = Parcel.obtain();
427         location.writeToParcel(parcel, 0);
428         parcel.setDataPosition(0);
429         Location newLocation = Location.CREATOR.createFromParcel(parcel);
430         assertTestLocation(newLocation);
431     }
432 
testSettingInjectorService()433     public void testSettingInjectorService() {
434         Context c = getContext();
435         SettingInjectorServiceDerived service = new SettingInjectorServiceDerived();
436 
437         assertNotNull(c);
438 
439         Intent intent =
440             new Intent(c, android.location.SettingInjectorService.class);
441 
442         assertNotNull(c.getMainLooper());
443         SettingInjectorResultHandler resultHandler =
444             new SettingInjectorResultHandler(c.getMainLooper());
445 
446         Messenger m = new Messenger(resultHandler);
447         intent.putExtra(MESSENGER_KEY, m);
448 
449         int ret;
450         final long timeout = 500;
451 
452         // should refuse binding
453         IBinder binder = service.callOnBind(intent);
454         assertNull("onBind should always fail.", binder);
455 
456         // test if result consistent with the truth
457         // enabled == false case
458         service.setEnabled(false);
459         resultHandler.expectEnabled(false);
460         resultHandler.expectMessage(true);
461         ret = service.callOnStartCommand(intent, SettingInjectorService.START_NOT_STICKY, 0);
462         assertEquals("onStartCommand return value invalid in (enabled == false) case.",
463             ret, SettingInjectorService.START_NOT_STICKY);
464         assertTrue("Message time out in (enabled == false case).",
465             resultHandler.waitForMessage(timeout));
466 
467         // enabled == true case
468         service.setEnabled(true);
469         assertTrue(service.onGetEnabled());
470         assertEquals("Summary", service.onGetSummary());
471         resultHandler.expectEnabled(true);
472         resultHandler.expectMessage(true);
473         ret = service.callOnStartCommand(intent, SettingInjectorService.START_NOT_STICKY, 0);
474         assertEquals("onStartCommand return value invalid in (enabled == true) case.",
475             ret, SettingInjectorService.START_NOT_STICKY);
476         assertTrue("Message time out in (enabled == true) case.",
477             resultHandler.waitForMessage(timeout));
478 
479         // should not respond to the deprecated method
480         resultHandler.expectMessage(false);
481         service.callOnStart(intent, 0);
482         resultHandler.waitForMessage(timeout);
483     }
484 
assertTestLocation(Location l)485     private void assertTestLocation(Location l) {
486         assertNotNull(l);
487         assertEquals(TEST_PROVIDER, l.getProvider());
488         assertEquals(TEST_ACCURACY, l.getAccuracy(), DELTA);
489         assertEquals(TEST_ALTITUDE, l.getAltitude(), DELTA);
490         assertEquals(TEST_LATITUDE, l.getLatitude(), DELTA);
491         assertEquals(TEST_BEARING, l.getBearing(), DELTA);
492         assertEquals(TEST_LONGITUDE, l.getLongitude(), DELTA);
493         assertEquals(TEST_SPEED, l.getSpeed(), DELTA);
494         assertEquals(TEST_TIME, l.getTime());
495         assertTestBundle(l.getExtras());
496     }
497 
createTestLocation()498     private Location createTestLocation() {
499         Location l = new Location(TEST_PROVIDER);
500         l.setAccuracy(TEST_ACCURACY);
501         l.setAltitude(TEST_ALTITUDE);
502         l.setLatitude(TEST_LATITUDE);
503         l.setBearing(TEST_BEARING);
504         l.setLongitude(TEST_LONGITUDE);
505         l.setSpeed(TEST_SPEED);
506         l.setTime(TEST_TIME);
507         Bundle bundle = new Bundle();
508         bundle.putBoolean(TEST_KEY1NAME, TEST_KEY1VALUE);
509         bundle.putByte(TEST_KEY2NAME, TEST_KEY2VALUE);
510         l.setExtras(bundle);
511 
512         return l;
513     }
514 
assertTestBundle(Bundle bundle)515     private void assertTestBundle(Bundle bundle) {
516         assertFalse(bundle.getBoolean(TEST_KEY1NAME));
517         assertEquals(TEST_KEY2VALUE, bundle.getByte(TEST_KEY2NAME));
518     }
519 
520     private class SettingInjectorResultHandler extends Handler {
521         private boolean mEnabledShouldBe;
522         private boolean mExpectingMessage;
523         private boolean mMessageArrived;
524 
SettingInjectorResultHandler(Looper l)525         SettingInjectorResultHandler(Looper l) {
526             super(l);
527         }
528 
529         @Override
handleMessage(Message m)530         public void handleMessage(Message m) {
531 
532             assertTrue("Unexpected message.", mExpectingMessage);
533 
534             boolean enabled = m.getData().getBoolean(ENABLED_KEY);
535 
536             assertEquals(String.format(
537                     "Message value (%s) inconsistent with service state (%s).",
538                     String.valueOf(enabled), String.valueOf(mEnabledShouldBe) ),
539                     mEnabledShouldBe, enabled);
540 
541             synchronized (this) {
542                 mMessageArrived = true;
543                 notify();
544             }
545         }
546 
expectEnabled(boolean enabled)547         public void expectEnabled(boolean enabled) {
548             mEnabledShouldBe = enabled;
549         }
550 
expectMessage(boolean expecting)551         public void expectMessage(boolean expecting) {
552             mMessageArrived = false;
553             mExpectingMessage = expecting;
554         }
555 
waitForMessage(long millis)556         public synchronized boolean waitForMessage(long millis) {
557             synchronized (this) {
558                 try {
559                     wait(millis);
560                 } catch (InterruptedException e) {
561                     e.printStackTrace();
562                 }
563                 return mMessageArrived;
564             }
565         }
566     }
567 
568 
569     private class SettingInjectorServiceDerived extends SettingInjectorService {
570 
571         private boolean mEnabled;
572 
SettingInjectorServiceDerived()573         SettingInjectorServiceDerived() {
574             super("SettingInjectorServiceDerived");
575             setEnabled(false);
576         }
577 
578         @Override
579         // Deprecated API
onGetSummary()580         protected String onGetSummary() {
581             return "Summary";
582         }
583 
584         @Override
onGetEnabled()585         protected boolean onGetEnabled() {
586             return mEnabled;
587         }
588 
setEnabled(boolean enabled)589         public void setEnabled(boolean enabled) {
590             mEnabled = enabled;
591         }
592 
593         // API coverage dashboard will not count method call from derived class.
594         // Thus, it is necessary to make explicit call to SettingInjectorService public methods.
callOnBind(Intent intent)595         public IBinder callOnBind(Intent intent) {
596             return super.onBind(intent);
597         }
598 
callOnStart(Intent intent, int startId)599         public void callOnStart(Intent intent, int startId) {
600             super.onStart(intent, startId);
601         }
602 
callOnStartCommand(Intent intent, int flags, int startId)603         public int callOnStartCommand(Intent intent, int flags, int startId) {
604             return super.onStartCommand(intent, flags, startId);
605         }
606     }
607 
608 }
609