/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.location;

import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.Printer;
import android.util.TimeUtils;

import java.text.DecimalFormat;
import java.util.StringTokenizer;

/**
 * A data class representing a geographic location.
 *
 * <p>A location can consist of a latitude, longitude, timestamp,
 * and other information such as bearing, altitude and velocity.
 *
 * <p>All locations generated by the {@link LocationManager} are
 * guaranteed to have a valid latitude, longitude, and timestamp
 * (both UTC time and elapsed real-time since boot), all other
 * parameters are optional.
 */
public class Location implements Parcelable {
    /**
     * Constant used to specify formatting of a latitude or longitude
     * in the form "[+-]DDD.DDDDD where D indicates degrees.
     */
    public static final int FORMAT_DEGREES = 0;

    /**
     * Constant used to specify formatting of a latitude or longitude
     * in the form "[+-]DDD:MM.MMMMM" where D indicates degrees and
     * M indicates minutes of arc (1 minute = 1/60th of a degree).
     */
    public static final int FORMAT_MINUTES = 1;

    /**
     * Constant used to specify formatting of a latitude or longitude
     * in the form "DDD:MM:SS.SSSSS" where D indicates degrees, M
     * indicates minutes of arc, and S indicates seconds of arc (1
     * minute = 1/60th of a degree, 1 second = 1/3600th of a degree).
     */
    public static final int FORMAT_SECONDS = 2;

    /**
     * Bundle key for a version of the location that has been fed through
     * LocationFudger. Allows location providers to flag locations as being
     * safe for use with ACCESS_COARSE_LOCATION permission.
     *
     * @hide
     */
    public static final String EXTRA_COARSE_LOCATION = "coarseLocation";

    /**
     * Bundle key for a version of the location containing no GPS data.
     * Allows location providers to flag locations as being safe to
     * feed to LocationFudger.
     *
     * @hide
     */
    public static final String EXTRA_NO_GPS_LOCATION = "noGPSLocation";

    /**
     * Bit mask for mFieldsMask indicating the presence of mAltitude.
     */
    private static final int HAS_ALTITUDE_MASK = 1;
    /**
     * Bit mask for mFieldsMask indicating the presence of mSpeed.
     */
    private static final int HAS_SPEED_MASK = 2;
    /**
     * Bit mask for mFieldsMask indicating the presence of mBearing.
     */
    private static final int HAS_BEARING_MASK = 4;
    /**
     * Bit mask for mFieldsMask indicating the presence of mHorizontalAccuracy.
     */
    private static final int HAS_HORIZONTAL_ACCURACY_MASK = 8;
    /**
     * Bit mask for mFieldsMask indicating location is from a mock provider.
     */
    private static final int HAS_MOCK_PROVIDER_MASK = 16;
    /**
     * Bit mask for mFieldsMask indicating the presence of mVerticalAccuracy.
     */
    private static final int HAS_VERTICAL_ACCURACY_MASK = 32;
    /**
     * Bit mask for mFieldsMask indicating the presence of mSpeedAccuracy.
     */
    private static final int HAS_SPEED_ACCURACY_MASK = 64;
    /**
     * Bit mask for mFieldsMask indicating the presence of mBearingAccuracy.
     */
    private static final int HAS_BEARING_ACCURACY_MASK = 128;
    /**
     * Bit mask for mFieldsMask indicating the presence of mElapsedRealtimeUncertaintyNanos.
     */
    private static final int HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK = 256;

    // Cached data to make bearing/distance computations more efficient for the case
    // where distanceTo and bearingTo are called in sequence.  Assume this typically happens
    // on the same thread for caching purposes.
    private static ThreadLocal<BearingDistanceCache> sBearingDistanceCache
            = new ThreadLocal<BearingDistanceCache>() {
        @Override
        protected BearingDistanceCache initialValue() {
            return new BearingDistanceCache();
        }
    };

    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
    private String mProvider;
    private long mTime = 0;
    @UnsupportedAppUsage
    private long mElapsedRealtimeNanos = 0;
    // Estimate of the relative precision of the alignment of this SystemClock
    // timestamp, with the reported measurements in nanoseconds (68% confidence).
    private double mElapsedRealtimeUncertaintyNanos = 0.0f;
    private double mLatitude = 0.0;
    private double mLongitude = 0.0;
    private double mAltitude = 0.0f;
    private float mSpeed = 0.0f;
    private float mBearing = 0.0f;
    private float mHorizontalAccuracyMeters = 0.0f;
    private float mVerticalAccuracyMeters = 0.0f;
    private float mSpeedAccuracyMetersPerSecond = 0.0f;
    private float mBearingAccuracyDegrees = 0.0f;

    private Bundle mExtras = null;

    // A bitmask of fields present in this object (see HAS_* constants defined above).
    private int mFieldsMask = 0;

    /**
     * Construct a new Location with a named provider.
     *
     * <p>By default time, latitude and longitude are 0, and the location
     * has no bearing, altitude, speed, accuracy or extras.
     *
     * @param provider the name of the provider that generated this location
     */
    public Location(String provider) {
        mProvider = provider;
    }

    /**
     * Construct a new Location object that is copied from an existing one.
     */
    public Location(Location l) {
        set(l);
    }

