OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.chrome.browser.omnibox.geo; |
| 6 |
| 7 import android.content.Context; |
| 8 import android.location.Location; |
| 9 import android.location.LocationListener; |
| 10 import android.location.LocationManager; |
| 11 import android.os.Bundle; |
| 12 import android.os.Handler; |
| 13 |
| 14 import org.chromium.base.ThreadUtils; |
| 15 import org.chromium.base.VisibleForTesting; |
| 16 import org.chromium.base.annotations.SuppressFBWarnings; |
| 17 |
| 18 /** |
| 19 * Keeps track of the device's location, allowing synchronous location requests. |
| 20 * getLastKnownLocation() returns the current best estimate of the location. If
possible, call |
| 21 * refreshLastKnownLocation() several seconds before a location is needed to max
imize the chances |
| 22 * that the location is known. |
| 23 */ |
| 24 class GeolocationTracker { |
| 25 |
| 26 private static SelfCancelingListener sListener; |
| 27 private static Location sLocationForTesting; |
| 28 private static boolean sUseLocationForTesting; |
| 29 |
| 30 private static class SelfCancelingListener implements LocationListener { |
| 31 |
| 32 // Length of time before the location request should be canceled. This t
imeout ensures the |
| 33 // device doesn't get stuck in an infinite loop trying and failing to ge
t a location, which |
| 34 // would cause battery drain. See: http://crbug.com/309917 |
| 35 private static final int REQUEST_TIMEOUT_MS = 60 * 1000; // 60 sec. |
| 36 |
| 37 private final LocationManager mLocationManager; |
| 38 private final Handler mHandler; |
| 39 private final Runnable mCancelRunnable; |
| 40 |
| 41 private SelfCancelingListener(LocationManager manager) { |
| 42 mLocationManager = manager; |
| 43 mHandler = new Handler(); |
| 44 mCancelRunnable = new Runnable() { |
| 45 @Override |
| 46 public void run() { |
| 47 mLocationManager.removeUpdates(SelfCancelingListener.this); |
| 48 sListener = null; |
| 49 } |
| 50 }; |
| 51 mHandler.postDelayed(mCancelRunnable, REQUEST_TIMEOUT_MS); |
| 52 } |
| 53 |
| 54 @Override |
| 55 public void onLocationChanged(Location location) { |
| 56 mHandler.removeCallbacks(mCancelRunnable); |
| 57 sListener = null; |
| 58 } |
| 59 |
| 60 @Override |
| 61 public void onProviderDisabled(String provider) { } |
| 62 |
| 63 @Override |
| 64 public void onProviderEnabled(String provider) { } |
| 65 |
| 66 @Override |
| 67 public void onStatusChanged(String provider, int status, Bundle extras)
{ } |
| 68 } |
| 69 |
| 70 /** |
| 71 * Returns the age of location is milliseconds. |
| 72 * Note: the age will be invalid if the system clock has been changed since
the location was |
| 73 * created. If the apparent age is negative, Long.MAX_VALUE will be returned
. |
| 74 */ |
| 75 static long getLocationAge(Location location) { |
| 76 long age = System.currentTimeMillis() - location.getTime(); |
| 77 return age >= 0 ? age : Long.MAX_VALUE; |
| 78 } |
| 79 |
| 80 /** |
| 81 * Returns the last known location from the network provider or null if none
is available. |
| 82 */ |
| 83 static Location getLastKnownLocation(Context context) { |
| 84 if (sUseLocationForTesting) return sLocationForTesting; |
| 85 LocationManager locationManager = |
| 86 (LocationManager) context.getSystemService(Context.LOCATION_SERV
ICE); |
| 87 return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROV
IDER); |
| 88 } |
| 89 |
| 90 /** |
| 91 * Requests an updated location if the last known location is older than max
Age milliseconds. |
| 92 * |
| 93 * Note: this must be called only on the UI thread. |
| 94 */ |
| 95 @SuppressFBWarnings("LI_LAZY_INIT_UPDATE_STATIC") |
| 96 static void refreshLastKnownLocation(Context context, long maxAge) { |
| 97 ThreadUtils.assertOnUiThread(); |
| 98 |
| 99 // We're still waiting for a location update. |
| 100 if (sListener != null) return; |
| 101 |
| 102 LocationManager locationManager = |
| 103 (LocationManager) context.getSystemService(Context.LOCATION_SERV
ICE); |
| 104 Location location = locationManager.getLastKnownLocation(LocationManager
.NETWORK_PROVIDER); |
| 105 if (location == null || getLocationAge(location) > maxAge) { |
| 106 String provider = LocationManager.NETWORK_PROVIDER; |
| 107 if (locationManager.isProviderEnabled(provider)) { |
| 108 sListener = new SelfCancelingListener(locationManager); |
| 109 locationManager.requestSingleUpdate(provider, sListener, null); |
| 110 } |
| 111 } |
| 112 } |
| 113 |
| 114 @VisibleForTesting |
| 115 static void setLocationForTesting(Location location) { |
| 116 sLocationForTesting = location; |
| 117 sUseLocationForTesting = true; |
| 118 } |
| 119 } |
OLD | NEW |