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