    /**
     * Sets the contents of the location to the values from the given location.
     */
    public void set(Location l) {
        mProvider = l.mProvider;
        mTime = l.mTime;
        mElapsedRealtimeNanos = l.mElapsedRealtimeNanos;
        mElapsedRealtimeUncertaintyNanos = l.mElapsedRealtimeUncertaintyNanos;
        mFieldsMask = l.mFieldsMask;
        mLatitude = l.mLatitude;
        mLongitude = l.mLongitude;
        mAltitude = l.mAltitude;
        mSpeed = l.mSpeed;
        mBearing = l.mBearing;
        mHorizontalAccuracyMeters = l.mHorizontalAccuracyMeters;
        mVerticalAccuracyMeters = l.mVerticalAccuracyMeters;
        mSpeedAccuracyMetersPerSecond = l.mSpeedAccuracyMetersPerSecond;
        mBearingAccuracyDegrees = l.mBearingAccuracyDegrees;
        mExtras = (l.mExtras == null) ? null : new Bundle(l.mExtras);
    }

    /**
     * Clears the contents of the location.
     */
    public void reset() {
        mProvider = null;
        mTime = 0;
        mElapsedRealtimeNanos = 0;
        mElapsedRealtimeUncertaintyNanos = 0.0;
        mFieldsMask = 0;
        mLatitude = 0;
        mLongitude = 0;
        mAltitude = 0;
        mSpeed = 0;
        mBearing = 0;
        mHorizontalAccuracyMeters = 0;
        mVerticalAccuracyMeters = 0;
        mSpeedAccuracyMetersPerSecond = 0;
        mBearingAccuracyDegrees = 0;
        mExtras = null;
    }

    /**
     * Converts a coordinate to a String representation. The outputType
     * may be one of FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
     * The coordinate must be a valid double between -180.0 and 180.0.
     * This conversion is performed in a method that is dependent on the
     * default locale, and so is not guaranteed to round-trip with
     * {@link #convert(String)}.
     *
     * @throws IllegalArgumentException if coordinate is less than
     * -180.0, greater than 180.0, or is not a number.
     * @throws IllegalArgumentException if outputType is not one of
     * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS.
     */
    public static String convert(double coordinate, int outputType) {
        if (coordinate < -180.0 || coordinate > 180.0 ||
            Double.isNaN(coordinate)) {
            throw new IllegalArgumentException("coordinate=" + coordinate);
        }
        if ((outputType != FORMAT_DEGREES) &&
            (outputType != FORMAT_MINUTES) &&
            (outputType != FORMAT_SECONDS)) {
            throw new IllegalArgumentException("outputType=" + outputType);
        }

        StringBuilder sb = new StringBuilder();

        // Handle negative values
        if (coordinate < 0) {
            sb.append('-');
            coordinate = -coordinate;
        }

        DecimalFormat df = new DecimalFormat("###.#####");
        if (outputType == FORMAT_MINUTES || outputType == FORMAT_SECONDS) {
            int degrees = (int) Math.floor(coordinate);
            sb.append(degrees);
            sb.append(':');
            coordinate -= degrees;
            coordinate *= 60.0;
            if (outputType == FORMAT_SECONDS) {
                int minutes = (int) Math.floor(coordinate);
                sb.append(minutes);
                sb.append(':');
                coordinate -= minutes;
                coordinate *= 60.0;
            }
        }
        sb.append(df.format(coordinate));
        return sb.toString();
    }

    /**
     * Converts a String in one of the formats described by
     * FORMAT_DEGREES, FORMAT_MINUTES, or FORMAT_SECONDS into a
     * double. This conversion is performed in a locale agnostic
     * method, and so is not guaranteed to round-trip with
     * {@link #convert(double, int)}.
     *
     * @throws NullPointerException if coordinate is null
     * @throws IllegalArgumentException if the coordinate is not
     * in one of the valid formats.
     */
    public static double convert(String coordinate) {
        // IllegalArgumentException if bad syntax
        if (coordinate == null) {
            throw new NullPointerException("coordinate");
        }

        boolean negative = false;
        if (coordinate.charAt(0) == '-') {
            coordinate = coordinate.substring(1);
            negative = true;
        }

        StringTokenizer st = new StringTokenizer(coordinate, ":");
        int tokens = st.countTokens();
        if (tokens < 1) {
            throw new IllegalArgumentException("coordinate=" + coordinate);
        }
        try {
            String degrees = st.nextToken();
            double val;
            if (tokens == 1) {
                val = Double.parseDouble(degrees);
                return negative ? -val : val;
            }

            String minutes = st.nextToken();
            int deg = Integer.parseInt(degrees);
            double min;
            double sec = 0.0;
            boolean secPresent = false;

            if (st.hasMoreTokens()) {
                min = Integer.parseInt(minutes);
                String seconds = st.nextToken();
                sec = Double.parseDouble(seconds);
                secPresent = true;
            } else {
                min = Double.parseDouble(minutes);
            }

            boolean isNegative180 = negative && (deg == 180) &&
                (min == 0) && (sec == 0);

            // deg must be in [0, 179] except for the case of -180 degrees
            if ((deg < 0.0) || (deg > 179 && !isNegative180)) {
                throw new IllegalArgumentException("coordinate=" + coordinate);
            }

            // min must be in [0, 59] if seconds are present, otherwise [0.0, 60.0)
            if (min < 0 || min >= 60 || (secPresent && (min > 59))) {
                throw new IllegalArgumentException("coordinate=" +
                        coordinate);
            }

            // sec must be in [0.0, 60.0)
            if (sec < 0 || sec >= 60) {
                throw new IllegalArgumentException("coordinate=" +
                        coordinate);
            }

            val = deg*3600.0 + min*60.0 + sec;
            val /= 3600.0;
            return negative ? -val : val;
        } catch (NumberFormatException nfe) {
            throw new IllegalArgumentException("coordinate=" + coordinate);
        }
    }

