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