• 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 static java.util.concurrent.TimeUnit.NANOSECONDS;
20 
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.SystemApi;
24 import android.compat.annotation.UnsupportedAppUsage;
25 import android.os.Build;
26 import android.os.Bundle;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.os.SystemClock;
30 import android.util.Printer;
31 import android.util.TimeUtils;
32 
33 import java.text.DecimalFormat;
34 import java.util.Locale;
35 import java.util.Objects;
36 import java.util.StringTokenizer;
37 
38 /**
39  * A data class representing a geographic location.
40  *
41  * <p>A location may consist of a latitude, longitude, timestamp, and other information such as
42  * bearing, altitude and velocity.
43  *
44  * <p>All locations generated through {@link LocationManager} are guaranteed to have a valid
45  * latitude, longitude, and timestamp (both UTC time and elapsed real-time since boot). All other
46  * parameters are optional.
47  */
48 public class Location implements Parcelable {
49 
50     /**
51      * Constant used to specify formatting of a latitude or longitude
52      * in the form "[+-]DDD.DDDDD where D indicates degrees.
53      */
54     public static final int FORMAT_DEGREES = 0;
55 
56     /**
57      * Constant used to specify formatting of a latitude or longitude
58      * in the form "[+-]DDD:MM.MMMMM" where D indicates degrees and
59      * M indicates minutes of arc (1 minute = 1/60th of a degree).
60      */
61     public static final int FORMAT_MINUTES = 1;
62 
63     /**
64      * Constant used to specify formatting of a latitude or longitude
65      * in the form "DDD:MM:SS.SSSSS" where D indicates degrees, M
66      * indicates minutes of arc, and S indicates seconds of arc (1
67      * minute = 1/60th of a degree, 1 second = 1/3600th of a degree).
68      */
69     public static final int FORMAT_SECONDS = 2;
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      * @deprecated As of Android R, this extra is longer in use, since it is not necessary to keep
78      * gps locations separate from other locations for coarsening. Providers that do not need to
79      * support platforms below Android R should not use this constant.
80      */
81     @SystemApi
82     @Deprecated
83     public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";
84 
85     private static final int HAS_ALTITUDE_MASK = 1 << 0;
86     private static final int HAS_SPEED_MASK = 1 << 1;
87     private static final int HAS_BEARING_MASK = 1 << 2;
88     private static final int HAS_HORIZONTAL_ACCURACY_MASK = 1 << 3;
89     private static final int HAS_MOCK_PROVIDER_MASK = 1 << 4;
90     private static final int HAS_VERTICAL_ACCURACY_MASK = 1 << 5;
91     private static final int HAS_SPEED_ACCURACY_MASK = 1 << 6;
92     private static final int HAS_BEARING_ACCURACY_MASK = 1 << 7;
93     private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK = 1 << 8;
94 
95     // Cached data to make bearing/distance computations more efficient for the case
96     // where distanceTo and bearingTo are called in sequence.  Assume this typically happens
97     // on the same thread for caching purposes.
98     private static final ThreadLocal<BearingDistanceCache> sBearingDistanceCache =
99             ThreadLocal.withInitial(BearingDistanceCache::new);
100 
101     private String mProvider;
102     private long mTime = 0;
103     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R,
104             publicAlternatives = "{@link #getElapsedRealtimeNanos()}")
105     private long mElapsedRealtimeNanos = 0;
106     // Estimate of the relative precision of the alignment of this SystemClock
107     // timestamp, with the reported measurements in nanoseconds (68% confidence).
108     private double mElapsedRealtimeUncertaintyNanos = 0.0f;
109     private double mLatitude = 0.0;
110     private double mLongitude = 0.0;
111     private double mAltitude = 0.0f;
112     private float mSpeed = 0.0f;
113     private float mBearing = 0.0f;
114     private float mHorizontalAccuracyMeters = 0.0f;
115     private float mVerticalAccuracyMeters = 0.0f;
116     private float mSpeedAccuracyMetersPerSecond = 0.0f;
117     private float mBearingAccuracyDegrees = 0.0f;
118 
119     private Bundle mExtras = null;
120 
121     // A bitmask of fields present in this object (see HAS_* constants defined above).
122     private int mFieldsMask = 0;
123 
124     /**
125      * Construct a new Location with a named provider.
126      *
127      * <p>By default time, latitude and longitude are 0, and the location
128      * has no bearing, altitude, speed, accuracy or extras.
129      *
130      * @param provider the source that provides the location. It can be of type
131      * {@link LocationManager#GPS_PROVIDER}, {@link LocationManager#NETWORK_PROVIDER},
132      * or {@link LocationManager#PASSIVE_PROVIDER}. You can also define your own
133      * provider string, in which case an empty string is a valid provider.
134      */
Location(String provider)135     public Location(String provider) {
136         mProvider = provider;
137     }
138 
139     /**
140      * Construct a new Location object that is copied from an existing one.
141      */
Location(Location l)142     public Location(Location l) {
143         set(l);
144     }
145 
146     /**
147      * Sets the contents of the location to the values from the given location.
148      */
set(Location l)149     public void set(Location l) {
150         mProvider = l.mProvider;
151         mTime = l.mTime;
152         mElapsedRealtimeNanos = l.mElapsedRealtimeNanos;
153         mElapsedRealtimeUncertaintyNanos = l.mElapsedRealtimeUncertaintyNanos;
154         mFieldsMask = l.mFieldsMask;
155         mLatitude = l.mLatitude;
156         mLongitude = l.mLongitude;
157         mAltitude = l.mAltitude;
158         mSpeed = l.mSpeed;
159         mBearing = l.mBearing;
160         mHorizontalAccuracyMeters = l.mHorizontalAccuracyMeters;
161         mVerticalAccuracyMeters = l.mVerticalAccuracyMeters;
162         mSpeedAccuracyMetersPerSecond = l.mSpeedAccuracyMetersPerSecond;
163         mBearingAccuracyDegrees = l.mBearingAccuracyDegrees;
164         mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
165     }
166 
167     /**
168      * Clears the contents of the location.
169      */
reset()170     public void reset() {
171         mProvider = null;
172         mTime = 0;
173         mElapsedRealtimeNanos = 0;
174         mElapsedRealtimeUncertaintyNanos = 0.0;
175         mFieldsMask = 0;
176         mLatitude = 0;
177         mLongitude = 0;
178         mAltitude = 0;
179         mSpeed = 0;
180         mBearing = 0;
181         mHorizontalAccuracyMeters = 0;
182         mVerticalAccuracyMeters = 0;
183         mSpeedAccuracyMetersPerSecond = 0;
184         mBearingAccuracyDegrees = 0;
185         mExtras = null;
186     }
187 
188     /**
189      * Converts a coordinate to a String representation. The outputType
190      * may be one of FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
191      * The coordinate must be a valid double between -180.0 and 180.0.
192      * This conversion is performed in a method that is dependent on the
193      * default locale, and so is not guaranteed to round-trip with
194      * {@link #convert(String)}.
195      *
196      * @throws IllegalArgumentException if coordinate is less than
197      * -180.0, greater than 180.0, or is not a number.
198      * @throws IllegalArgumentException if outputType is not one of
199      * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
200      */
convert(double coordinate, int outputType)201     public static String convert(double coordinate, int outputType) {
202         if (coordinate < -180.0 || coordinate > 180.0 || Double.isNaN(coordinate)) {
203             throw new IllegalArgumentException("coordinate=" + coordinate);
204         }
205         if ((outputType != FORMAT_DEGREES) &&
206             (outputType != FORMAT_MINUTES) &&
207             (outputType != FORMAT_SECONDS)) {
208             throw new IllegalArgumentException("outputType=" + outputType);
209         }
210 
211         StringBuilder sb = new StringBuilder();
212 
213         // Handle negative values
214         if (coordinate < 0) {
215             sb.append('-');
216             coordinate = -coordinate;
217         }
218 
219         DecimalFormat df = new DecimalFormat("###.#####");
220         if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
221             int degrees = (int) Math.floor(coordinate);
222             sb.append(degrees);
223             sb.append(':');
224             coordinate -= degrees;
225             coordinate *= 60.0;
226             if (outputType == FORMAT_SECONDS) {
227                 int minutes = (int) Math.floor(coordinate);
228                 sb.append(minutes);
229                 sb.append(':');
230                 coordinate -= minutes;
231                 coordinate *= 60.0;
232             }
233         }
234         sb.append(df.format(coordinate));
235         return sb.toString();
236     }
237 
238     /**
239      * Converts a String in one of the formats described by
240      * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a
241      * double. This conversion is performed in a locale agnostic
242      * method, and so is not guaranteed to round-trip with
243      * {@link #convert(double, int)}.
244      *
245      * @throws NullPointerException if coordinate is null
246      * @throws IllegalArgumentException if the coordinate is not
247      * in one of the valid formats.
248      */
convert(String coordinate)249     public static double convert(String coordinate) {
250         // IllegalArgumentException if bad syntax
251         if (coordinate == null) {
252             throw new NullPointerException("coordinate");
253         }
254 
255         boolean negative = false;
256         if (coordinate.charAt(0) == '-') {
257             coordinate = coordinate.substring(1);
258             negative = true;
259         }
260 
261         StringTokenizer st = new StringTokenizer(coordinate, ":");
262         int tokens = st.countTokens();
263         if (tokens < 1) {
264             throw new IllegalArgumentException("coordinate=" + coordinate);
265         }
266         try {
267             String degrees = st.nextToken();
268             double val;
269             if (tokens == 1) {
270                 val = Double.parseDouble(degrees);
271                 return negative ? -val : val;
272             }
273 
274             String minutes = st.nextToken();
275             int deg = Integer.parseInt(degrees);
276             double min;
277             double sec = 0.0;
278             boolean secPresent = false;
279 
280             if (st.hasMoreTokens()) {
281                 min = Integer.parseInt(minutes);
282                 String seconds = st.nextToken();
283                 sec = Double.parseDouble(seconds);
284                 secPresent = true;
285             } else {
286                 min = Double.parseDouble(minutes);
287             }
288 
289             boolean isNegative180 = negative && (deg == 180) &&
290                 (min == 0) && (sec == 0);
291 
292             // deg must be in [0, 179] except for the case of -180 degrees
293             if ((deg < 0.0) || (deg > 179 && !isNegative180)) {
294                 throw new IllegalArgumentException("coordinate=" + coordinate);
295             }
296 
297             // min must be in [0, 59] if seconds are present, otherwise [0.0, 60.0)
298             if (min < 0 || min >= 60 || (secPresent && (min > 59))) {
299                 throw new IllegalArgumentException("coordinate=" +
300                         coordinate);
301             }
302 
303             // sec must be in [0.0, 60.0)
304             if (sec < 0 || sec >= 60) {
305                 throw new IllegalArgumentException("coordinate=" +
306                         coordinate);
307             }
308 
309             val = deg*3600.0 + min*60.0 + sec;
310             val /= 3600.0;
311             return negative ? -val : val;
312         } catch (NumberFormatException nfe) {
313             throw new IllegalArgumentException("coordinate=" + coordinate);
314         }
315     }
316 
computeDistanceAndBearing(double lat1, double lon1, double lat2, double lon2, BearingDistanceCache results)317     private static void computeDistanceAndBearing(double lat1, double lon1,
318         double lat2, double lon2, BearingDistanceCache results) {
319         // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
320         // using the "Inverse Formula" (section 4)
321 
322         int MAXITERS = 20;
323         // Convert lat/long to radians
324         lat1 *= Math.PI / 180.0;
325         lat2 *= Math.PI / 180.0;
326         lon1 *= Math.PI / 180.0;
327         lon2 *= Math.PI / 180.0;
328 
329         double a = 6378137.0; // WGS84 major axis
330         double b = 6356752.3142; // WGS84 semi-major axis
331         double f = (a - b) / a;
332         double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);
333 
334         double L = lon2 - lon1;
335         double A = 0.0;
336         double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
337         double U2 = Math.atan((1.0 - f) * Math.tan(lat2));
338 
339         double cosU1 = Math.cos(U1);
340         double cosU2 = Math.cos(U2);
341         double sinU1 = Math.sin(U1);
342         double sinU2 = Math.sin(U2);
343         double cosU1cosU2 = cosU1 * cosU2;
344         double sinU1sinU2 = sinU1 * sinU2;
345 
346         double sigma = 0.0;
347         double deltaSigma = 0.0;
348         double cosSqAlpha;
349         double cos2SM;
350         double cosSigma;
351         double sinSigma;
352         double cosLambda = 0.0;
353         double sinLambda = 0.0;
354 
355         double lambda = L; // initial guess
356         for (int iter = 0; iter < MAXITERS; iter++) {
357             double lambdaOrig = lambda;
358             cosLambda = Math.cos(lambda);
359             sinLambda = Math.sin(lambda);
360             double t1 = cosU2 * sinLambda;
361             double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
362             double sinSqSigma = t1 * t1 + t2 * t2; // (14)
363             sinSigma = Math.sqrt(sinSqSigma);
364             cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
365             sigma = Math.atan2(sinSigma, cosSigma); // (16)
366             double sinAlpha = (sinSigma == 0) ? 0.0 :
367                 cosU1cosU2 * sinLambda / sinSigma; // (17)
368             cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
369             cos2SM = (cosSqAlpha == 0) ? 0.0 :
370                 cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)
371 
372             double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
373             A = 1 + (uSquared / 16384.0) * // (3)
374                 (4096.0 + uSquared *
375                  (-768 + uSquared * (320.0 - 175.0 * uSquared)));
376             double B = (uSquared / 1024.0) * // (4)
377                 (256.0 + uSquared *
378                  (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
379             double C = (f / 16.0) *
380                 cosSqAlpha *
381                 (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
382             double cos2SMSq = cos2SM * cos2SM;
383             deltaSigma = B * sinSigma * // (6)
384                 (cos2SM + (B / 4.0) *
385                  (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
386                   (B / 6.0) * cos2SM *
387                   (-3.0 + 4.0 * sinSigma * sinSigma) *
388                   (-3.0 + 4.0 * cos2SMSq)));
389 
390             lambda = L +
391                 (1.0 - C) * f * sinAlpha *
392                 (sigma + C * sinSigma *
393                  (cos2SM + C * cosSigma *
394                   (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)
395 
396             double delta = (lambda - lambdaOrig) / lambda;
397             if (Math.abs(delta) < 1.0e-12) {
398                 break;
399             }
400         }
401 
402         results.mDistance = (float) (b * A * (sigma - deltaSigma));
403         float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
404             cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
405         initialBearing *= 180.0 / Math.PI;
406         results.mInitialBearing = initialBearing;
407         float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
408                 -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
409         finalBearing *= 180.0 / Math.PI;
410         results.mFinalBearing = finalBearing;
411         results.mLat1 = lat1;
412         results.mLat2 = lat2;
413         results.mLon1 = lon1;
414         results.mLon2 = lon2;
415     }
416 
417     /**
418      * Computes the approximate distance in meters between two
419      * locations, and optionally the initial and final bearings of the
420      * shortest path between them.  Distance and bearing are defined using the
421      * WGS84 ellipsoid.
422      *
423      * <p> The computed distance is stored in results[0].  If results has length
424      * 2 or greater, the initial bearing is stored in results[1]. If results has
425      * length 3 or greater, the final bearing is stored in results[2].
426      *
427      * @param startLatitude the starting latitude
428      * @param startLongitude the starting longitude
429      * @param endLatitude the ending latitude
430      * @param endLongitude the ending longitude
431      * @param results an array of floats to hold the results
432      *
433      * @throws IllegalArgumentException if results is null or has length < 1
434      */
distanceBetween(double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)435     public static void distanceBetween(double startLatitude, double startLongitude,
436         double endLatitude, double endLongitude, float[] results) {
437         if (results == null || results.length < 1) {
438             throw new IllegalArgumentException("results is null or has length < 1");
439         }
440         BearingDistanceCache cache = sBearingDistanceCache.get();
441         computeDistanceAndBearing(startLatitude, startLongitude,
442                 endLatitude, endLongitude, cache);
443         results[0] = cache.mDistance;
444         if (results.length > 1) {
445             results[1] = cache.mInitialBearing;
446             if (results.length > 2) {
447                 results[2] = cache.mFinalBearing;
448             }
449         }
450     }
451 
452     /**
453      * Returns the approximate distance in meters between this
454      * location and the given location.  Distance is defined using
455      * the WGS84 ellipsoid.
456      *
457      * @param dest the destination location
458      * @return the approximate distance in meters
459      */
distanceTo(Location dest)460     public float distanceTo(Location dest) {
461         BearingDistanceCache cache = sBearingDistanceCache.get();
462         // See if we already have the result
463         if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
464             dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
465             computeDistanceAndBearing(mLatitude, mLongitude,
466                 dest.mLatitude, dest.mLongitude, cache);
467         }
468         return cache.mDistance;
469     }
470 
471     /**
472      * Returns the approximate initial bearing in degrees East of true
473      * North when traveling along the shortest path between this
474      * location and the given location.  The shortest path is defined
475      * using the WGS84 ellipsoid.  Locations that are (nearly)
476      * antipodal may produce meaningless results.
477      *
478      * @param dest the destination location
479      * @return the initial bearing in degrees
480      */
bearingTo(Location dest)481     public float bearingTo(Location dest) {
482         BearingDistanceCache cache = sBearingDistanceCache.get();
483         // See if we already have the result
484         if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
485                         dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
486             computeDistanceAndBearing(mLatitude, mLongitude,
487                 dest.mLatitude, dest.mLongitude, cache);
488         }
489         return cache.mInitialBearing;
490     }
491 
492     /**
493      * Returns the name of the provider that generated this fix.
494      *
495      * @return the provider, or null if it has not been set
496      */
getProvider()497     public String getProvider() {
498         return mProvider;
499     }
500 
501     /**
502      * Sets the name of the provider that generated this fix.
503      */
setProvider(String provider)504     public void setProvider(String provider) {
505         mProvider = provider;
506     }
507 
508     /**
509      * Return the UTC time of this location fix, in milliseconds since epoch (January 1, 1970).
510      *
511      * <p>There is no guarantee that different locations have times set from the same clock.
512      * Locations derived from the {@link LocationManager#GPS_PROVIDER} are guaranteed to have their
513      * time set from the clock in use by the satellite constellation that provided the fix.
514      * Locations derived from other providers may use any clock to set their time, though it is most
515      * common to use the device clock (which may be incorrect).
516      *
517      * <p>Note that the device clock UTC time is not monotonic; it can jump forwards or backwards
518      * unpredictably and may be changed at any time by the user, so this time should not be used to
519      * order or compare locations. Prefer {@link #getElapsedRealtimeNanos} for that purpose, as this
520      * clock is guaranteed to be monotonic.
521      *
522      * <p>On the other hand, this method may be useful for presenting a human readable time to the
523      * user, or as a heuristic for comparing location fixes across reboot or across devices.
524      *
525      * <p>All locations generated by the {@link LocationManager} are guaranteed to have a UTC time
526      * set, however remember that the device clock may have changed since the location was
527      * generated.
528      *
529      * @return UTC time of fix, in milliseconds since January 1, 1970.
530      */
getTime()531     public long getTime() {
532         return mTime;
533     }
534 
535     /**
536      * Set the UTC time of this fix, in milliseconds since epoch (January 1, 1970).
537      *
538      * @param time UTC time of this fix, in milliseconds since January 1, 1970
539      */
setTime(long time)540     public void setTime(long time) {
541         mTime = time;
542     }
543 
544     /**
545      * Return the time of this fix in nanoseconds of elapsed realtime since system boot.
546      *
547      * <p>This value can be compared with {@link android.os.SystemClock#elapsedRealtimeNanos}, to
548      * reliably order or compare locations. This is reliable because elapsed realtime is guaranteed
549      * to be monotonic and continues to increment even when the system is in deep sleep (unlike
550      * {@link #getTime}). However, since elapsed realtime is with reference to system boot, it does
551      * not make sense to use this value to order or compare locations across boot cycles.
552      *
553      * <p>All locations generated by the {@link LocationManager} are guaranteed to have a valid
554      * elapsed realtime set.
555      *
556      * @return elapsed realtime of fix, in nanoseconds since system boot.
557      */
getElapsedRealtimeNanos()558     public long getElapsedRealtimeNanos() {
559         return mElapsedRealtimeNanos;
560     }
561 
562     /**
563      * Return the time of this fix in milliseconds of elapsed realtime since system boot.
564      *
565      * @see #getElapsedRealtimeNanos()
566      *
567      * @hide
568      */
getElapsedRealtimeMillis()569     public long getElapsedRealtimeMillis() {
570         return NANOSECONDS.toMillis(getElapsedRealtimeNanos());
571     }
572 
573     /**
574      * Returns the age of this fix with respect to the current elapsed realtime.
575      *
576      * @see #getElapsedRealtimeNanos()
577      *
578      * @hide
579      */
getElapsedRealtimeAgeMillis()580     public long getElapsedRealtimeAgeMillis() {
581         return getElapsedRealtimeAgeMillis(SystemClock.elapsedRealtime());
582     }
583 
584     /**
585      * Returns the age of this fix with respect to the given elapsed realtime.
586      *
587      * @see #getElapsedRealtimeNanos()
588      *
589      * @hide
590      */
getElapsedRealtimeAgeMillis(long referenceRealtimeMs)591     public long getElapsedRealtimeAgeMillis(long referenceRealtimeMs) {
592         return referenceRealtimeMs - NANOSECONDS.toMillis(mElapsedRealtimeNanos);
593     }
594 
595     /**
596      * Set the time of this fix, in elapsed realtime since system boot.
597      *
598      * @param time elapsed realtime of fix, in nanoseconds since system boot.
599      */
setElapsedRealtimeNanos(long time)600     public void setElapsedRealtimeNanos(long time) {
601         mElapsedRealtimeNanos = time;
602     }
603 
604     /**
605      * Get estimate of the relative precision of the alignment of the
606      * ElapsedRealtimeNanos timestamp, with the reported measurements in
607      * nanoseconds (68% confidence).
608      *
609      * This means that we have 68% confidence that the true timestamp of the
610      * event is within ElapsedReatimeNanos +/- uncertainty.
611      *
612      * Example :
613      *   - getElapsedRealtimeNanos() returns 10000000
614      *   - getElapsedRealtimeUncertaintyNanos() returns 1000000 (equivalent to 1millisecond)
615      *   This means that the event most likely happened between 9000000 and 11000000.
616      *
617      * @return uncertainty of elapsed real-time of fix, in nanoseconds.
618      */
getElapsedRealtimeUncertaintyNanos()619     public double getElapsedRealtimeUncertaintyNanos() {
620         return mElapsedRealtimeUncertaintyNanos;
621     }
622 
623     /**
624      * Set estimate of the relative precision of the alignment of the
625      * ElapsedRealtimeNanos timestamp, with the reported measurements in
626      * nanoseconds (68% confidence).
627      *
628      * @param time uncertainty of the elapsed real-time of fix, in nanoseconds.
629      */
setElapsedRealtimeUncertaintyNanos(double time)630     public void setElapsedRealtimeUncertaintyNanos(double time) {
631         mElapsedRealtimeUncertaintyNanos = time;
632         mFieldsMask |= HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK;
633     }
634 
635     /**
636      * True if this location has a elapsed realtime accuracy.
637      */
hasElapsedRealtimeUncertaintyNanos()638     public boolean hasElapsedRealtimeUncertaintyNanos() {
639         return (mFieldsMask & HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK) != 0;
640     }
641 
642 
643     /**
644      * Get the latitude, in degrees.
645      *
646      * <p>All locations generated by the {@link LocationManager}
647      * will have a valid latitude.
648      */
getLatitude()649     public double getLatitude() {
650         return mLatitude;
651     }
652 
653     /**
654      * Set the latitude, in degrees.
655      */
setLatitude(double latitude)656     public void setLatitude(double latitude) {
657         mLatitude = latitude;
658     }
659 
660     /**
661      * Get the longitude, in degrees.
662      *
663      * <p>All locations generated by the {@link LocationManager}
664      * will have a valid longitude.
665      */
getLongitude()666     public double getLongitude() {
667         return mLongitude;
668     }
669 
670     /**
671      * Set the longitude, in degrees.
672      */
setLongitude(double longitude)673     public void setLongitude(double longitude) {
674         mLongitude = longitude;
675     }
676 
677     /**
678      * True if this location has an altitude.
679      */
hasAltitude()680     public boolean hasAltitude() {
681         return (mFieldsMask & HAS_ALTITUDE_MASK) != 0;
682     }
683 
684     /**
685      * Get the altitude if available, in meters above the WGS 84 reference
686      * ellipsoid.
687      *
688      * <p>If this location does not have an altitude then 0.0 is returned.
689      */
getAltitude()690     public double getAltitude() {
691         return mAltitude;
692     }
693 
694     /**
695      * Set the altitude, in meters above the WGS 84 reference ellipsoid.
696      *
697      * <p>Following this call {@link #hasAltitude} will return true.
698      */
setAltitude(double altitude)699     public void setAltitude(double altitude) {
700         mAltitude = altitude;
701         mFieldsMask |= HAS_ALTITUDE_MASK;
702     }
703 
704     /**
705      * Remove the altitude from this location.
706      *
707      * <p>Following this call {@link #hasAltitude} will return false,
708      * and {@link #getAltitude} will return 0.0.
709      *
710      * @deprecated use a new Location object for location updates.
711      */
712     @Deprecated
removeAltitude()713     public void removeAltitude() {
714         mAltitude = 0.0f;
715         mFieldsMask &= ~HAS_ALTITUDE_MASK;
716     }
717 
718     /**
719      * True if this location has a speed.
720      */
hasSpeed()721     public boolean hasSpeed() {
722         return (mFieldsMask & HAS_SPEED_MASK) != 0;
723     }
724 
725     /**
726      * Get the speed if it is available, in meters/second over ground.
727      *
728      * <p>If this location does not have a speed then 0.0 is returned.
729      */
getSpeed()730     public float getSpeed() {
731         return mSpeed;
732     }
733 
734     /**
735      * Set the speed, in meters/second over ground.
736      *
737      * <p>Following this call {@link #hasSpeed} will return true.
738      */
setSpeed(float speed)739     public void setSpeed(float speed) {
740         mSpeed = speed;
741         mFieldsMask |= HAS_SPEED_MASK;
742     }
743 
744     /**
745      * Remove the speed from this location.
746      *
747      * <p>Following this call {@link #hasSpeed} will return false,
748      * and {@link #getSpeed} will return 0.0.
749      *
750      * @deprecated use a new Location object for location updates.
751      */
752     @Deprecated
removeSpeed()753     public void removeSpeed() {
754         mSpeed = 0.0f;
755         mFieldsMask &= ~HAS_SPEED_MASK;
756     }
757 
758     /**
759      * True if this location has a bearing.
760      */
hasBearing()761     public boolean hasBearing() {
762         return (mFieldsMask & HAS_BEARING_MASK) != 0;
763     }
764 
765     /**
766      * Get the bearing, in degrees.
767      *
768      * <p>Bearing is the horizontal direction of travel of this device,
769      * and is not related to the device orientation. It is guaranteed to
770      * be in the range (0.0, 360.0] if the device has a bearing.
771      *
772      * <p>If this location does not have a bearing then 0.0 is returned.
773      */
getBearing()774     public float getBearing() {
775         return mBearing;
776     }
777 
778     /**
779      * Set the bearing, in degrees.
780      *
781      * <p>Bearing is the horizontal direction of travel of this device,
782      * and is not related to the device orientation.
783      *
784      * <p>The input will be wrapped into the range (0.0, 360.0].
785      */
setBearing(float bearing)786     public void setBearing(float bearing) {
787         while (bearing < 0.0f) {
788             bearing += 360.0f;
789         }
790         while (bearing >= 360.0f) {
791             bearing -= 360.0f;
792         }
793         mBearing = bearing;
794         mFieldsMask |= HAS_BEARING_MASK;
795     }
796 
797     /**
798      * Remove the bearing from this location.
799      *
800      * <p>Following this call {@link #hasBearing} will return false,
801      * and {@link #getBearing} will return 0.0.
802      *
803      * @deprecated use a new Location object for location updates.
804      */
805     @Deprecated
removeBearing()806     public void removeBearing() {
807         mBearing = 0.0f;
808         mFieldsMask &= ~HAS_BEARING_MASK;
809     }
810 
811     /**
812      * True if this location has a horizontal accuracy.
813      *
814      * <p>All locations generated by the {@link LocationManager} have an horizontal accuracy.
815      */
hasAccuracy()816     public boolean hasAccuracy() {
817         return (mFieldsMask & HAS_HORIZONTAL_ACCURACY_MASK) != 0;
818     }
819 
820     /**
821      * Get the estimated horizontal accuracy of this location, radial, in meters.
822      *
823      * <p>We define horizontal accuracy as the radius of 68% confidence. In other
824      * words, if you draw a circle centered at this location's
825      * latitude and longitude, and with a radius equal to the accuracy,
826      * then there is a 68% probability that the true location is inside
827      * the circle.
828      *
829      * <p>This accuracy estimation is only concerned with horizontal
830      * accuracy, and does not indicate the accuracy of bearing,
831      * velocity or altitude if those are included in this Location.
832      *
833      * <p>If this location does not have a horizontal accuracy, then 0.0 is returned.
834      * All locations generated by the {@link LocationManager} include horizontal accuracy.
835      */
getAccuracy()836     public float getAccuracy() {
837         return mHorizontalAccuracyMeters;
838     }
839 
840     /**
841      * Set the estimated horizontal accuracy of this location, meters.
842      *
843      * <p>See {@link #getAccuracy} for the definition of horizontal accuracy.
844      *
845      * <p>Following this call {@link #hasAccuracy} will return true.
846      */
setAccuracy(float horizontalAccuracy)847     public void setAccuracy(float horizontalAccuracy) {
848         mHorizontalAccuracyMeters = horizontalAccuracy;
849         mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
850     }
851 
852     /**
853      * Remove the horizontal accuracy from this location.
854      *
855      * <p>Following this call {@link #hasAccuracy} will return false, and
856      * {@link #getAccuracy} will return 0.0.
857      *
858      * @deprecated use a new Location object for location updates.
859      */
860     @Deprecated
removeAccuracy()861     public void removeAccuracy() {
862         mHorizontalAccuracyMeters = 0.0f;
863         mFieldsMask &= ~HAS_HORIZONTAL_ACCURACY_MASK;
864     }
865 
866     /**
867      * True if this location has a vertical accuracy.
868      */
hasVerticalAccuracy()869     public boolean hasVerticalAccuracy() {
870         return (mFieldsMask & HAS_VERTICAL_ACCURACY_MASK) != 0;
871     }
872 
873     /**
874      * Get the estimated vertical accuracy of this location, in meters.
875      *
876      * <p>We define vertical accuracy at 68% confidence. Specifically, as 1-side of the 2-sided
877      * range above and below the estimated altitude reported by {@link #getAltitude()}, within which
878      * there is a 68% probability of finding the true altitude.
879      *
880      * <p>In the case where the underlying distribution is assumed Gaussian normal, this would be
881      * considered 1 standard deviation.
882      *
883      * <p>For example, if {@link #getAltitude()} returns 150m, and this method returns 20m then
884      * there is a 68% probability of the true altitude being between 130m and 170m.
885      */
getVerticalAccuracyMeters()886     public float getVerticalAccuracyMeters() {
887         return mVerticalAccuracyMeters;
888     }
889 
890     /**
891      * Set the estimated vertical accuracy of this location, meters.
892      *
893      * <p>See {@link #getVerticalAccuracyMeters} for the definition of vertical accuracy.
894      *
895      * <p>Following this call {@link #hasVerticalAccuracy} will return true.
896      */
setVerticalAccuracyMeters(float verticalAccuracyMeters)897     public void setVerticalAccuracyMeters(float verticalAccuracyMeters) {
898         mVerticalAccuracyMeters = verticalAccuracyMeters;
899         mFieldsMask |= HAS_VERTICAL_ACCURACY_MASK;
900     }
901 
902     /**
903      * Remove the vertical accuracy from this location.
904      *
905      * <p>Following this call {@link #hasVerticalAccuracy} will return false, and
906      * {@link #getVerticalAccuracyMeters} will return 0.0.
907      *
908      * @deprecated use a new Location object for location updates.
909      * @removed
910      */
911     @Deprecated
removeVerticalAccuracy()912     public void removeVerticalAccuracy() {
913         mVerticalAccuracyMeters = 0.0f;
914         mFieldsMask &= ~HAS_VERTICAL_ACCURACY_MASK;
915     }
916 
917     /**
918      * True if this location has a speed accuracy.
919      */
hasSpeedAccuracy()920     public boolean hasSpeedAccuracy() {
921         return (mFieldsMask & HAS_SPEED_ACCURACY_MASK) != 0;
922     }
923 
924     /**
925      * Get the estimated speed accuracy of this location, in meters per second.
926      *
927      * <p>We define speed accuracy at 68% confidence. Specifically, as 1-side of the 2-sided range
928      * above and below the estimated speed reported by {@link #getSpeed()}, within which there is a
929      * 68% probability of finding the true speed.
930      *
931      * <p>In the case where the underlying distribution is assumed Gaussian normal, this would be
932      * considered 1 standard deviation.
933      *
934      * <p>For example, if {@link #getSpeed()} returns 5m/s, and this method returns 1m/s, then there
935      * is a 68% probability of the true speed being between 4m/s and 6m/s.
936      *
937      * <p>Note that the speed and speed accuracy may be more accurate than would be obtained simply
938      * from differencing sequential positions, such as when the Doppler measurements from GNSS
939      * satellites are taken into account.
940      */
getSpeedAccuracyMetersPerSecond()941     public float getSpeedAccuracyMetersPerSecond() {
942         return mSpeedAccuracyMetersPerSecond;
943     }
944 
945     /**
946      * Set the estimated speed accuracy of this location, meters per second.
947      *
948      * <p>See {@link #getSpeedAccuracyMetersPerSecond} for the definition of speed accuracy.
949      *
950      * <p>Following this call {@link #hasSpeedAccuracy} will return true.
951      */
setSpeedAccuracyMetersPerSecond(float speedAccuracyMeterPerSecond)952     public void setSpeedAccuracyMetersPerSecond(float speedAccuracyMeterPerSecond) {
953         mSpeedAccuracyMetersPerSecond = speedAccuracyMeterPerSecond;
954         mFieldsMask |= HAS_SPEED_ACCURACY_MASK;
955     }
956 
957     /**
958      * Remove the speed accuracy from this location.
959      *
960      * <p>Following this call {@link #hasSpeedAccuracy} will return false, and
961      * {@link #getSpeedAccuracyMetersPerSecond} will return 0.0.
962      *
963      * @deprecated use a new Location object for location updates.
964      * @removed
965      */
966     @Deprecated
removeSpeedAccuracy()967     public void removeSpeedAccuracy() {
968         mSpeedAccuracyMetersPerSecond = 0.0f;
969         mFieldsMask &= ~HAS_SPEED_ACCURACY_MASK;
970     }
971 
972     /**
973      * True if this location has a bearing accuracy.
974      */
hasBearingAccuracy()975     public boolean hasBearingAccuracy() {
976         return (mFieldsMask & HAS_BEARING_ACCURACY_MASK) != 0;
977     }
978 
979     /**
980      * Get the estimated bearing accuracy of this location, in degrees.
981      *
982      * <p>We define bearing accuracy at 68% confidence. Specifically, as 1-side of the 2-sided range
983      * on each side of the estimated bearing reported by {@link #getBearing()}, within which there
984      * is a 68% probability of finding the true bearing.
985      *
986      * <p>In the case where the underlying distribution is assumed Gaussian normal, this would be
987      * considered 1 standard deviation.
988      *
989      * <p>For example, if {@link #getBearing()} returns 60°, and this method returns 10°, then there
990      * is a 68% probability of the true bearing being between 50° and 70°.
991      */
getBearingAccuracyDegrees()992     public float getBearingAccuracyDegrees() {
993         return mBearingAccuracyDegrees;
994     }
995 
996     /**
997      * Set the estimated bearing accuracy of this location, degrees.
998      *
999      * <p>See {@link #getBearingAccuracyDegrees} for the definition of bearing accuracy.
1000      *
1001      * <p>Following this call {@link #hasBearingAccuracy} will return true.
1002      */
setBearingAccuracyDegrees(float bearingAccuracyDegrees)1003     public void setBearingAccuracyDegrees(float bearingAccuracyDegrees) {
1004         mBearingAccuracyDegrees = bearingAccuracyDegrees;
1005         mFieldsMask |= HAS_BEARING_ACCURACY_MASK;
1006     }
1007 
1008     /**
1009      * Remove the bearing accuracy from this location.
1010      *
1011      * <p>Following this call {@link #hasBearingAccuracy} will return false, and
1012      * {@link #getBearingAccuracyDegrees} will return 0.0.
1013      *
1014      * @deprecated use a new Location object for location updates.
1015      * @removed
1016      */
1017     @Deprecated
removeBearingAccuracy()1018     public void removeBearingAccuracy() {
1019         mBearingAccuracyDegrees = 0.0f;
1020         mFieldsMask &= ~HAS_BEARING_ACCURACY_MASK;
1021     }
1022 
1023     /**
1024      * Return true if this Location object is complete.
1025      *
1026      * <p>A location object is currently considered complete if it has
1027      * a valid provider, accuracy, wall-clock time and elapsed real-time.
1028      *
1029      * <p>All locations supplied by the {@link LocationManager} to
1030      * applications must be complete.
1031      *
1032      * @see #makeComplete
1033      * @hide
1034      */
1035     @SystemApi
isComplete()1036     public boolean isComplete() {
1037         return mProvider != null && hasAccuracy() && mTime != 0 && mElapsedRealtimeNanos != 0;
1038     }
1039 
1040     /**
1041      * Helper to fill incomplete fields.
1042      *
1043      * <p>Used to assist in backwards compatibility with
1044      * Location objects received from applications.
1045      *
1046      * @see #isComplete
1047      * @hide
1048      */
1049     @SystemApi
makeComplete()1050     public void makeComplete() {
1051         if (mProvider == null) mProvider = "?";
1052         if (!hasAccuracy()) {
1053             mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
1054             mHorizontalAccuracyMeters = 100.0f;
1055         }
1056         if (mTime == 0) mTime = System.currentTimeMillis();
1057         if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
1058     }
1059 
1060     /**
1061      * Returns additional provider-specific information about the location fix as a Bundle. The keys
1062      * and values are determined by the provider.  If no additional information is available, null
1063      * is returned.
1064      *
1065      * <p> A number of common key/value pairs are listed
1066      * below. Providers that use any of the keys on this list must
1067      * provide the corresponding value as described below.
1068      *
1069      * <ul>
1070      * <li> satellites - the number of satellites used to derive the fix
1071      * </ul>
1072      */
getExtras()1073     public Bundle getExtras() {
1074         return mExtras;
1075     }
1076 
1077     /**
1078      * Sets the extra information associated with this fix to the given Bundle.
1079      *
1080      * <p>Note this stores a copy of the given extras, so any changes to extras after calling this
1081      * method won't be reflected in the location bundle.
1082      */
setExtras(@ullable Bundle extras)1083     public void setExtras(@Nullable Bundle extras) {
1084         mExtras = (extras == null) ? null : new Bundle(extras);
1085     }
1086 
1087     /**
1088      * Location equality is provided primarily for test purposes. Comparing locations for equality
1089      * in production may indicate incorrect assumptions, and should be avoided whenever possible.
1090      *
1091      * <p>{@inheritDoc}
1092      */
1093     @Override
equals(Object o)1094     public boolean equals(Object o) {
1095         if (this == o) {
1096             return true;
1097         }
1098         if (o == null || getClass() != o.getClass()) {
1099             return false;
1100         }
1101 
1102         Location location = (Location) o;
1103         return mTime == location.mTime
1104                 && mElapsedRealtimeNanos == location.mElapsedRealtimeNanos
1105                 && hasElapsedRealtimeUncertaintyNanos()
1106                 == location.hasElapsedRealtimeUncertaintyNanos()
1107                 && (!hasElapsedRealtimeUncertaintyNanos() || Double.compare(
1108                 location.mElapsedRealtimeUncertaintyNanos, mElapsedRealtimeUncertaintyNanos) == 0)
1109                 && Double.compare(location.mLatitude, mLatitude) == 0
1110                 && Double.compare(location.mLongitude, mLongitude) == 0
1111                 && hasAltitude() == location.hasAltitude()
1112                 && (!hasAltitude() || Double.compare(location.mAltitude, mAltitude) == 0)
1113                 && hasSpeed() == location.hasSpeed()
1114                 && (!hasSpeed() || Float.compare(location.mSpeed, mSpeed) == 0)
1115                 && hasBearing() == location.hasBearing()
1116                 && (!hasBearing() || Float.compare(location.mBearing, mBearing) == 0)
1117                 && hasAccuracy() == location.hasAccuracy()
1118                 && (!hasAccuracy() || Float.compare(location.mHorizontalAccuracyMeters,
1119                 mHorizontalAccuracyMeters) == 0)
1120                 && hasVerticalAccuracy() == location.hasVerticalAccuracy()
1121                 && (!hasVerticalAccuracy() || Float.compare(location.mVerticalAccuracyMeters,
1122                 mVerticalAccuracyMeters) == 0)
1123                 && hasSpeedAccuracy() == location.hasSpeedAccuracy()
1124                 && (!hasSpeedAccuracy() || Float.compare(location.mSpeedAccuracyMetersPerSecond,
1125                 mSpeedAccuracyMetersPerSecond) == 0)
1126                 && hasBearingAccuracy() == location.hasBearingAccuracy()
1127                 && (!hasBearingAccuracy() || Float.compare(location.mBearingAccuracyDegrees,
1128                 mBearingAccuracyDegrees) == 0)
1129                 && Objects.equals(mProvider, location.mProvider)
1130                 && areExtrasEqual(mExtras, location.mExtras);
1131     }
1132 
areExtrasEqual(@ullable Bundle extras1, @Nullable Bundle extras2)1133     private static boolean areExtrasEqual(@Nullable Bundle extras1, @Nullable Bundle extras2) {
1134         if ((extras1 == null || extras1.isEmpty()) && (extras2 == null || extras2.isEmpty())) {
1135             return true;
1136         } else if (extras1 == null || extras2 == null) {
1137             return false;
1138         } else {
1139             return extras1.kindofEquals(extras2);
1140         }
1141     }
1142 
1143     @Override
hashCode()1144     public int hashCode() {
1145         return Objects.hash(mProvider, mElapsedRealtimeNanos, mLatitude, mLongitude);
1146     }
1147 
1148     @Override
toString()1149     public String toString() {
1150         StringBuilder s = new StringBuilder();
1151         s.append("Location[");
1152         s.append(mProvider);
1153         s.append(" ").append(String.format(Locale.ROOT, "%.6f,%.6f", mLatitude, mLongitude));
1154         if (hasAccuracy()) {
1155             s.append(" hAcc=").append(mHorizontalAccuracyMeters);
1156         }
1157         s.append(" et=");
1158         TimeUtils.formatDuration(getElapsedRealtimeMillis(), s);
1159         if (hasAltitude()) {
1160             s.append(" alt=").append(mAltitude);
1161             if (hasVerticalAccuracy()) {
1162                 s.append(" vAcc=").append(mVerticalAccuracyMeters);
1163             }
1164         }
1165         if (hasSpeed()) {
1166             s.append(" vel=").append(mSpeed);
1167             if (hasSpeedAccuracy()) {
1168                 s.append(" sAcc=").append(mSpeedAccuracyMetersPerSecond);
1169             }
1170         }
1171         if (hasBearing()) {
1172             s.append(" bear=").append(mBearing);
1173             if (hasBearingAccuracy()) {
1174                 s.append(" bAcc=").append(mBearingAccuracyDegrees);
1175             }
1176         }
1177         if (isMock()) {
1178             s.append(" mock");
1179         }
1180 
1181         if (mExtras != null) {
1182             s.append(" {").append(mExtras).append('}');
1183         }
1184         s.append(']');
1185         return s.toString();
1186     }
1187 
dump(Printer pw, String prefix)1188     public void dump(Printer pw, String prefix) {
1189         pw.println(prefix + toString());
1190     }
1191 
1192     public static final @NonNull Parcelable.Creator<Location> CREATOR =
1193         new Parcelable.Creator<Location>() {
1194         @Override
1195         public Location createFromParcel(Parcel in) {
1196             Location l = new Location(in.readString());
1197             l.mFieldsMask = in.readInt();
1198             l.mTime = in.readLong();
1199             l.mElapsedRealtimeNanos = in.readLong();
1200             if (l.hasElapsedRealtimeUncertaintyNanos()) {
1201                 l.mElapsedRealtimeUncertaintyNanos = in.readDouble();
1202             }
1203             l.mLatitude = in.readDouble();
1204             l.mLongitude = in.readDouble();
1205             if (l.hasAltitude()) {
1206                 l.mAltitude = in.readDouble();
1207             }
1208             if (l.hasSpeed()) {
1209                 l.mSpeed = in.readFloat();
1210             }
1211             if (l.hasBearing()) {
1212                 l.mBearing = in.readFloat();
1213             }
1214             if (l.hasAccuracy()) {
1215                 l.mHorizontalAccuracyMeters = in.readFloat();
1216             }
1217             if (l.hasVerticalAccuracy()) {
1218                 l.mVerticalAccuracyMeters = in.readFloat();
1219             }
1220             if (l.hasSpeedAccuracy()) {
1221                 l.mSpeedAccuracyMetersPerSecond = in.readFloat();
1222             }
1223             if (l.hasBearingAccuracy()) {
1224                 l.mBearingAccuracyDegrees = in.readFloat();
1225             }
1226             l.mExtras = Bundle.setDefusable(in.readBundle(), true);
1227             return l;
1228         }
1229 
1230         @Override
1231         public Location[] newArray(int size) {
1232             return new Location[size];
1233         }
1234     };
1235 
1236     @Override
describeContents()1237     public int describeContents() {
1238         return 0;
1239     }
1240 
1241     @Override
writeToParcel(Parcel parcel, int flags)1242     public void writeToParcel(Parcel parcel, int flags) {
1243         parcel.writeString(mProvider);
1244         parcel.writeInt(mFieldsMask);
1245         parcel.writeLong(mTime);
1246         parcel.writeLong(mElapsedRealtimeNanos);
1247         if (hasElapsedRealtimeUncertaintyNanos()) {
1248             parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
1249         }
1250         parcel.writeDouble(mLatitude);
1251         parcel.writeDouble(mLongitude);
1252         if (hasAltitude()) {
1253             parcel.writeDouble(mAltitude);
1254         }
1255         if (hasSpeed()) {
1256             parcel.writeFloat(mSpeed);
1257         }
1258         if (hasBearing()) {
1259             parcel.writeFloat(mBearing);
1260         }
1261         if (hasAccuracy()) {
1262             parcel.writeFloat(mHorizontalAccuracyMeters);
1263         }
1264         if (hasVerticalAccuracy()) {
1265             parcel.writeFloat(mVerticalAccuracyMeters);
1266         }
1267         if (hasSpeedAccuracy()) {
1268             parcel.writeFloat(mSpeedAccuracyMetersPerSecond);
1269         }
1270         if (hasBearingAccuracy()) {
1271             parcel.writeFloat(mBearingAccuracyDegrees);
1272         }
1273         parcel.writeBundle(mExtras);
1274     }
1275 
1276     /**
1277      * Returns true if the Location came from a mock provider.
1278      *
1279      * @return true if this Location came from a mock provider, false otherwise
1280      * @deprecated Prefer {@link #isMock()} instead.
1281      */
1282     @Deprecated
isFromMockProvider()1283     public boolean isFromMockProvider() {
1284         return isMock();
1285     }
1286 
1287     /**
1288      * Flag this Location as having come from a mock provider or not.
1289      *
1290      * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
1291      * @deprecated Prefer {@link #setMock(boolean)} instead.
1292      * @hide
1293      */
1294     @Deprecated
1295     @SystemApi
setIsFromMockProvider(boolean isFromMockProvider)1296     public void setIsFromMockProvider(boolean isFromMockProvider) {
1297         setMock(isFromMockProvider);
1298     }
1299 
1300     /**
1301      * Returns true if this location is marked as a mock location. If this location comes from the
1302      * Android framework, this indicates that the location was provided by a test location provider,
1303      * and thus may not be related to the actual location of the device.
1304      *
1305      * @see LocationManager#addTestProvider
1306      */
isMock()1307     public boolean isMock() {
1308         return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0;
1309     }
1310 
1311     /**
1312      * Sets whether this location is marked as a mock location.
1313      */
setMock(boolean mock)1314     public void setMock(boolean mock) {
1315         if (mock) {
1316             mFieldsMask |= HAS_MOCK_PROVIDER_MASK;
1317         } else {
1318             mFieldsMask &= ~HAS_MOCK_PROVIDER_MASK;
1319         }
1320     }
1321 
1322     /**
1323      * Caches data used to compute distance and bearing (so successive calls to {@link #distanceTo}
1324      * and {@link #bearingTo} don't duplicate work.
1325      */
1326     private static class BearingDistanceCache {
1327         double mLat1 = 0.0;
1328         double mLon1 = 0.0;
1329         double mLat2 = 0.0;
1330         double mLon2 = 0.0;
1331         float mDistance = 0.0f;
1332         float mInitialBearing = 0.0f;
1333         float mFinalBearing = 0.0f;
1334     }
1335 }
1336