    private static void computeDistanceAndBearing(double lat1, double lon1,
        double lat2, double lon2, BearingDistanceCache results) {
        // Based on http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
        // using the "Inverse Formula" (section 4)

        int MAXITERS = 20;
        // Convert lat/long to radians
        lat1 *= Math.PI / 180.0;
        lat2 *= Math.PI / 180.0;
        lon1 *= Math.PI / 180.0;
        lon2 *= Math.PI / 180.0;

        double a = 6378137.0; // WGS84 major axis
        double b = 6356752.3142; // WGS84 semi-major axis
        double f = (a - b) / a;
        double aSqMinusBSqOverBSq = (a * a - b * b) / (b * b);

        double L = lon2 - lon1;
        double A = 0.0;
        double U1 = Math.atan((1.0 - f) * Math.tan(lat1));
        double U2 = Math.atan((1.0 - f) * Math.tan(lat2));

        double cosU1 = Math.cos(U1);
        double cosU2 = Math.cos(U2);
        double sinU1 = Math.sin(U1);
        double sinU2 = Math.sin(U2);
        double cosU1cosU2 = cosU1 * cosU2;
        double sinU1sinU2 = sinU1 * sinU2;

        double sigma = 0.0;
        double deltaSigma = 0.0;
        double cosSqAlpha = 0.0;
        double cos2SM = 0.0;
        double cosSigma = 0.0;
        double sinSigma = 0.0;
        double cosLambda = 0.0;
        double sinLambda = 0.0;

        double lambda = L; // initial guess
        for (int iter = 0; iter < MAXITERS; iter++) {
            double lambdaOrig = lambda;
            cosLambda = Math.cos(lambda);
            sinLambda = Math.sin(lambda);
            double t1 = cosU2 * sinLambda;
            double t2 = cosU1 * sinU2 - sinU1 * cosU2 * cosLambda;
            double sinSqSigma = t1 * t1 + t2 * t2; // (14)
            sinSigma = Math.sqrt(sinSqSigma);
            cosSigma = sinU1sinU2 + cosU1cosU2 * cosLambda; // (15)
            sigma = Math.atan2(sinSigma, cosSigma); // (16)
            double sinAlpha = (sinSigma == 0) ? 0.0 :
                cosU1cosU2 * sinLambda / sinSigma; // (17)
            cosSqAlpha = 1.0 - sinAlpha * sinAlpha;
            cos2SM = (cosSqAlpha == 0) ? 0.0 :
                cosSigma - 2.0 * sinU1sinU2 / cosSqAlpha; // (18)

            double uSquared = cosSqAlpha * aSqMinusBSqOverBSq; // defn
            A = 1 + (uSquared / 16384.0) * // (3)
                (4096.0 + uSquared *
                 (-768 + uSquared * (320.0 - 175.0 * uSquared)));
            double B = (uSquared / 1024.0) * // (4)
                (256.0 + uSquared *
                 (-128.0 + uSquared * (74.0 - 47.0 * uSquared)));
            double C = (f / 16.0) *
                cosSqAlpha *
                (4.0 + f * (4.0 - 3.0 * cosSqAlpha)); // (10)
            double cos2SMSq = cos2SM * cos2SM;
            deltaSigma = B * sinSigma * // (6)
                (cos2SM + (B / 4.0) *
                 (cosSigma * (-1.0 + 2.0 * cos2SMSq) -
                  (B / 6.0) * cos2SM *
                  (-3.0 + 4.0 * sinSigma * sinSigma) *
                  (-3.0 + 4.0 * cos2SMSq)));

            lambda = L +
                (1.0 - C) * f * sinAlpha *
                (sigma + C * sinSigma *
                 (cos2SM + C * cosSigma *
                  (-1.0 + 2.0 * cos2SM * cos2SM))); // (11)

            double delta = (lambda - lambdaOrig) / lambda;
            if (Math.abs(delta) < 1.0e-12) {
                break;
            }
        }

        float distance = (float) (b * A * (sigma - deltaSigma));
        results.mDistance = distance;
        float initialBearing = (float) Math.atan2(cosU2 * sinLambda,
            cosU1 * sinU2 - sinU1 * cosU2 * cosLambda);
        initialBearing *= 180.0 / Math.PI;
        results.mInitialBearing = initialBearing;
        float finalBearing = (float) Math.atan2(cosU1 * sinLambda,
                -sinU1 * cosU2 + cosU1 * sinU2 * cosLambda);
        finalBearing *= 180.0 / Math.PI;
        results.mFinalBearing = finalBearing;
        results.mLat1 = lat1;
        results.mLat2 = lat2;
        results.mLon1 = lon1;
        results.mLon2 = lon2;
    }

