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