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>In statistical terms, it is assumed that location errors
770     * are random with a normal distribution, so the 68% confidence circle
771     * represents one standard deviation. Note that in practice, location
772     * errors do not always follow such a simple distribution.
773     *
774     * <p>This accuracy estimation is only concerned with horizontal
775     * accuracy, and does not indicate the accuracy of bearing,
776     * velocity or altitude if those are included in this Location.
777     *
778     * <p>If this location does not have a horizontal accuracy, then 0.0 is returned.
779     * All locations generated by the {@link LocationManager} include horizontal accuracy.
780     */
781    public float getAccuracy() {
782        return mHorizontalAccuracyMeters;
783    }
784
785    /**
786     * Set the estimated horizontal accuracy of this location, meters.
787     *
788     * <p>See {@link #getAccuracy} for the definition of horizontal accuracy.
789     *
790     * <p>Following this call {@link #hasAccuracy} will return true.
791     */
792    public void setAccuracy(float horizontalAccuracy) {
793        mHorizontalAccuracyMeters = horizontalAccuracy;
794        mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
795    }
796
797    /**
798     * Remove the horizontal accuracy from this location.
799     *
800     * <p>Following this call {@link #hasAccuracy} will return false, and
801     * {@link #getAccuracy} will return 0.0.
802     *
803     * @deprecated use a new Location object for location updates.
804     */
805    @Deprecated
806    public void removeAccuracy() {
807        mHorizontalAccuracyMeters = 0.0f;
808        mFieldsMask &= ~HAS_HORIZONTAL_ACCURACY_MASK;
809    }
810
811    /**
812     * True if this location has a vertical accuracy.
813     */
814    public boolean hasVerticalAccuracy() {
815        return (mFieldsMask & HAS_VERTICAL_ACCURACY_MASK) != 0;
816    }
817
818    /**
819     * Get the estimated vertical accuracy of this location, in meters.
820     *
821     * <p>We define vertical accuracy as the radius of 68% confidence. In other
822     * words, if you draw a circle centered at this location's altitude, and with a radius
823     * equal to the vertical accuracy, then there is a 68% probability that the true altitude is
824     * inside the circle.
825     *
826     * <p>In statistical terms, it is assumed that location errors
827     * are random with a normal distribution, so the 68% confidence circle
828     * represents one standard deviation. Note that in practice, location
829     * errors do not always follow such a simple distribution.
830     *
831     * <p>If this location does not have a vertical accuracy, then 0.0 is returned.
832     */
833    public float getVerticalAccuracyMeters() {
834        return mVerticalAccuracyMeters;
835    }
836
837    /**
838     * Set the estimated vertical accuracy of this location, meters.
839     *
840     * <p>See {@link #getVerticalAccuracyMeters} for the definition of vertical accuracy.
841     *
842     * <p>Following this call {@link #hasVerticalAccuracy} will return true.
843     */
844    public void setVerticalAccuracyMeters(float verticalAccuracyMeters) {
845        mVerticalAccuracyMeters = verticalAccuracyMeters;
846        mFieldsMask |= HAS_VERTICAL_ACCURACY_MASK;
847    }
848
849    /**
850     * Remove the vertical accuracy from this location.
851     *
852     * <p>Following this call {@link #hasVerticalAccuracy} will return false, and
853     * {@link #getVerticalAccuracyMeters} will return 0.0.
854     *
855     * @deprecated use a new Location object for location updates.
856     * @removed
857     */
858    @Deprecated
859    public void removeVerticalAccuracy() {
860        mVerticalAccuracyMeters = 0.0f;
861        mFieldsMask &= ~HAS_VERTICAL_ACCURACY_MASK;
862    }
863
864    /**
865     * True if this location has a speed accuracy.
866     */
867    public boolean hasSpeedAccuracy() {
868        return (mFieldsMask & HAS_SPEED_ACCURACY_MASK) != 0;
869    }
870
871    /**
872     * Get the estimated speed accuracy of this location, in meters per second.
873     *
874     * <p>We define speed accuracy as the radius of 68% confidence. In other
875     * words, if you draw a circle centered at this location's speed, and with a radius
876     * equal to the speed accuracy, then there is a 68% probability that the true speed is
877     * inside the circle.
878     *
879     * <p>If this location does not have a speed accuracy, then 0.0 is returned.
880     */
881    public float getSpeedAccuracyMetersPerSecond() {
882        return mSpeedAccuracyMetersPerSecond;
883    }
884
885    /**
886     * Set the estimated speed accuracy of this location, meters per second.
887     *
888     * <p>See {@link #getSpeedAccuracyMetersPerSecond} for the definition of speed accuracy.
889     *
890     * <p>Following this call {@link #hasSpeedAccuracy} will return true.
891     */
892    public void setSpeedAccuracyMetersPerSecond(float speedAccuracyMeterPerSecond) {
893        mSpeedAccuracyMetersPerSecond = speedAccuracyMeterPerSecond;
894        mFieldsMask |= HAS_SPEED_ACCURACY_MASK;
895    }
896
897    /**
898     * Remove the speed accuracy from this location.
899     *
900     * <p>Following this call {@link #hasSpeedAccuracy} will return false, and
901     * {@link #getSpeedAccuracyMetersPerSecond} will return 0.0.
902     *
903     * @deprecated use a new Location object for location updates.
904     * @removed
905     */
906    @Deprecated
907    public void removeSpeedAccuracy() {
908        mSpeedAccuracyMetersPerSecond = 0.0f;
909        mFieldsMask &= ~HAS_SPEED_ACCURACY_MASK;
910    }
911
912    /**
913     * True if this location has a bearing accuracy.
914     */
915    public boolean hasBearingAccuracy() {
916        return (mFieldsMask & HAS_BEARING_ACCURACY_MASK) != 0;
917    }
918
919    /**
920     * Get the estimated bearing accuracy of this location, in degrees.
921     *
922     * <p>We define bearing accuracy as the radius of 68% confidence. In other
923     * words, if you draw a circle centered at this location's bearing, and with a radius
924     * equal to the bearing accuracy, then there is a 68% probability that the true bearing is
925     * inside the circle.
926     *
927     * <p>If this location does not have a bearing accuracy, then 0.0 is returned.
928     */
929    public float getBearingAccuracyDegrees() {
930        return mBearingAccuracyDegrees;
931    }
932
933    /**
934     * Set the estimated bearing accuracy of this location, degrees.
935     *
936     * <p>See {@link #getBearingAccuracyDegrees} for the definition of bearing accuracy.
937     *
938     * <p>Following this call {@link #hasBearingAccuracy} will return true.
939     */
940    public void setBearingAccuracyDegrees(float bearingAccuracyDegrees) {
941        mBearingAccuracyDegrees = bearingAccuracyDegrees;
942        mFieldsMask |= HAS_BEARING_ACCURACY_MASK;
943    }
944
945    /**
946     * Remove the bearing accuracy from this location.
947     *
948     * <p>Following this call {@link #hasBearingAccuracy} will return false, and
949     * {@link #getBearingAccuracyDegrees} will return 0.0.
950     *
951     * @deprecated use a new Location object for location updates.
952     * @removed
953     */
954    @Deprecated
955    public void removeBearingAccuracy() {
956        mBearingAccuracyDegrees = 0.0f;
957        mFieldsMask &= ~HAS_BEARING_ACCURACY_MASK;
958    }
959
960    /**
961     * Return true if this Location object is complete.
962     *
963     * <p>A location object is currently considered complete if it has
964     * a valid provider, accuracy, wall-clock time and elapsed real-time.
965     *
966     * <p>All locations supplied by the {@link LocationManager} to
967     * applications must be complete.
968     *
969     * @see #makeComplete
970     * @hide
971     */
972    @SystemApi
973    public boolean isComplete() {
974        if (mProvider == null) return false;
975        if (!hasAccuracy()) return false;
976        if (mTime == 0) return false;
977        if (mElapsedRealtimeNanos == 0) return false;
978        return true;
979    }
980
981    /**
982     * Helper to fill incomplete fields.
983     *
984     * <p>Used to assist in backwards compatibility with
985     * Location objects received from applications.
986     *
987     * @see #isComplete
988     * @hide
989     */
990    @SystemApi
991    public void makeComplete() {
992        if (mProvider == null) mProvider = "?";
993        if (!hasAccuracy()) {
994            mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
995            mHorizontalAccuracyMeters = 100.0f;
996        }
997        if (mTime == 0) mTime = System.currentTimeMillis();
998        if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
999    }
1000
1001    /**
1002     * Returns additional provider-specific information about the
1003     * location fix as a Bundle.  The keys and values are determined
1004     * by the provider.  If no additional information is available,
1005     * null is returned.
1006     *
1007     * <p> A number of common key/value pairs are listed
1008     * below. Providers that use any of the keys on this list must
1009     * provide the corresponding value as described below.
1010     *
1011     * <ul>
1012     * <li> satellites - the number of satellites used to derive the fix
1013     * </ul>
1014     */
1015    public Bundle getExtras() {
1016        return mExtras;
1017    }
1018
1019    /**
1020     * Sets the extra information associated with this fix to the
1021     * given Bundle.
1022     */
1023    public void setExtras(Bundle extras) {
1024        mExtras = (extras == null) ? null : new Bundle(extras);
1025    }
1026
1027    @Override
1028    public String toString() {
1029        StringBuilder s = new StringBuilder();
1030        s.append("Location[");
1031        s.append(mProvider);
1032        s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude));
1033        if (hasAccuracy()) s.append(String.format(" hAcc=%.0f", mHorizontalAccuracyMeters));
1034        else s.append(" hAcc=???");
1035        if (mTime == 0) {
1036            s.append(" t=?!?");
1037        }
1038        if (mElapsedRealtimeNanos == 0) {
1039            s.append(" et=?!?");
1040        } else {
1041            s.append(" et=");
1042            TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s);
1043        }
1044        if (hasAltitude()) s.append(" alt=").append(mAltitude);
1045        if (hasSpeed()) s.append(" vel=").append(mSpeed);
1046        if (hasBearing()) s.append(" bear=").append(mBearing);
1047        if (hasVerticalAccuracy()) s.append(String.format(" vAcc=%.0f", mVerticalAccuracyMeters));
1048        else s.append(" vAcc=???");
1049        if (hasSpeedAccuracy()) s.append(String.format(" sAcc=%.0f", mSpeedAccuracyMetersPerSecond));
1050        else s.append(" sAcc=???");
1051        if (hasBearingAccuracy()) s.append(String.format(" bAcc=%.0f", mBearingAccuracyDegrees));
1052        else s.append(" bAcc=???");
1053        if (isFromMockProvider()) s.append(" mock");
1054
1055        if (mExtras != null) {
1056            s.append(" {").append(mExtras).append('}');
1057        }
1058        s.append(']');
1059        return s.toString();
1060    }
1061
1062    public void dump(Printer pw, String prefix) {
1063        pw.println(prefix + toString());
1064    }
1065
1066    public static final Parcelable.Creator<Location> CREATOR =
1067        new Parcelable.Creator<Location>() {
1068        @Override
1069        public Location createFromParcel(Parcel in) {
1070            String provider = in.readString();
1071            Location l = new Location(provider);
1072            l.mTime = in.readLong();
1073            l.mElapsedRealtimeNanos = in.readLong();
1074            l.mFieldsMask = in.readByte();
1075            l.mLatitude = in.readDouble();
1076            l.mLongitude = in.readDouble();
1077            l.mAltitude = in.readDouble();
1078            l.mSpeed = in.readFloat();
1079            l.mBearing = in.readFloat();
1080            l.mHorizontalAccuracyMeters = in.readFloat();
1081            l.mVerticalAccuracyMeters = in.readFloat();
1082            l.mSpeedAccuracyMetersPerSecond = in.readFloat();
1083            l.mBearingAccuracyDegrees = in.readFloat();
1084            l.mExtras = Bundle.setDefusable(in.readBundle(), true);
1085            return l;
1086        }
1087
1088        @Override
1089        public Location[] newArray(int size) {
1090            return new Location[size];
1091        }
1092    };
1093
1094    @Override
1095    public int describeContents() {
1096        return 0;
1097    }
1098
1099    @Override
1100    public void writeToParcel(Parcel parcel, int flags) {
1101        parcel.writeString(mProvider);
1102        parcel.writeLong(mTime);
1103        parcel.writeLong(mElapsedRealtimeNanos);
1104        parcel.writeByte(mFieldsMask);
1105        parcel.writeDouble(mLatitude);
1106        parcel.writeDouble(mLongitude);
1107        parcel.writeDouble(mAltitude);
1108        parcel.writeFloat(mSpeed);
1109        parcel.writeFloat(mBearing);
1110        parcel.writeFloat(mHorizontalAccuracyMeters);
1111        parcel.writeFloat(mVerticalAccuracyMeters);
1112        parcel.writeFloat(mSpeedAccuracyMetersPerSecond);
1113        parcel.writeFloat(mBearingAccuracyDegrees);
1114        parcel.writeBundle(mExtras);
1115    }
1116
1117    /**
1118     * Returns one of the optional extra {@link Location}s that can be attached
1119     * to this Location.
1120     *
1121     * @param key the key associated with the desired extra Location
1122     * @return the extra Location, or null if unavailable
1123     * @hide
1124     */
1125    public Location getExtraLocation(String key) {
1126        if (mExtras != null) {
1127            Parcelable value = mExtras.getParcelable(key);
1128            if (value instanceof Location) {
1129                return (Location) value;
1130            }
1131        }
1132        return null;
1133    }
1134
1135    /**
1136     * Attaches an extra {@link Location} to this Location.
1137     *
1138     * @param key the key associated with the Location extra
1139     * @param value the Location to attach
1140     * @hide
1141     */
1142    public void setExtraLocation(String key, Location value) {
1143        if (mExtras == null) {
1144            mExtras = new Bundle();
1145        }
1146        mExtras.putParcelable(key, value);
1147    }
1148
1149    /**
1150     * Returns true if the Location came from a mock provider.
1151     *
1152     * @return true if this Location came from a mock provider, false otherwise
1153     */
1154    public boolean isFromMockProvider() {
1155        return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0;
1156    }
1157
1158    /**
1159     * Flag this Location as having come from a mock provider or not.
1160     *
1161     * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
1162     * @hide
1163     */
1164    @SystemApi
1165    public void setIsFromMockProvider(boolean isFromMockProvider) {
1166        if (isFromMockProvider) {
1167            mFieldsMask |= HAS_MOCK_PROVIDER_MASK;
1168        } else {
1169            mFieldsMask &= ~HAS_MOCK_PROVIDER_MASK;
1170        }
1171    }
1172
1173    /**
1174     * Caches data used to compute distance and bearing (so successive calls to {@link #distanceTo}
1175     * and {@link #bearingTo} don't duplicate work.
1176     */
1177    private static class BearingDistanceCache {
1178        private double mLat1 = 0.0;
1179        private double mLon1 = 0.0;
1180        private double mLat2 = 0.0;
1181        private double mLon2 = 0.0;
1182        private float mDistance = 0.0f;
1183        private float mInitialBearing = 0.0f;
1184        private float mFinalBearing = 0.0f;
1185    }
1186}
1187