    /**
     * Computes the approximate distance in meters between two
     * locations, and optionally the initial and final bearings of the
     * shortest path between them.  Distance and bearing are defined using the
     * WGS84 ellipsoid.
     *
     * <p> The computed distance is stored in results[0].  If results has length
     * 2 or greater, the initial bearing is stored in results[1]. If results has
     * length 3 or greater, the final bearing is stored in results[2].
     *
     * @param startLatitude the starting latitude
     * @param startLongitude the starting longitude
     * @param endLatitude the ending latitude
     * @param endLongitude the ending longitude
     * @param results an array of floats to hold the results
     *
     * @throws IllegalArgumentException if results is null or has length < 1
     */
    public static void distanceBetween(double startLatitude, double startLongitude,
        double endLatitude, double endLongitude, float[] results) {
        if (results == null || results.length < 1) {
            throw new IllegalArgumentException("results is null or has length < 1");
        }
        BearingDistanceCache cache = sBearingDistanceCache.get();
        computeDistanceAndBearing(startLatitude, startLongitude,
                endLatitude, endLongitude, cache);
        results[0] = cache.mDistance;
        if (results.length > 1) {
            results[1] = cache.mInitialBearing;
            if (results.length > 2) {
                results[2] = cache.mFinalBearing;
            }
        }
    }

