Bug 828563 - Return the most recent location, not the most accurate provider's most recent location. r=blassey
authorChris Peterson <cpeterson@mozilla.com>
Tue, 07 May 2013 15:19:58 -0700
changeset 142250 061c33f0e98409ec930948d9e79bb7d412830c57
parent 142249 05a6210472f10421c8087edd83958335baa5ee3a
child 142251 814044b7f85345868cdcc9739bb9d86512d9564c
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs828563
milestone23.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 828563 - Return the most recent location, not the most accurate provider's most recent location. r=blassey
mobile/android/base/GeckoAppShell.java
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -144,17 +144,17 @@ public class GeckoAppShell
 
     private static Sensor gAccelerometerSensor = null;
     private static Sensor gLinearAccelerometerSensor = null;
     private static Sensor gGyroscopeSensor = null;
     private static Sensor gOrientationSensor = null;
     private static Sensor gProximitySensor = null;
     private static Sensor gLightSensor = null;
 
-    private static boolean mLocationHighAccuracy = false;
+    private static volatile boolean mLocationHighAccuracy;
 
     public static ActivityHandlerHelper sActivityHelper = new ActivityHandlerHelper();
     static NotificationClient sNotificationClient;
 
     /* The Android-side API: API methods that Android calls */
 
     // Initialization methods
     public static native void nativeInit();
@@ -388,24 +388,62 @@ public class GeckoAppShell
     // Signal the Java thread that it's time to wake up
     public static void acknowledgeEvent() {
         synchronized (sEventAckLock) {
             sWaitingForEventAck = false;
             sEventAckLock.notifyAll();
         }
     }
 
+    private static float getLocationAccuracy(Location location) {
+        float radius = location.getAccuracy();
+        return (location.hasAccuracy() && radius > 0) ? radius : 1001;
+    }
+
+    private static Location getLastKnownLocation() {
+        Location lastKnownLocation = null;
+        LocationManager lm = getLocationManager();
+        List<String> providers = lm.getAllProviders();
+
+        for (String provider : providers) {
+            Location location = lm.getLastKnownLocation(provider);
+            if (location == null) {
+                continue;
+            }
+
+            if (lastKnownLocation == null) {
+                lastKnownLocation = location;
+                continue;
+            }
+
+            long timeDiff = location.getElapsedRealtimeNanos()
+                            - lastKnownLocation.getElapsedRealtimeNanos();
+
+            if (timeDiff > 0 ||
+                (timeDiff == 0 &&
+                 getLocationAccuracy(location) < getLocationAccuracy(lastKnownLocation))) {
+                lastKnownLocation = location;
+            }
+        }
+
+        return lastKnownLocation;
+    }
+
     public static void enableLocation(final boolean enable) {
         ThreadUtils.postToUiThread(new Runnable() {
                 @Override
                 public void run() {
-                    LocationManager lm = (LocationManager)
-                        GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
+                    LocationManager lm = getLocationManager();
 
                     if (enable) {
+                        Location lastKnownLocation = getLastKnownLocation();
+                        if (lastKnownLocation != null) {
+                            GeckoApp.mAppContext.onLocationChanged(lastKnownLocation);
+                        }
+
                         Criteria criteria = new Criteria();
                         criteria.setSpeedRequired(false);
                         criteria.setBearingRequired(false);
                         criteria.setAltitudeRequired(false);
                         if (mLocationHighAccuracy) {
                             criteria.setAccuracy(Criteria.ACCURACY_FINE);
                             criteria.setCostAllowed(true);
                             criteria.setPowerRequirement(Criteria.POWER_HIGH);
@@ -415,28 +453,28 @@ public class GeckoAppShell
                             criteria.setPowerRequirement(Criteria.POWER_LOW);
                         }
 
                         String provider = lm.getBestProvider(criteria, true);
                         if (provider == null)
                             return;
 
                         Looper l = Looper.getMainLooper();
-                        Location loc = lm.getLastKnownLocation(provider);
-                        if (loc != null) {
-                            GeckoApp.mAppContext.onLocationChanged(loc);
-                        }
                         lm.requestLocationUpdates(provider, 100, (float).5, GeckoApp.mAppContext, l);
                     } else {
                         lm.removeUpdates(GeckoApp.mAppContext);
                     }
                 }
             });
     }
 
+    private static LocationManager getLocationManager() {
+        return (LocationManager) GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
+    }
+
     public static void enableLocationHighAccuracy(final boolean enable) {
         mLocationHighAccuracy = enable;
     }
 
     public static void enableSensor(int aSensortype) {
         SensorManager sm = (SensorManager)
             GeckoApp.mAppContext.getSystemService(Context.SENSOR_SERVICE);