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