• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 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;
18 
19 import android.os.Bundle;
20 import android.os.Parcel;
21 import android.os.Parcelable;
22 import android.os.SystemClock;
23 import android.util.Printer;
24 import android.util.TimeUtils;
25 
26 import java.text.DecimalFormat;
27 import java.util.StringTokenizer;
28 
29 /**
30  * A data class representing a geographic location.
31  *
32  * <p>A location can consist of a latitude, longitude, timestamp,
33  * and other information such as bearing, altitude and velocity.
34  *
35  * <p>All locations generated by the {@link LocationManager} are
36  * guaranteed to have a valid latitude, longitude, and timestamp
37  * (both UTC time and elapsed real-time since boot), all other
38  * parameters are optional.
39  */
40 public class Location implements Parcelable {
41     /**
42      * Constant used to specify formatting of a latitude or longitude
43      * in the form "[+-]DDD.DDDDD where D indicates degrees.
44      */
45     public static final int FORMAT_DEGREES = 0;
46 
47     /**
48      * Constant used to specify formatting of a latitude or longitude
49      * in the form "[+-]DDD:MM.MMMMM" where D indicates degrees and
50      * M indicates minutes of arc (1 minute = 1/60th of a degree).
51      */
52     public static final int FORMAT_MINUTES = 1;
53 
54     /**
55      * Constant used to specify formatting of a latitude or longitude
56      * in the form "DDD:MM:SS.SSSSS" where D indicates degrees, M
57      * indicates minutes of arc, and S indicates seconds of arc (1
58      * minute = 1/60th of a degree, 1 second = 1/3600th of a degree).
59      */
60     public static final int FORMAT_SECONDS = 2;
61 
62     /**
63      * Bundle key for a version of the location that has been fed through
64      * LocationFudger. Allows location providers to flag locations as being
65      * safe for use with ACCESS_COARSE_LOCATION permission.
66      *
67      * @hide
68      */
69     public static final String EXTRA_COARSE_LOCATION = "coarseLocation";
70 
71     /**
72      * Bundle key for a version of the location containing no GPS data.
73      * Allows location providers to flag locations as being safe to
74      * feed to LocationFudger.
75      *
76      * @hide
77      */
78     public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
79 
80     private String mProvider;
81     private long mTime = 0;
82     private long mElapsedRealtimeNanos = 0;
83     private double mLatitude = 0.0;
84     private double mLongitude = 0.0;
85     private boolean mHasAltitude = false;
86     private double mAltitude = 0.0f;
87     private boolean mHasSpeed = false;
88     private float mSpeed = 0.0f;
89     private boolean mHasBearing = false;
90     private float mBearing = 0.0f;
91     private boolean mHasAccuracy = false;
92     private float mAccuracy = 0.0f;
93     private Bundle mExtras = null;
94     private boolean mIsFromMockProvider = false;
95 
96     // Cache the inputs and outputs of computeDistanceAndBearing
97     // so calls to distanceTo() and bearingTo() can share work
98     private double mLat1 = 0.0;
99     private double mLon1 = 0.0;
100     private double mLat2 = 0.0;
101     private double mLon2 = 0.0;
102     private float mDistance = 0.0f;
103     private float mInitialBearing = 0.0f;
104     // Scratchpad
105     private final float[] mResults = new float[2];
106 
107     /**
108      * Construct a new Location with a named provider.
109      *
110      * <p>By default time, latitude and longitude are 0, and the location
111      * has no bearing, altitude, speed, accuracy or extras.
112      *
113      * @param provider the name of the provider that generated this location
114      */
Location(String provider)115     public Location(String provider) {
116         mProvider = provider;
117     }
118 
119     /**
120      * Construct a new Location object that is copied from an existing one.
121      */
Location(Location l)122     public Location(Location l) {
123         set(l);
124     }
125 
126     /**
127      * Sets the contents of the location to the values from the given location.
128      */
set(Location l)129     public void set(Location l) {
130         mProvider = l.mProvider;
131         mTime = l.mTime;
132         mElapsedRealtimeNanos = l.mElapsedRealtimeNanos;
133         mLatitude = l.mLatitude;
134         mLongitude = l.mLongitude;
135         mHasAltitude = l.mHasAltitude;
136         mAltitude = l.mAltitude;
137         mHasSpeed = l.mHasSpeed;
138         mSpeed = l.mSpeed;
139         mHasBearing = l.mHasBearing;
140         mBearing = l.mBearing;
141         mHasAccuracy = l.mHasAccuracy;
142         mAccuracy = l.mAccuracy;
143         mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
144         mIsFromMockProvider = l.mIsFromMockProvider;
145     }
146 
147     /**
148      * Clears the contents of the location.
149      */
reset()150     public void reset() {
151         mProvider = null;
152         mTime = 0;
153         mElapsedRealtimeNanos = 0;
154         mLatitude = 0;
155         mLongitude = 0;
156         mHasAltitude = false;
157         mAltitude = 0;
158         mHasSpeed = false;
159         mSpeed = 0;
160         mHasBearing = false;
161         mBearing = 0;
162         mHasAccuracy = false;
163         mAccuracy = 0;
164         mExtras = null;
165         mIsFromMockProvider = false;
166     }
167 
168     /**
169      * Converts a coordinate to a String representation. The outputType
170      * may be one of FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
171      * The coordinate must be a valid double between -180.0 and 180.0.
172      *
173      * @throws IllegalArgumentException if coordinate is less than
174      * -180.0, greater than 180.0, or is not a number.
175      * @throws IllegalArgumentException if outputType is not one of
176      * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
177      */
convert(double coordinate, int outputType)178     public static String convert(double coordinate, int outputType) {
179         if (coordinate < -180.0 || coordinate > 180.0 ||
180             Double.isNaN(coordinate)) {
181             throw new IllegalArgumentException("coordinate=" + coordinate);
182         }
183         if ((outputType != FORMAT_DEGREES) &&
184             (outputType != FORMAT_MINUTES) &&
185             (outputType != FORMAT_SECONDS)) {
186             throw new IllegalArgumentException("outputType=" + outputType);
187         }
188 
189         StringBuilder sb = new StringBuilder();
190 
191         // Handle negative values
192         if (coordinate < 0) {
193             sb.append('-');
194             coordinate = -coordinate;
195         }
196 
197         DecimalFormat df = new DecimalFormat("###.#####");
198         if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
199             int degrees = (int) Math.floor(coordinate);
200             sb.append(degrees);
201             sb.append(':');
202             coordinate -= degrees;
203             coordinate *= 60.0;
204             if (outputType == FORMAT_SECONDS) {
205                 int minutes = (int) Math.floor(coordinate);
206                 sb.append(minutes);
207                 sb.append(':');
208                 coordinate -= minutes;
209                 coordinate *= 60.0;
210             }
211         }
212         sb.append(df.format(coordinate));
213         return sb.toString();
214     }
215 
216     /**
217      * Converts a String in one of the formats described by
218      * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a
219      * double.
220      *
221      * @throws NullPointerException if coordinate is null
222      * @throws IllegalArgumentException if the coordinate is not
223      * in one of the valid formats.
224      */
convert(String coordinate)225     public static double convert(String coordinate) {
226         // IllegalArgumentException if bad syntax
227         if (coordinate == null) {
228             throw new NullPointerException("coordinate");
229         }
230 
231         boolean negative = false;
232         if (coordinate.charAt(0) == '-') {
233             coordinate = coordinate.substring(1);
234             negative = true;
235         }
236 
237         StringTokenizer st = new StringTokenizer(coordinate, ":");
238         int tokens = st.countTokens();
239         if (tokens < 1) {
240             throw new IllegalArgumentException("coordinate=" + coordinate);
241         }
242         try {
243             String degrees = st.nextToken();
244             double val;
245             if (tokens == 1) {
246                 val = Double.parseDouble(degrees);
247                 return negative ? -val : val;
248             }
249 
250             String minutes = st.nextToken();
251             int deg = Integer.parseInt(degrees);
252             double min;
253             double sec = 0.0;
254 
255             if (st.hasMoreTokens()) {
256                 min = Integer.parseInt(minutes);
257                 String seconds = st.nextToken();
258                 sec = Double.parseDouble(seconds);
259             } else {
260                 min = Double.parseDouble(minutes);
261             }
262 
263             boolean isNegative180 = negative && (deg == 180) &&
264                 (min == 0) && (sec == 0);
265 
266             // deg must be in [0, 179] except for the case of -180 degrees
267             if ((deg < 0.0) || (deg > 179 && !isNegative180)) {
268                 throw new IllegalArgumentException("coordinate=" + coordinate);
269             }
270             if (min < 0 || min > 59) {
271                 throw new IllegalArgumentException("coordinate=" +
272                         coordinate);
273             }
274             if (sec < 0 || sec > 59) {
275                 throw new IllegalArgumentException("coordinate=" +
276                         coordinate);
277             }
278 
279             val = deg*3600.0 + min*60.0 + sec;
280             val /= 3600.0;
281             return negative ? -val : val;
282         } catch (NumberFormatException nfe) {
283             throw new IllegalArgumentException("coordinate=" + coordinate);
284         }
285     }
286 
computeDistanceAndBearing(double lat1, double lon1, double lat2, double lon2, float[] results)287     private static void computeDistanceAndBearing(double lat1, double lon1,
288         double lat2, double lon2, float[] results) {
289         // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
290         // using the "Inverse Formula" (section 4)
291 
292         int MAXITERS = 20;
293         // Convert lat/long to radians
294         lat1 *= Math.PI / 180.0;
295         lat2 *= Math.PI / 180.0;
296         lon1 *= Math.PI / 180.0;
297         lon2 *= Math.PI / 180.0;
298 
299         double a = 6378137.0; // WGS84 major axis
300         double b = 6356752.3142; // WGS84 semi-major axis
301         double f = (a - b) / a;
302         double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
303 
304         double L = lon2 - lon1;
305         double A = 0.0;
306         double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
307         double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
308 
309         double cosU1 = Math.cos(U1);
310         double cosU2 = Math.cos(U2);
311         double sinU1 = Math.sin(U1);
312         double sinU2 = Math.sin(U2);
313         double cosU1cosU2 = cosU1 * cosU2;
314         double sinU1sinU2 = sinU1 * sinU2;
315 
316         double sigma = 0.0;
317         double deltaSigma = 0.0;
318         double cosSqAlpha = 0.0;
319         double cos2SM = 0.0;
320         double cosSigma = 0.0;
321         double sinSigma = 0.0;
322         double cosLambda = 0.0;
323         double sinLambda = 0.0;
324 
325         double lambda = L; // initial guess
326         for (int iter = 0; iter < MAXITERS; iter++) {
327             double lambdaOrig = lambda;
328             cosLambda = Math.cos(lambda);
329             sinLambda = Math.sin(lambda);
330             double t1 = cosU2 * sinLambda;
331             double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
332             double sinSqSigma = t1 * t1 + t2 * t2; // (14)
333             sinSigma = Math.sqrt(sinSqSigma);
334             cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
335             sigma = Math.atan2(sinSigma, cosSigma); // (16)
336             double sinAlpha = (sinSigma == 0) ? 0.0 :
337                 cosU1cosU2 * sinLambda / sinSigma; // (17)
338             cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
339             cos2SM = (cosSqAlpha == 0) ? 0.0 :
340                 cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
341 
342             double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
343             A = 1 + (uSquared / 16384.0) * // (3)
344                 (4096.0 + uSquared *
345                  (-768 + uSquared * (320.0 - 175.0 * uSquared)));
346             double B = (uSquared / 1024.0) * // (4)
347                 (256.0 + uSquared *
348                  (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
349             double C = (f / 16.0) *
350                 cosSqAlpha *
351                 (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
352             double cos2SMSq = cos2SM * cos2SM;
353             deltaSigma = B * sinSigma * // (6)
354                 (cos2SM + (B / 4.0) *
355                  (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
356                   (B / 6.0) * cos2SM *
357                   (-3.0 + 4.0 * sinSigma * sinSigma) *
358                   (-3.0 + 4.0 * cos2SMSq)));
359 
360             lambda = L +
361                 (1.0 - C) * f * sinAlpha *
362                 (sigma + C * sinSigma *
363                  (cos2SM + C * cosSigma *
364                   (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
365 
366             double delta = (lambda - lambdaOrig) / lambda;
367             if (Math.abs(delta) < 1.0e-12) {
368                 break;
369             }
370         }
371 
372         float distance = (float) (b * A * (sigma - deltaSigma));
373         results[0] = distance;
374         if (results.length > 1) {
375             float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
376                 cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
377             initialBearing *= 180.0 / Math.PI;
378             results[1] = initialBearing;
379             if (results.length > 2) {
380                 float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
381                     -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
382                 finalBearing *= 180.0 / Math.PI;
383                 results[2] = finalBearing;
384             }
385         }
386     }
387 
388     /**
389      * Computes the approximate distance in meters between two
390      * locations, and optionally the initial and final bearings of the
391      * shortest path between them.  Distance and bearing are defined using the
392      * WGS84 ellipsoid.
393      *
394      * <p> The computed distance is stored in results[0].  If results has length
395      * 2 or greater, the initial bearing is stored in results[1]. If results has
396      * length 3 or greater, the final bearing is stored in results[2].
397      *
398      * @param startLatitude the starting latitude
399      * @param startLongitude the starting longitude
400      * @param endLatitude the ending latitude
401      * @param endLongitude the ending longitude
402      * @param results an array of floats to hold the results
403      *
404      * @throws IllegalArgumentException if results is null or has length < 1
405      */
distanceBetween(double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)406     public static void distanceBetween(double startLatitude, double startLongitude,
407         double endLatitude, double endLongitude, float[] results) {
408         if (results == null || results.length < 1) {
409             throw new IllegalArgumentException("results is null or has length < 1");
410         }
411         computeDistanceAndBearing(startLatitude, startLongitude,
412             endLatitude, endLongitude, results);
413     }
414 
415     /**
416      * Returns the approximate distance in meters between this
417      * location and the given location.  Distance is defined using
418      * the WGS84 ellipsoid.
419      *
420      * @param dest the destination location
421      * @return the approximate distance in meters
422      */
distanceTo(Location dest)423     public float distanceTo(Location dest) {
424         // See if we already have the result
425         synchronized (mResults) {
426             if (mLatitude != mLat1 || mLongitude != mLon1 ||
427                 dest.mLatitude != mLat2 || dest.mLongitude != mLon2) {
428                 computeDistanceAndBearing(mLatitude, mLongitude,
429                     dest.mLatitude, dest.mLongitude, mResults);
430                 mLat1 = mLatitude;
431                 mLon1 = mLongitude;
432                 mLat2 = dest.mLatitude;
433                 mLon2 = dest.mLongitude;
434                 mDistance = mResults[0];
435                 mInitialBearing = mResults[1];
436             }
437             return mDistance;
438         }
439     }
440 
441     /**
442      * Returns the approximate initial bearing in degrees East of true
443      * North when traveling along the shortest path between this
444      * location and the given location.  The shortest path is defined
445      * using the WGS84 ellipsoid.  Locations that are (nearly)
446      * antipodal may produce meaningless results.
447      *
448      * @param dest the destination location
449      * @return the initial bearing in degrees
450      */
bearingTo(Location dest)451     public float bearingTo(Location dest) {
452         synchronized (mResults) {
453             // See if we already have the result
454             if (mLatitude != mLat1 || mLongitude != mLon1 ||
455                             dest.mLatitude != mLat2 || dest.mLongitude != mLon2) {
456                 computeDistanceAndBearing(mLatitude, mLongitude,
457                     dest.mLatitude, dest.mLongitude, mResults);
458                 mLat1 = mLatitude;
459                 mLon1 = mLongitude;
460                 mLat2 = dest.mLatitude;
461                 mLon2 = dest.mLongitude;
462                 mDistance = mResults[0];
463                 mInitialBearing = mResults[1];
464             }
465             return mInitialBearing;
466         }
467     }
468 
469     /**
470      * Returns the name of the provider that generated this fix.
471      *
472      * @return the provider, or null if it has not been set
473      */
getProvider()474     public String getProvider() {
475         return mProvider;
476     }
477 
478     /**
479      * Sets the name of the provider that generated this fix.
480      */
setProvider(String provider)481     public void setProvider(String provider) {
482         mProvider = provider;
483     }
484 
485     /**
486      * Return the UTC time of this fix, in milliseconds since January 1, 1970.
487      *
488      * <p>Note that the UTC time on a device is not monotonic: it
489      * can jump forwards or backwards unpredictably. So always use
490      * {@link #getElapsedRealtimeNanos} when calculating time deltas.
491      *
492      * <p>On the other hand, {@link #getTime} is useful for presenting
493      * a human readable time to the user, or for carefully comparing
494      * location fixes across reboot or across devices.
495      *
496      * <p>All locations generated by the {@link LocationManager}
497      * are guaranteed to have a valid UTC time, however remember that
498      * the system time may have changed since the location was generated.
499      *
500      * @return time of fix, in milliseconds since January 1, 1970.
501      */
getTime()502     public long getTime() {
503         return mTime;
504     }
505 
506     /**
507      * Set the UTC time of this fix, in milliseconds since January 1,
508      * 1970.
509      *
510      * @param time UTC time of this fix, in milliseconds since January 1, 1970
511      */
setTime(long time)512     public void setTime(long time) {
513         mTime = time;
514     }
515 
516     /**
517      * Return the time of this fix, in elapsed real-time since system boot.
518      *
519      * <p>This value can be reliably compared to
520      * {@link android.os.SystemClock#elapsedRealtimeNanos},
521      * to calculate the age of a fix and to compare Location fixes. This
522      * is reliable because elapsed real-time is guaranteed monotonic for
523      * each system boot and continues to increment even when the system
524      * is in deep sleep (unlike {@link #getTime}.
525      *
526      * <p>All locations generated by the {@link LocationManager}
527      * are guaranteed to have a valid elapsed real-time.
528      *
529      * @return elapsed real-time of fix, in nanoseconds since system boot.
530      */
getElapsedRealtimeNanos()531     public long getElapsedRealtimeNanos() {
532         return mElapsedRealtimeNanos;
533     }
534 
535     /**
536      * Set the time of this fix, in elapsed real-time since system boot.
537      *
538      * @param time elapsed real-time of fix, in nanoseconds since system boot.
539      */
setElapsedRealtimeNanos(long time)540     public void setElapsedRealtimeNanos(long time) {
541         mElapsedRealtimeNanos = time;
542     }
543 
544     /**
545      * Get the latitude, in degrees.
546      *
547      * <p>All locations generated by the {@link LocationManager}
548      * will have a valid latitude.
549      */
getLatitude()550     public double getLatitude() {
551         return mLatitude;
552     }
553 
554     /**
555      * Set the latitude, in degrees.
556      */
setLatitude(double latitude)557     public void setLatitude(double latitude) {
558         mLatitude = latitude;
559     }
560 
561     /**
562      * Get the longitude, in degrees.
563      *
564      * <p>All locations generated by the {@link LocationManager}
565      * will have a valid longitude.
566      */
getLongitude()567     public double getLongitude() {
568         return mLongitude;
569     }
570 
571     /**
572      * Set the longitude, in degrees.
573      */
setLongitude(double longitude)574     public void setLongitude(double longitude) {
575         mLongitude = longitude;
576     }
577 
578     /**
579      * True if this location has an altitude.
580      */
hasAltitude()581     public boolean hasAltitude() {
582         return mHasAltitude;
583     }
584 
585     /**
586      * Get the altitude if available, in meters above sea level.
587      *
588      * <p>If this location does not have an altitude then 0.0 is returned.
589      */
getAltitude()590     public double getAltitude() {
591         return mAltitude;
592     }
593 
594     /**
595      * Set the altitude, in meters above sea level.
596      *
597      * <p>Following this call {@link #hasAltitude} will return true.
598      */
setAltitude(double altitude)599     public void setAltitude(double altitude) {
600         mAltitude = altitude;
601         mHasAltitude = true;
602     }
603 
604     /**
605      * Remove the altitude from this location.
606      *
607      * <p>Following this call {@link #hasAltitude} will return false,
608      * and {@link #getAltitude} will return 0.0.
609      */
removeAltitude()610     public void removeAltitude() {
611         mAltitude = 0.0f;
612         mHasAltitude = false;
613     }
614 
615     /**
616      * True if this location has a speed.
617      */
hasSpeed()618     public boolean hasSpeed() {
619         return mHasSpeed;
620     }
621 
622     /**
623      * Get the speed if it is available, in meters/second over ground.
624      *
625      * <p>If this location does not have a speed then 0.0 is returned.
626      */
getSpeed()627     public float getSpeed() {
628         return mSpeed;
629     }
630 
631     /**
632      * Set the speed, in meters/second over ground.
633      *
634      * <p>Following this call {@link #hasSpeed} will return true.
635      */
setSpeed(float speed)636     public void setSpeed(float speed) {
637         mSpeed = speed;
638         mHasSpeed = true;
639     }
640 
641     /**
642      * Remove the speed from this location.
643      *
644      * <p>Following this call {@link #hasSpeed} will return false,
645      * and {@link #getSpeed} will return 0.0.
646      */
removeSpeed()647     public void removeSpeed() {
648         mSpeed = 0.0f;
649         mHasSpeed = false;
650     }
651 
652     /**
653      * True if this location has a bearing.
654      */
hasBearing()655     public boolean hasBearing() {
656         return mHasBearing;
657     }
658 
659     /**
660      * Get the bearing, in degrees.
661      *
662      * <p>Bearing is the horizontal direction of travel of this device,
663      * and is not related to the device orientation. It is guaranteed to
664      * be in the range (0.0, 360.0] if the device has a bearing.
665      *
666      * <p>If this location does not have a bearing then 0.0 is returned.
667      */
getBearing()668     public float getBearing() {
669         return mBearing;
670     }
671 
672     /**
673      * Set the bearing, in degrees.
674      *
675      * <p>Bearing is the horizontal direction of travel of this device,
676      * and is not related to the device orientation.
677      *
678      * <p>The input will be wrapped into the range (0.0, 360.0].
679      */
setBearing(float bearing)680     public void setBearing(float bearing) {
681         while (bearing < 0.0f) {
682             bearing += 360.0f;
683         }
684         while (bearing >= 360.0f) {
685             bearing -= 360.0f;
686         }
687         mBearing = bearing;
688         mHasBearing = true;
689     }
690 
691     /**
692      * Remove the bearing from this location.
693      *
694      * <p>Following this call {@link #hasBearing} will return false,
695      * and {@link #getBearing} will return 0.0.
696      */
removeBearing()697     public void removeBearing() {
698         mBearing = 0.0f;
699         mHasBearing = false;
700     }
701 
702     /**
703      * True if this location has an accuracy.
704      *
705      * <p>All locations generated by the {@link LocationManager} have an
706      * accuracy.
707      */
hasAccuracy()708     public boolean hasAccuracy() {
709         return mHasAccuracy;
710     }
711 
712     /**
713      * Get the estimated accuracy of this location, in meters.
714      *
715      * <p>We define accuracy as the radius of 68% confidence. In other
716      * words, if you draw a circle centered at this location's
717      * latitude and longitude, and with a radius equal to the accuracy,
718      * then there is a 68% probability that the true location is inside
719      * the circle.
720      *
721      * <p>In statistical terms, it is assumed that location errors
722      * are random with a normal distribution, so the 68% confidence circle
723      * represents one standard deviation. Note that in practice, location
724      * errors do not always follow such a simple distribution.
725      *
726      * <p>This accuracy estimation is only concerned with horizontal
727      * accuracy, and does not indicate the accuracy of bearing,
728      * velocity or altitude if those are included in this Location.
729      *
730      * <p>If this location does not have an accuracy, then 0.0 is returned.
731      * All locations generated by the {@link LocationManager} include
732      * an accuracy.
733      */
getAccuracy()734     public float getAccuracy() {
735         return mAccuracy;
736     }
737 
738     /**
739      * Set the estimated accuracy of this location, meters.
740      *
741      * <p>See {@link #getAccuracy} for the definition of accuracy.
742      *
743      * <p>Following this call {@link #hasAccuracy} will return true.
744      */
setAccuracy(float accuracy)745     public void setAccuracy(float accuracy) {
746         mAccuracy = accuracy;
747         mHasAccuracy = true;
748     }
749 
750     /**
751      * Remove the accuracy from this location.
752      *
753      * <p>Following this call {@link #hasAccuracy} will return false, and
754      * {@link #getAccuracy} will return 0.0.
755      */
removeAccuracy()756     public void removeAccuracy() {
757         mAccuracy = 0.0f;
758         mHasAccuracy = false;
759     }
760 
761     /**
762      * Return true if this Location object is complete.
763      *
764      * <p>A location object is currently considered complete if it has
765      * a valid provider, accuracy, wall-clock time and elapsed real-time.
766      *
767      * <p>All locations supplied by the {@link LocationManager} to
768      * applications must be complete.
769      *
770      * @see #makeComplete
771      * @hide
772      */
isComplete()773     public boolean isComplete() {
774         if (mProvider == null) return false;
775         if (!mHasAccuracy) return false;
776         if (mTime == 0) return false;
777         if (mElapsedRealtimeNanos == 0) return false;
778         return true;
779     }
780 
781     /**
782      * Helper to fill incomplete fields.
783      *
784      * <p>Used to assist in backwards compatibility with
785      * Location objects received from applications.
786      *
787      * @see #isComplete
788      * @hide
789      */
makeComplete()790     public void makeComplete() {
791         if (mProvider == null) mProvider = "?";
792         if (!mHasAccuracy) {
793             mHasAccuracy = true;
794             mAccuracy = 100.0f;
795         }
796         if (mTime == 0) mTime = System.currentTimeMillis();
797         if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
798     }
799 
800     /**
801      * Returns additional provider-specific information about the
802      * location fix as a Bundle.  The keys and values are determined
803      * by the provider.  If no additional information is available,
804      * null is returned.
805      *
806      * <p> A number of common key/value pairs are listed
807      * below. Providers that use any of the keys on this list must
808      * provide the corresponding value as described below.
809      *
810      * <ul>
811      * <li> satellites - the number of satellites used to derive the fix
812      * </ul>
813      */
getExtras()814     public Bundle getExtras() {
815         return mExtras;
816     }
817 
818     /**
819      * Sets the extra information associated with this fix to the
820      * given Bundle.
821      */
setExtras(Bundle extras)822     public void setExtras(Bundle extras) {
823         mExtras = (extras == null) ? null : new Bundle(extras);
824     }
825 
826     @Override
toString()827     public String toString() {
828         StringBuilder s = new StringBuilder();
829         s.append("Location[");
830         s.append(mProvider);
831         s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude));
832         if (mHasAccuracy) s.append(String.format(" acc=%.0f", mAccuracy));
833         else s.append(" acc=???");
834         if (mTime == 0) {
835             s.append(" t=?!?");
836         }
837         if (mElapsedRealtimeNanos == 0) {
838             s.append(" et=?!?");
839         } else {
840             s.append(" et=");
841             TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s);
842         }
843         if (mHasAltitude) s.append(" alt=").append(mAltitude);
844         if (mHasSpeed) s.append(" vel=").append(mSpeed);
845         if (mHasBearing) s.append(" bear=").append(mBearing);
846         if (mIsFromMockProvider) s.append(" mock");
847 
848         if (mExtras != null) {
849             s.append(" {").append(mExtras).append('}');
850         }
851         s.append(']');
852         return s.toString();
853     }
854 
dump(Printer pw, String prefix)855     public void dump(Printer pw, String prefix) {
856         pw.println(prefix + toString());
857     }
858 
859     public static final Parcelable.Creator<Location> CREATOR =
860         new Parcelable.Creator<Location>() {
861         @Override
862         public Location createFromParcel(Parcel in) {
863             String provider = in.readString();
864             Location l = new Location(provider);
865             l.mTime = in.readLong();
866             l.mElapsedRealtimeNanos = in.readLong();
867             l.mLatitude = in.readDouble();
868             l.mLongitude = in.readDouble();
869             l.mHasAltitude = in.readInt() != 0;
870             l.mAltitude = in.readDouble();
871             l.mHasSpeed = in.readInt() != 0;
872             l.mSpeed = in.readFloat();
873             l.mHasBearing = in.readInt() != 0;
874             l.mBearing = in.readFloat();
875             l.mHasAccuracy = in.readInt() != 0;
876             l.mAccuracy = in.readFloat();
877             l.mExtras = in.readBundle();
878             l.mIsFromMockProvider = in.readInt() != 0;
879             return l;
880         }
881 
882         @Override
883         public Location[] newArray(int size) {
884             return new Location[size];
885         }
886     };
887 
888     @Override
describeContents()889     public int describeContents() {
890         return 0;
891     }
892 
893     @Override
writeToParcel(Parcel parcel, int flags)894     public void writeToParcel(Parcel parcel, int flags) {
895         parcel.writeString(mProvider);
896         parcel.writeLong(mTime);
897         parcel.writeLong(mElapsedRealtimeNanos);
898         parcel.writeDouble(mLatitude);
899         parcel.writeDouble(mLongitude);
900         parcel.writeInt(mHasAltitude ? 1 : 0);
901         parcel.writeDouble(mAltitude);
902         parcel.writeInt(mHasSpeed ? 1 : 0);
903         parcel.writeFloat(mSpeed);
904         parcel.writeInt(mHasBearing ? 1 : 0);
905         parcel.writeFloat(mBearing);
906         parcel.writeInt(mHasAccuracy ? 1 : 0);
907         parcel.writeFloat(mAccuracy);
908         parcel.writeBundle(mExtras);
909         parcel.writeInt(mIsFromMockProvider? 1 : 0);
910     }
911 
912     /**
913      * Returns one of the optional extra {@link Location}s that can be attached
914      * to this Location.
915      *
916      * @param key the key associated with the desired extra Location
917      * @return the extra Location, or null if unavailable
918      * @hide
919      */
getExtraLocation(String key)920     public Location getExtraLocation(String key) {
921         if (mExtras != null) {
922             Parcelable value = mExtras.getParcelable(key);
923             if (value instanceof Location) {
924                 return (Location) value;
925             }
926         }
927         return null;
928     }
929 
930     /**
931      * Attaches an extra {@link Location} to this Location.
932      *
933      * @param key the key associated with the Location extra
934      * @param location the Location to attach
935      * @hide
936      */
setExtraLocation(String key, Location value)937     public void setExtraLocation(String key, Location value) {
938         if (mExtras == null) {
939             mExtras = new Bundle();
940         }
941         mExtras.putParcelable(key, value);
942     }
943 
944     /**
945      * Returns true if the Location came from a mock provider.
946      *
947      * @return true if this Location came from a mock provider, false otherwise
948      */
isFromMockProvider()949     public boolean isFromMockProvider() {
950         return mIsFromMockProvider;
951     }
952 
953     /**
954      * Flag this Location as having come from a mock provider or not.
955      *
956      * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
957      * @hide
958      */
setIsFromMockProvider(boolean isFromMockProvider)959     public void setIsFromMockProvider(boolean isFromMockProvider) {
960         mIsFromMockProvider = isFromMockProvider;
961     }
962 }
963