    /**
     * Returns the approximate distance in meters between this
     * location and the given location.  Distance is defined using
     * the WGS84 ellipsoid.
     *
     * @param dest the destination location
     * @return the approximate distance in meters
     */
    public float distanceTo(Location dest) {
        BearingDistanceCache cache = sBearingDistanceCache.get();
        // See if we already have the result
        if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
            dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
            computeDistanceAndBearing(mLatitude, mLongitude,
                dest.mLatitude, dest.mLongitude, cache);
        }
        return cache.mDistance;
    }

    /**
     * Returns the approximate initial bearing in degrees East of true
     * North when traveling along the shortest path between this
     * location and the given location.  The shortest path is defined
     * using the WGS84 ellipsoid.  Locations that are (nearly)
     * antipodal may produce meaningless results.
     *
     * @param dest the destination location
     * @return the initial bearing in degrees
     */
    public float bearingTo(Location dest) {
        BearingDistanceCache cache = sBearingDistanceCache.get();
        // See if we already have the result
        if (mLatitude != cache.mLat1 || mLongitude != cache.mLon1 ||
                        dest.mLatitude != cache.mLat2 || dest.mLongitude != cache.mLon2) {
            computeDistanceAndBearing(mLatitude, mLongitude,
                dest.mLatitude, dest.mLongitude, cache);
        }
        return cache.mInitialBearing;
    }

    /**
     * Returns the name of the provider that generated this fix.
     *
     * @return the provider, or null if it has not been set
     */
    public String getProvider() {
        return mProvider;
    }

    /**
     * Sets the name of the provider that generated this fix.
     */
    public void setProvider(String provider) {
        mProvider = provider;
    }

    /**
     * Return the UTC time of this fix, in milliseconds since January 1, 1970.
     *
     * <p>Note that the UTC time on a device is not monotonic: it
     * can jump forwards or backwards unpredictably. So always use
     * {@link #getElapsedRealtimeNanos} when calculating time deltas.
     *
     * <p>On the other hand, {@link #getTime} is useful for presenting
     * a human readable time to the user, or for carefully comparing
     * location fixes across reboot or across devices.
     *
     * <p>All locations generated by the {@link LocationManager}
     * are guaranteed to have a valid UTC time, however remember that
     * the system time may have changed since the location was generated.
     *
     * @return time of fix, in milliseconds since January 1, 1970.
     */
    public long getTime() {
        return mTime;
    }

    /**
     * Set the UTC time of this fix, in milliseconds since January 1,
     * 1970.
     *
     * @param time UTC time of this fix, in milliseconds since January 1, 1970
     */
    public void setTime(long time) {
        mTime = time;
    }

    /**
     * Return the time of this fix, in elapsed real-time since system boot.
     *
     * <p>This value can be reliably compared to
     * {@link android.os.SystemClock#elapsedRealtimeNanos},
     * to calculate the age of a fix and to compare Location fixes. This
     * is reliable because elapsed real-time is guaranteed monotonic for
     * each system boot and continues to increment even when the system
     * is in deep sleep (unlike {@link #getTime}.
     *
     * <p>All locations generated by the {@link LocationManager}
     * are guaranteed to have a valid elapsed real-time.
     *
     * @return elapsed real-time of fix, in nanoseconds since system boot.
     */
    public long getElapsedRealtimeNanos() {
        return mElapsedRealtimeNanos;
    }

    /**
     * Set the time of this fix, in elapsed real-time since system boot.
     *
     * @param time elapsed real-time of fix, in nanoseconds since system boot.
     */
    public void setElapsedRealtimeNanos(long time) {
        mElapsedRealtimeNanos = time;
    }

    /**
     * Get estimate of the relative precision of the alignment of the
     * ElapsedRealtimeNanos timestamp, with the reported measurements in
     * nanoseconds (68% confidence).
     *
     * This means that we have 68% confidence that the true timestamp of the
     * event is within ElapsedReatimeNanos +/- uncertainty.
     *
     * Example :
     *   - getElapsedRealtimeNanos() returns 10000000
     *   - getElapsedRealtimeUncertaintyNanos() returns 1000000 (equivalent to 1millisecond)
     *   This means that the event most likely happened between 9000000 and 11000000.
     *
     * @return uncertainty of elapsed real-time of fix, in nanoseconds.
     */
    public double getElapsedRealtimeUncertaintyNanos() {
        return mElapsedRealtimeUncertaintyNanos;
    }

    /**
     * Set estimate of the relative precision of the alignment of the
     * ElapsedRealtimeNanos timestamp, with the reported measurements in
     * nanoseconds (68% confidence).
     *
     * @param time uncertainty of the elapsed real-time of fix, in nanoseconds.
     */
    public void setElapsedRealtimeUncertaintyNanos(double time) {
        mElapsedRealtimeUncertaintyNanos = time;
        mFieldsMask |= HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK;
    }

    /**
     * True if this location has a elapsed realtime accuracy.
     */
    public boolean hasElapsedRealtimeUncertaintyNanos() {
        return (mFieldsMask & HAS_ELAPSED_REALTIME_UNCERTAINTY_MASK) != 0;
    }


    /**
     * Get the latitude, in degrees.
     *
     * <p>All locations generated by the {@link LocationManager}
     * will have a valid latitude.
     */
    public double getLatitude() {
        return mLatitude;
    }

    /**
     * Set the latitude, in degrees.
     */
    public void setLatitude(double latitude) {
        mLatitude = latitude;
    }

    /**
     * Get the longitude, in degrees.
     *
     * <p>All locations generated by the {@link LocationManager}
     * will have a valid longitude.
     */
    public double getLongitude() {
        return mLongitude;
    }

    /**
     * Set the longitude, in degrees.
     */
    public void setLongitude(double longitude) {
        mLongitude = longitude;
    }

    /**
     * True if this location has an altitude.
     */
    public boolean hasAltitude() {
        return (mFieldsMask & HAS_ALTITUDE_MASK) != 0;
    }

    /**
     * Get the altitude if available, in meters above the WGS 84 reference
     * ellipsoid.
     *
     * <p>If this location does not have an altitude then 0.0 is returned.
     */
    public double getAltitude() {
        return mAltitude;
    }

    /**
     * Set the altitude, in meters above the WGS 84 reference ellipsoid.
     *
     * <p>Following this call {@link #hasAltitude} will return true.
     */
    public void setAltitude(double altitude) {
        mAltitude = altitude;
        mFieldsMask |= HAS_ALTITUDE_MASK;
    }

    /**
     * Remove the altitude from this location.
     *
     * <p>Following this call {@link #hasAltitude} will return false,
     * and {@link #getAltitude} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     */
    @Deprecated
    public void removeAltitude() {
        mAltitude = 0.0f;
        mFieldsMask &= ~HAS_ALTITUDE_MASK;
    }

    /**
     * True if this location has a speed.
     */
    public boolean hasSpeed() {
        return (mFieldsMask & HAS_SPEED_MASK) != 0;
    }

    /**
     * Get the speed if it is available, in meters/second over ground.
     *
     * <p>If this location does not have a speed then 0.0 is returned.
     */
    public float getSpeed() {
        return mSpeed;
    }

    /**
     * Set the speed, in meters/second over ground.
     *
     * <p>Following this call {@link #hasSpeed} will return true.
     */
    public void setSpeed(float speed) {
        mSpeed = speed;
        mFieldsMask |= HAS_SPEED_MASK;
    }

    /**
     * Remove the speed from this location.
     *
     * <p>Following this call {@link #hasSpeed} will return false,
     * and {@link #getSpeed} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     */
    @Deprecated
    public void removeSpeed() {
        mSpeed = 0.0f;
        mFieldsMask &= ~HAS_SPEED_MASK;
    }

    /**
     * True if this location has a bearing.
     */
    public boolean hasBearing() {
        return (mFieldsMask & HAS_BEARING_MASK) != 0;
    }

    /**
     * Get the bearing, in degrees.
     *
     * <p>Bearing is the horizontal direction of travel of this device,
     * and is not related to the device orientation. It is guaranteed to
     * be in the range (0.0, 360.0] if the device has a bearing.
     *
     * <p>If this location does not have a bearing then 0.0 is returned.
     */
    public float getBearing() {
        return mBearing;
    }

    /**
     * Set the bearing, in degrees.
     *
     * <p>Bearing is the horizontal direction of travel of this device,
     * and is not related to the device orientation.
     *
     * <p>The input will be wrapped into the range (0.0, 360.0].
     */
    public void setBearing(float bearing) {
        while (bearing < 0.0f) {
            bearing += 360.0f;
        }
        while (bearing >= 360.0f) {
            bearing -= 360.0f;
        }
        mBearing = bearing;
        mFieldsMask |= HAS_BEARING_MASK;
    }

    /**
     * Remove the bearing from this location.
     *
     * <p>Following this call {@link #hasBearing} will return false,
     * and {@link #getBearing} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     */
    @Deprecated
    public void removeBearing() {
        mBearing = 0.0f;
        mFieldsMask &= ~HAS_BEARING_MASK;
    }

    /**
     * True if this location has a horizontal accuracy.
     *
     * <p>All locations generated by the {@link LocationManager} have an horizontal accuracy.
     */
    public boolean hasAccuracy() {
        return (mFieldsMask & HAS_HORIZONTAL_ACCURACY_MASK) != 0;
    }

    /**
     * Get the estimated horizontal accuracy of this location, radial, in meters.
     *
     * <p>We define horizontal accuracy as the radius of 68% confidence. In other
     * words, if you draw a circle centered at this location's
     * latitude and longitude, and with a radius equal to the accuracy,
     * then there is a 68% probability that the true location is inside
     * the circle.
     *
     * <p>This accuracy estimation is only concerned with horizontal
     * accuracy, and does not indicate the accuracy of bearing,
     * velocity or altitude if those are included in this Location.
     *
     * <p>If this location does not have a horizontal accuracy, then 0.0 is returned.
     * All locations generated by the {@link LocationManager} include horizontal accuracy.
     */
    public float getAccuracy() {
        return mHorizontalAccuracyMeters;
    }

    /**
     * Set the estimated horizontal accuracy of this location, meters.
     *
     * <p>See {@link #getAccuracy} for the definition of horizontal accuracy.
     *
     * <p>Following this call {@link #hasAccuracy} will return true.
     */
    public void setAccuracy(float horizontalAccuracy) {
        mHorizontalAccuracyMeters = horizontalAccuracy;
        mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
    }

    /**
     * Remove the horizontal accuracy from this location.
     *
     * <p>Following this call {@link #hasAccuracy} will return false, and
     * {@link #getAccuracy} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     */
    @Deprecated
    public void removeAccuracy() {
        mHorizontalAccuracyMeters = 0.0f;
        mFieldsMask &= ~HAS_HORIZONTAL_ACCURACY_MASK;
    }

    /**
     * True if this location has a vertical accuracy.
     */
    public boolean hasVerticalAccuracy() {
        return (mFieldsMask & HAS_VERTICAL_ACCURACY_MASK) != 0;
    }

    /**
     * Get the estimated vertical accuracy of this location, in meters.
     *
     * <p>We define vertical accuracy at 68% confidence.  Specifically, as 1-side of the
     * 2-sided range above and below the estimated altitude reported by {@link #getAltitude()},
     * within which there is a 68% probability of finding the true altitude.
     *
     * <p>In the case where the underlying distribution is assumed Gaussian normal, this would be
     * considered 1 standard deviation.
     *
     * <p>For example, if {@link #getAltitude()} returns 150, and
     * {@link #getVerticalAccuracyMeters()} returns 20 then there is a 68% probability
     * of the true altitude being between 130 and 170 meters.
     *
     * <p>If this location does not have a vertical accuracy, then 0.0 is returned.
     */
    public float getVerticalAccuracyMeters() {
        return mVerticalAccuracyMeters;
    }

    /**
     * Set the estimated vertical accuracy of this location, meters.
     *
     * <p>See {@link #getVerticalAccuracyMeters} for the definition of vertical accuracy.
     *
     * <p>Following this call {@link #hasVerticalAccuracy} will return true.
     */
    public void setVerticalAccuracyMeters(float verticalAccuracyMeters) {
        mVerticalAccuracyMeters = verticalAccuracyMeters;
        mFieldsMask |= HAS_VERTICAL_ACCURACY_MASK;
    }

    /**
     * Remove the vertical accuracy from this location.
     *
     * <p>Following this call {@link #hasVerticalAccuracy} will return false, and
     * {@link #getVerticalAccuracyMeters} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     * @removed
     */
    @Deprecated
    public void removeVerticalAccuracy() {
        mVerticalAccuracyMeters = 0.0f;
        mFieldsMask &= ~HAS_VERTICAL_ACCURACY_MASK;
    }

    /**
     * True if this location has a speed accuracy.
     */
    public boolean hasSpeedAccuracy() {
        return (mFieldsMask & HAS_SPEED_ACCURACY_MASK) != 0;
    }

    /**
     * Get the estimated speed accuracy of this location, in meters per second.
     *
     * <p>We define speed accuracy at 68% confidence.  Specifically, as 1-side of the
     * 2-sided range above and below the estimated speed reported by {@link #getSpeed()},
     * within which there is a 68% probability of finding the true speed.
     *
     * <p>In the case where the underlying
     * distribution is assumed Gaussian normal, this would be considered 1 standard deviation.
     *
     * <p>For example, if {@link #getSpeed()} returns 5, and
     * {@link #getSpeedAccuracyMetersPerSecond()} returns 1, then there is a 68% probability of
     * the true speed being between 4 and 6 meters per second.
     *
     * <p>Note that the speed and speed accuracy is often better than would be obtained simply from
     * differencing sequential positions, such as when the Doppler measurements from GNSS satellites
     * are used.
     *
     * <p>If this location does not have a speed accuracy, then 0.0 is returned.
     */
    public float getSpeedAccuracyMetersPerSecond() {
        return mSpeedAccuracyMetersPerSecond;
    }

    /**
     * Set the estimated speed accuracy of this location, meters per second.
     *
     * <p>See {@link #getSpeedAccuracyMetersPerSecond} for the definition of speed accuracy.
     *
     * <p>Following this call {@link #hasSpeedAccuracy} will return true.
     */
    public void setSpeedAccuracyMetersPerSecond(float speedAccuracyMeterPerSecond) {
        mSpeedAccuracyMetersPerSecond = speedAccuracyMeterPerSecond;
        mFieldsMask |= HAS_SPEED_ACCURACY_MASK;
    }

    /**
     * Remove the speed accuracy from this location.
     *
     * <p>Following this call {@link #hasSpeedAccuracy} will return false, and
     * {@link #getSpeedAccuracyMetersPerSecond} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     * @removed
     */
    @Deprecated
    public void removeSpeedAccuracy() {
        mSpeedAccuracyMetersPerSecond = 0.0f;
        mFieldsMask &= ~HAS_SPEED_ACCURACY_MASK;
    }

    /**
     * True if this location has a bearing accuracy.
     */
    public boolean hasBearingAccuracy() {
        return (mFieldsMask & HAS_BEARING_ACCURACY_MASK) != 0;
    }

    /**
     * Get the estimated bearing accuracy of this location, in degrees.
     *
     * <p>We define bearing accuracy at 68% confidence.  Specifically, as 1-side of the
     * 2-sided range on each side of the estimated bearing reported by {@link #getBearing()},
     * within which there is a 68% probability of finding the true bearing.
     *
     * <p>In the case where the underlying distribution is assumed Gaussian normal, this would be
     * considered 1 standard deviation.
     *
     * <p>For example, if {@link #getBearing()} returns 60, and
     * {@link #getBearingAccuracyDegrees()} returns 10, then there is a 68% probability of the
     * true bearing being between 50 and 70 degrees.
     *
     * <p>If this location does not have a bearing accuracy, then 0.0 is returned.
     */
    public float getBearingAccuracyDegrees() {
        return mBearingAccuracyDegrees;
    }

    /**
     * Set the estimated bearing accuracy of this location, degrees.
     *
     * <p>See {@link #getBearingAccuracyDegrees} for the definition of bearing accuracy.
     *
     * <p>Following this call {@link #hasBearingAccuracy} will return true.
     */
    public void setBearingAccuracyDegrees(float bearingAccuracyDegrees) {
        mBearingAccuracyDegrees = bearingAccuracyDegrees;
        mFieldsMask |= HAS_BEARING_ACCURACY_MASK;
    }

    /**
     * Remove the bearing accuracy from this location.
     *
     * <p>Following this call {@link #hasBearingAccuracy} will return false, and
     * {@link #getBearingAccuracyDegrees} will return 0.0.
     *
     * @deprecated use a new Location object for location updates.
     * @removed
     */
    @Deprecated
    public void removeBearingAccuracy() {
        mBearingAccuracyDegrees = 0.0f;
        mFieldsMask &= ~HAS_BEARING_ACCURACY_MASK;
    }

    /**
     * Return true if this Location object is complete.
     *
     * <p>A location object is currently considered complete if it has
     * a valid provider, accuracy, wall-clock time and elapsed real-time.
     *
     * <p>All locations supplied by the {@link LocationManager} to
     * applications must be complete.
     *
     * @see #makeComplete
     * @hide
     */
    @SystemApi
    public boolean isComplete() {
        if (mProvider == null) return false;
        if (!hasAccuracy()) return false;
        if (mTime == 0) return false;
        if (mElapsedRealtimeNanos == 0) return false;
        return true;
    }

    /**
     * Helper to fill incomplete fields.
     *
     * <p>Used to assist in backwards compatibility with
     * Location objects received from applications.
     *
     * @see #isComplete
     * @hide
     */
    @TestApi
    @SystemApi
    public void makeComplete() {
        if (mProvider == null) mProvider = "?";
        if (!hasAccuracy()) {
            mFieldsMask |= HAS_HORIZONTAL_ACCURACY_MASK;
            mHorizontalAccuracyMeters = 100.0f;
        }
        if (mTime == 0) mTime = System.currentTimeMillis();
        if (mElapsedRealtimeNanos == 0) mElapsedRealtimeNanos = SystemClock.elapsedRealtimeNanos();
    }

    /**
     * Returns additional provider-specific information about the
     * location fix as a Bundle.  The keys and values are determined
     * by the provider.  If no additional information is available,
     * null is returned.
     *
     * <p> A number of common key/value pairs are listed
     * below. Providers that use any of the keys on this list must
     * provide the corresponding value as described below.
     *
     * <ul>
     * <li> satellites - the number of satellites used to derive the fix
     * </ul>
     */
    public Bundle getExtras() {
        return mExtras;
    }

    /**
     * Sets the extra information associated with this fix to the
     * given Bundle.
     *
     * <p>Note this stores a copy of the given extras, so any changes to extras after calling this
     * method won't be reflected in the location bundle.
     */
    public void setExtras(Bundle extras) {
        mExtras = (extras == null) ? null : new Bundle(extras);
    }

    @Override
    public String toString() {
        StringBuilder s = new StringBuilder();
        s.append("Location[");
        s.append(mProvider);
        s.append(String.format(" %.6f,%.6f", mLatitude, mLongitude));
        if (hasAccuracy()) s.append(String.format(" hAcc=%.0f", mHorizontalAccuracyMeters));
        else s.append(" hAcc=???");
        if (mTime == 0) {
            s.append(" t=?!?");
        }
        if (mElapsedRealtimeNanos == 0) {
            s.append(" et=?!?");
        } else {
            s.append(" et=");
            TimeUtils.formatDuration(mElapsedRealtimeNanos / 1000000L, s);
        }
        if (hasElapsedRealtimeUncertaintyNanos()) {
            s.append(" etAcc=");
            TimeUtils.formatDuration((long) (mElapsedRealtimeUncertaintyNanos / 1000000), s);
        }
        if (hasAltitude()) s.append(" alt=").append(mAltitude);
        if (hasSpeed()) s.append(" vel=").append(mSpeed);
        if (hasBearing()) s.append(" bear=").append(mBearing);
        if (hasVerticalAccuracy()) s.append(String.format(" vAcc=%.0f", mVerticalAccuracyMeters));
        else s.append(" vAcc=???");
        if (hasSpeedAccuracy()) s.append(String.format(" sAcc=%.0f", mSpeedAccuracyMetersPerSecond));
        else s.append(" sAcc=???");
        if (hasBearingAccuracy()) s.append(String.format(" bAcc=%.0f", mBearingAccuracyDegrees));
        else s.append(" bAcc=???");
        if (isFromMockProvider()) s.append(" mock");

        if (mExtras != null) {
            s.append(" {").append(mExtras).append('}');
        }
        s.append(']');
        return s.toString();
    }

    public void dump(Printer pw, String prefix) {
        pw.println(prefix + toString());
    }

    public static final @android.annotation.NonNull Parcelable.Creator<Location> CREATOR =
        new Parcelable.Creator<Location>() {
        @Override
        public Location createFromParcel(Parcel in) {
            String provider = in.readString();
            Location l = new Location(provider);
            l.mTime = in.readLong();
            l.mElapsedRealtimeNanos = in.readLong();
            l.mElapsedRealtimeUncertaintyNanos = in.readDouble();
            l.mFieldsMask = in.readInt();
            l.mLatitude = in.readDouble();
            l.mLongitude = in.readDouble();
            l.mAltitude = in.readDouble();
            l.mSpeed = in.readFloat();
            l.mBearing = in.readFloat();
            l.mHorizontalAccuracyMeters = in.readFloat();
            l.mVerticalAccuracyMeters = in.readFloat();
            l.mSpeedAccuracyMetersPerSecond = in.readFloat();
            l.mBearingAccuracyDegrees = in.readFloat();
            l.mExtras = Bundle.setDefusable(in.readBundle(), true);
            return l;
        }

        @Override
        public Location[] newArray(int size) {
            return new Location[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeString(mProvider);
        parcel.writeLong(mTime);
        parcel.writeLong(mElapsedRealtimeNanos);
        parcel.writeDouble(mElapsedRealtimeUncertaintyNanos);
        parcel.writeInt(mFieldsMask);
        parcel.writeDouble(mLatitude);
        parcel.writeDouble(mLongitude);
        parcel.writeDouble(mAltitude);
        parcel.writeFloat(mSpeed);
        parcel.writeFloat(mBearing);
        parcel.writeFloat(mHorizontalAccuracyMeters);
        parcel.writeFloat(mVerticalAccuracyMeters);
        parcel.writeFloat(mSpeedAccuracyMetersPerSecond);
        parcel.writeFloat(mBearingAccuracyDegrees);
        parcel.writeBundle(mExtras);
    }

    /**
     * Returns one of the optional extra {@link Location}s that can be attached
     * to this Location.
     *
     * @param key the key associated with the desired extra Location
     * @return the extra Location, or null if unavailable
     * @hide
     */
    public Location getExtraLocation(String key) {
        if (mExtras != null) {
            Parcelable value = mExtras.getParcelable(key);
            if (value instanceof Location) {
                return (Location) value;
            }
        }
        return null;
    }

    /**
     * Attaches an extra {@link Location} to this Location.
     *
     * @param key the key associated with the Location extra
     * @param value the Location to attach
     * @hide
     */
    @UnsupportedAppUsage
    public void setExtraLocation(String key, Location value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putParcelable(key, value);
    }

    /**
     * Returns true if the Location came from a mock provider.
     *
     * @return true if this Location came from a mock provider, false otherwise
     */
    public boolean isFromMockProvider() {
        return (mFieldsMask & HAS_MOCK_PROVIDER_MASK) != 0;
    }

    /**
     * Flag this Location as having come from a mock provider or not.
     *
     * @param isFromMockProvider true if this Location came from a mock provider, false otherwise
     * @hide
     */
    @SystemApi
    public void setIsFromMockProvider(boolean isFromMockProvider) {
        if (isFromMockProvider) {
            mFieldsMask |= HAS_MOCK_PROVIDER_MASK;
        } else {
            mFieldsMask &= ~HAS_MOCK_PROVIDER_MASK;
        }
    }

    /**
     * Caches data used to compute distance and bearing (so successive calls to {@link #distanceTo}
     * and {@link #bearingTo} don't duplicate work.
     */
    private static class BearingDistanceCache {
        private double mLat1 = 0.0;
        private double mLon1 = 0.0;
        private double mLat2 = 0.0;
        private double mLon2 = 0.0;
        private float mDistance = 0.0f;
        private float mInitialBearing = 0.0f;
        private float mFinalBearing = 0.0f;
    }
}
