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