From 4e50b78bda9cd58be61581d2886c88ff6348a1c1 Mon Sep 17 00:00:00 2001
From: Mike Lockwood <>
Date: Fri, 3 Apr 2009 08:24:43 -0700
Subject: [PATCH] AI 144452: More Location Manager cleanup: Remove 1 Hz
"heartbeat" polling of location providers from LocationManagerService. Now
location providers report their location to LocationManagerService via
LocationManager.setLocation() rather than waiting to be polled. This
reduces GPS fix latency by up to one second. Remove
LocationProvderImpl.getLocation(). Since we are no longer polling, this
method is no longer necessary. BUG=1729031
Automated import of CL 144452
---
.../android/location/ILocationManager.aidl | 3 +
.../location/LocationProviderImpl.java | 26 +--
.../location/GpsLocationProvider.java | 24 +--
.../location/INetworkLocationProvider.java | 5 -
.../internal/location/MockProvider.java | 45 ++----
.../internal/location/TrackProvider.java | 86 +++++-----
.../server/LocationManagerService.java | 148 ++++++------------
.../android/test/TestLocationProvider.java | 62 ++++++--
8 files changed, 179 insertions(+), 220 deletions(-)
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index d0f987721f483..a7fb04d14703b 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -53,6 +53,9 @@ interface ILocationManager
boolean isProviderEnabled(String provider);
Location getLastKnownLocation(String provider);
+
+ /* used by location providers to tell the location manager when it has a new location */
+ void setLocation(in Location location);
String getFromLocation(double latitude, double longitude, int maxResults,
String language, String country, String variant, String appName, out List
addrs);
diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/android/location/LocationProviderImpl.java
index 0962992c61f05..bb225e238f5df 100644
--- a/location/java/android/location/LocationProviderImpl.java
+++ b/location/java/android/location/LocationProviderImpl.java
@@ -27,6 +27,7 @@ import java.util.HashMap;
import java.util.List;
import android.os.Bundle;
+import android.os.RemoteException;
import android.util.Config;
import android.util.Log;
@@ -46,11 +47,13 @@ public abstract class LocationProviderImpl extends LocationProvider {
private static HashMap sProvidersByName
= new HashMap();
+ private final ILocationManager mLocationManager;
private boolean mLocationTracking = false;
private long mMinTime = 0;
- protected LocationProviderImpl(String name) {
+ protected LocationProviderImpl(String name, ILocationManager locationManager) {
super(name);
+ mLocationManager = locationManager;
}
public static void addProvider(LocationProviderImpl provider) {
@@ -114,16 +117,24 @@ public abstract class LocationProviderImpl extends LocationProvider {
return null;
}
+ public void reportLocationChanged(Location location) {
+ try {
+ mLocationManager.setLocation(location);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException calling ILocationManager.onLocationChanged");
+ }
+ }
+
/**
* Enables this provider. When enabled, calls to {@link #getStatus()}
- * and {@link #getLocation} must be handled. Hardware may be started up
+ * must be handled. Hardware may be started up
* when the provider is enabled.
*/
public abstract void enable();
/**
* Disables this provider. When disabled, calls to {@link #getStatus()}
- * and {@link #getLocation} need not be handled. Hardware may be shut
+ * need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
public abstract void disable();
@@ -174,15 +185,6 @@ public abstract class LocationProviderImpl extends LocationProvider {
return 0;
}
- /**
- * Sets a Location object with the information gathered
- * during the most recent fix.
- *
- * @param l location object to set
- * @return true if a location fix is available
- */
- public abstract boolean getLocation(Location l);
-
/**
* Notifies the location provider that clients are listening for locations.
* Called with enable set to true when the first client is added and
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index f5950501d5107..d09318a43b6ae 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -22,6 +22,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.location.Criteria;
import android.location.IGpsStatusListener;
+import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationProvider;
@@ -209,8 +210,8 @@ public class GpsLocationProvider extends LocationProviderImpl {
return native_is_supported();
}
- public GpsLocationProvider(Context context) {
- super(LocationManager.GPS_PROVIDER);
+ public GpsLocationProvider(Context context, ILocationManager locationManager) {
+ super(LocationManager.GPS_PROVIDER, locationManager);
mContext = context;
TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver();
@@ -355,7 +356,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
/**
* Enables this provider. When enabled, calls to getStatus()
- * and getLocation() must be handled. Hardware may be started up
+ * must be handled. Hardware may be started up
* when the provider is enabled.
*/
@Override
@@ -385,7 +386,7 @@ public class GpsLocationProvider extends LocationProviderImpl {
/**
* Disables this provider. When disabled, calls to getStatus()
- * and getLocation() need not be handled. Hardware may be shut
+ * need not be handled. Hardware may be shut
* down while the provider is disabled.
*/
@Override
@@ -448,19 +449,6 @@ public class GpsLocationProvider extends LocationProviderImpl {
return mStatusUpdateTime;
}
- @Override
- public boolean getLocation(Location l) {
- synchronized (mLocation) {
- // don't report locations without latitude and longitude
- if ((mLocationFlags & LOCATION_HAS_LAT_LONG) == 0) {
- return false;
- }
- l.set(mLocation);
- l.setExtras(mLocationExtras);
- return true;
- }
- }
-
@Override
public void enableLocationTracking(boolean enable) {
if (mLocationTracking == enable) {
@@ -685,6 +673,8 @@ public class GpsLocationProvider extends LocationProviderImpl {
mLocation.removeAccuracy();
}
+ reportLocationChanged(mLocation);
+
// Send to collector
if ((flags & LOCATION_HAS_LAT_LONG) == LOCATION_HAS_LAT_LONG
&& mCollector != null) {
diff --git a/location/java/com/android/internal/location/INetworkLocationProvider.java b/location/java/com/android/internal/location/INetworkLocationProvider.java
index 730cb480a4d6c..f8947a61d2a62 100644
--- a/location/java/com/android/internal/location/INetworkLocationProvider.java
+++ b/location/java/com/android/internal/location/INetworkLocationProvider.java
@@ -20,12 +20,7 @@ import android.location.Address;
import android.location.Location;
import android.net.wifi.ScanResult;
-import com.google.common.io.protocol.ProtoBuf;
-
-import java.io.IOException;
-import java.util.Collection;
import java.util.List;
-import java.util.Locale;
/**
* Interface for network location provider
diff --git a/location/java/com/android/internal/location/MockProvider.java b/location/java/com/android/internal/location/MockProvider.java
index bd5cdd84489f9..c8d5b4f314303 100644
--- a/location/java/com/android/internal/location/MockProvider.java
+++ b/location/java/com/android/internal/location/MockProvider.java
@@ -16,6 +16,7 @@
package com.android.internal.location;
+import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationProviderImpl;
import android.os.Bundle;
@@ -46,10 +47,11 @@ public class MockProvider extends LocationProviderImpl {
private boolean mHasStatus;
private boolean mEnabled;
- public MockProvider(String name, boolean requiresNetwork, boolean requiresSatellite,
+ public MockProvider(String name, ILocationManager locationManager,
+ boolean requiresNetwork, boolean requiresSatellite,
boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude,
boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) {
- super(name);
+ super(name, locationManager);
mRequiresNetwork = requiresNetwork;
mRequiresSatellite = requiresSatellite;
@@ -73,15 +75,6 @@ public class MockProvider extends LocationProviderImpl {
mEnabled = true;
}
- @Override
- public boolean getLocation(Location l) {
- if (mHasLocation) {
- l.set(mLocation);
- return true;
- }
- return false;
- }
-
@Override
public int getStatus(Bundle extras) {
if (mHasStatus) {
@@ -93,6 +86,11 @@ public class MockProvider extends LocationProviderImpl {
}
}
+ @Override
+ public long getStatusUpdateTime() {
+ return mStatusUpdateTime;
+ }
+
@Override
public boolean isEnabled() {
return mEnabled;
@@ -146,6 +144,7 @@ public class MockProvider extends LocationProviderImpl {
public void setLocation(Location l) {
mLocation.set(l);
mHasLocation = true;
+ reportLocationChanged(mLocation);
}
public void clearLocation() {
@@ -164,29 +163,7 @@ public class MockProvider extends LocationProviderImpl {
public void clearStatus() {
mHasStatus = false;
- }
-
- public int overrideStatus(int status) {
- if (mHasStatus) {
- return mStatus;
- } else {
- return status;
- }
- }
-
- public long overrideStatusUpdateTime(long statusUpdateTime) {
- if (mHasStatus) {
- return mStatusUpdateTime;
- } else {
- return statusUpdateTime;
- }
- }
-
- public void overrideExtras(Bundle extras) {
- if (mHasStatus) {
- extras.clear();
- extras.putAll(mExtras);
- }
+ mStatusUpdateTime = 0;
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/location/java/com/android/internal/location/TrackProvider.java b/location/java/com/android/internal/location/TrackProvider.java
index 545d7dc892741..168626096f10c 100644
--- a/location/java/com/android/internal/location/TrackProvider.java
+++ b/location/java/com/android/internal/location/TrackProvider.java
@@ -16,6 +16,7 @@ import java.util.List;
import java.util.StringTokenizer;
import android.location.Criteria;
+import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationProviderImpl;
import android.os.Bundle;
@@ -50,6 +51,7 @@ public class TrackProvider extends LocationProviderImpl {
private static final long INTERVAL = 1000L;
private boolean mEnabled = true;
+ private TrackProviderThread mThread;
private double mLatitude;
private double mLongitude;
@@ -86,6 +88,36 @@ public class TrackProvider extends LocationProviderImpl {
private Location mInitialLocation;
+ private class TrackProviderThread extends Thread {
+
+ private boolean mDone = false;
+
+ public TrackProviderThread() {
+ super("TrackProviderThread");
+ }
+
+ public void run() {
+ // thread exits after disable() is called
+ synchronized (this) {
+ while (!mDone) {
+ try {
+ wait(INTERVAL);
+ } catch (InterruptedException e) {
+ }
+
+ if (!mDone) {
+ TrackProvider.this.update();
+ }
+ }
+ }
+ }
+
+ synchronized void setDone() {
+ mDone = true;
+ notify();
+ }
+ }
+
private void close(Reader rdr) {
try {
if (rdr != null) {
@@ -392,13 +424,13 @@ public class TrackProvider extends LocationProviderImpl {
}
}
- public TrackProvider(String name) {
- super(name);
+ public TrackProvider(String name, ILocationManager locationManager) {
+ super(name, locationManager);
setTimes();
}
- public TrackProvider(String name, File file) {
- this(name);
+ public TrackProvider(String name, ILocationManager locationManager, File file) {
+ this(name, locationManager);
String filename = file.getName();
if (filename.endsWith("kml")) {
@@ -429,12 +461,7 @@ public class TrackProvider extends LocationProviderImpl {
}
private void update() {
- // Don't update the position at all unless INTERVAL milliseconds
- // have passed since the last request
long time = System.currentTimeMillis() - mBaseTime;
- if (time - mLastTime < INTERVAL) {
- return;
- }
List waypoints = mWaypoints;
if (waypoints == null) {
@@ -594,12 +621,22 @@ public class TrackProvider extends LocationProviderImpl {
mTrackSpeed = trackSpeed;
}
- @Override public void enable() {
- mEnabled = true;
+ @Override public synchronized void enable() {
+ mEnabled = true;
+ mThread = new TrackProviderThread();
+ mThread.start();
}
- @Override public void disable() {
+ @Override public synchronized void disable() {
mEnabled = false;
+ if (mThread != null) {
+ mThread.setDone();
+ try {
+ mThread.join();
+ } catch (InterruptedException e) {
+ }
+ mThread = null;
+ }
}
@Override public boolean isEnabled() {
@@ -610,31 +647,6 @@ public class TrackProvider extends LocationProviderImpl {
return AVAILABLE;
}
- @Override public boolean getLocation(Location l) {
- if (mEnabled) {
- update();
- l.setProvider(getName());
- l.setTime(mTime + mBaseTime);
- l.setLatitude(mLatitude);
- l.setLongitude(mLongitude);
- if (mSupportsAltitude && mHasAltitude) {
- l.setAltitude(mAltitude);
- }
- if (mSupportsBearing && mHasBearing) {
- l.setBearing(mBearing);
- }
- if (mSupportsSpeed && mHasSpeed) {
- l.setSpeed(mSpeed);
- }
- if (mExtras != null) {
- l.setExtras(mExtras);
- }
- return true;
- } else {
- return false;
- }
- }
-
public Location getInitialLocation() {
return mInitialLocation;
}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index f3187d77b2670..952fdc5528791 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -136,7 +136,7 @@ public class LocationManagerService extends ILocationManager.Stub
private LocationWorkerHandler mLocationHandler;
// Handler messages
- private static final int MESSAGE_HEARTBEAT = 1;
+ private static final int MESSAGE_LOCATION_CHANGED = 1;
private static final int MESSAGE_ACQUIRE_WAKE_LOCK = 2;
private static final int MESSAGE_RELEASE_WAKE_LOCK = 3;
private static final int MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER = 4;
@@ -191,13 +191,6 @@ public class LocationManagerService extends ILocationManager.Stub
private final HashMap> mRecordsByProvider =
new HashMap>();
- /**
- * Mappings from provider name to object to use for current location. Locations
- * contained in this list may not always be valid.
- */
- private final HashMap mLocationsByProvider =
- new HashMap();
-
// Proximity listeners
private Receiver mProximityListener = null;
private HashMap mProximityAlerts =
@@ -484,7 +477,7 @@ public class LocationManagerService extends ILocationManager.Stub
// Attempt to load "real" providers first
if (GpsLocationProvider.isSupported()) {
// Create a gps location provider
- mGpsLocationProvider = new GpsLocationProvider(mContext);
+ mGpsLocationProvider = new GpsLocationProvider(mContext, this);
LocationProviderImpl.addProvider(mGpsLocationProvider);
}
@@ -518,7 +511,7 @@ public class LocationManagerService extends ILocationManager.Stub
File propertiesFile = new File(subdirs[i], "properties");
if (propertiesFile.exists()) {
- provider = new TrackProvider(name);
+ provider = new TrackProvider(name, this);
((TrackProvider)provider).readProperties(propertiesFile);
File kmlFile = new File(subdirs[i], "kml");
@@ -885,14 +878,6 @@ public class LocationManagerService extends ILocationManager.Stub
p.disable();
updateWakelockStatusLocked(mScreenOn);
}
-
- if (enabled && listeners > 0) {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
- Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
- mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
- } else {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
- }
}
private long getMinTimeLocked(String provider) {
@@ -1059,11 +1044,6 @@ public class LocationManagerService extends ILocationManager.Stub
updateReportedGpsLocked();
}
}
-
- // Clear heartbeats if any before starting a new one
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
- Message m = Message.obtain(mLocationHandler, MESSAGE_HEARTBEAT, provider);
- mLocationHandler.sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
} else {
try {
// Notify the listener that updates are currently disabled
@@ -1162,7 +1142,6 @@ public class LocationManagerService extends ILocationManager.Stub
if (hasOtherListener) {
p.setMinTime(getMinTimeLocked(provider));
} else {
- mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider);
p.enableLocationTracking(false);
}
@@ -1522,6 +1501,12 @@ public class LocationManagerService extends ILocationManager.Stub
}
}
+ public void setLocation(Location location) {
+ mLocationHandler.removeMessages(MESSAGE_LOCATION_CHANGED, location);
+ Message m = Message.obtain(mLocationHandler, MESSAGE_LOCATION_CHANGED, location);
+ mLocationHandler.sendMessageAtFrontOfQueue(m);
+ }
+
private boolean _isProviderEnabledLocked(String provider) {
checkPermissionsSafe(provider);
@@ -1592,7 +1577,8 @@ public class LocationManagerService extends ILocationManager.Stub
return true;
}
- private void handleLocationChangedLocked(String provider) {
+ private void handleLocationChangedLocked(Location location) {
+ String provider = location.getProvider();
ArrayList records = mRecordsByProvider.get(provider);
if (records == null || records.size() == 0) {
return;
@@ -1603,40 +1589,19 @@ public class LocationManagerService extends ILocationManager.Stub
return;
}
- // Get location object
- Location loc = mLocationsByProvider.get(provider);
- if (loc == null) {
- loc = new Location(provider);
- mLocationsByProvider.put(provider, loc);
- } else {
- loc.reset();
- }
-
- boolean locationValid;
-
- // Use the mock location if available
- MockProvider mockProvider = mMockProviders.get(provider);
- if (mockProvider != null && mockProvider.getLocation(loc)) {
- locationValid = true;
- } else {
- locationValid = p.getLocation(loc);
- }
-
// Update last known location for provider
- if (locationValid) {
- Location location = mLastKnownLocation.get(provider);
- if (location == null) {
- mLastKnownLocation.put(provider, new Location(loc));
- } else {
- location.set(loc);
- }
- writeLastKnownLocationLocked(provider, loc);
+ Location lastLocation = mLastKnownLocation.get(provider);
+ if (lastLocation == null) {
+ mLastKnownLocation.put(provider, new Location(location));
+ } else {
+ lastLocation.set(location);
+ }
+ writeLastKnownLocationLocked(provider, location);
- if (p instanceof INetworkLocationProvider) {
- mWakeLockNetworkReceived = true;
- } else if (p instanceof GpsLocationProvider) {
- // Gps location received signal is in NetworkStateBroadcastReceiver
- }
+ if (p instanceof INetworkLocationProvider) {
+ mWakeLockNetworkReceived = true;
+ } else if (p instanceof GpsLocationProvider) {
+ // Gps location received signal is in NetworkStateBroadcastReceiver
}
// Fetch latest status update time
@@ -1646,13 +1611,6 @@ public class LocationManagerService extends ILocationManager.Stub
Bundle extras = new Bundle();
int status = p.getStatus(extras);
- // Override with mock values if mock provider is present
- if (mockProvider != null) {
- status = mockProvider.overrideStatus(status);
- newStatusUpdateTime = mockProvider.overrideStatusUpdateTime(newStatusUpdateTime);
- mockProvider.overrideExtras(extras);
- }
-
ArrayList deadReceivers = null;
// Broadcast location or status to all listeners
@@ -1661,28 +1619,25 @@ public class LocationManagerService extends ILocationManager.Stub
UpdateRecord r = records.get(i);
Receiver receiver = r.mReceiver;
- // Broadcast location only if it is valid
- if (locationValid) {
- HashMap map = mLastFixBroadcast.get(receiver);
- if (map == null) {
- map = new HashMap();
- mLastFixBroadcast.put(receiver, map);
+ HashMap map = mLastFixBroadcast.get(receiver);
+ if (map == null) {
+ map = new HashMap();
+ mLastFixBroadcast.put(receiver, map);
+ }
+ Location lastLoc = map.get(provider);
+ if ((lastLoc == null) || shouldBroadcastSafe(location, lastLoc, r)) {
+ if (lastLoc == null) {
+ lastLoc = new Location(location);
+ map.put(provider, lastLoc);
+ } else {
+ lastLoc.set(location);
}
- Location lastLoc = map.get(provider);
- if ((lastLoc == null) || shouldBroadcastSafe(loc, lastLoc, r)) {
- if (lastLoc == null) {
- lastLoc = new Location(loc);
- map.put(provider, lastLoc);
- } else {
- lastLoc.set(loc);
- }
- if (!receiver.callLocationChangedLocked(loc)) {
- Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
- if (deadReceivers == null) {
- deadReceivers = new ArrayList();
- }
- deadReceivers.add(receiver);
+ if (!receiver.callLocationChangedLocked(location)) {
+ Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver);
+ if (deadReceivers == null) {
+ deadReceivers = new ArrayList();
}
+ deadReceivers.add(receiver);
}
}
@@ -1723,25 +1678,19 @@ public class LocationManagerService extends ILocationManager.Stub
@Override
public void handleMessage(Message msg) {
try {
- if (msg.what == MESSAGE_HEARTBEAT) {
- // log("LocationWorkerHandler: Heartbeat!");
+ if (msg.what == MESSAGE_LOCATION_CHANGED) {
+ // log("LocationWorkerHandler: MESSAGE_LOCATION_CHANGED!");
synchronized (mLocationListeners) {
- String provider = (String) msg.obj;
+ Location location = (Location) msg.obj;
+ String provider = location.getProvider();
if (!isAllowedBySettingsLocked(provider)) {
return;
}
// Process the location fix if the screen is on or we're holding a wakelock
if (mScreenOn || (mWakeLockAcquireTime != 0)) {
- handleLocationChangedLocked(provider);
- }
-
- // If it continues to have listeners
- ArrayList records = mRecordsByProvider.get(provider);
- if (records != null && records.size() > 0) {
- Message m = Message.obtain(this, MESSAGE_HEARTBEAT, provider);
- sendMessageAtTime(m, SystemClock.uptimeMillis() + 1000);
+ handleLocationChangedLocked(location);
}
if ((mWakeLockAcquireTime != 0) &&
@@ -2386,7 +2335,8 @@ public class LocationManagerService extends ILocationManager.Stub
checkMockPermissionsSafe();
synchronized (mLocationListeners) {
- MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite,
+ MockProvider provider = new MockProvider(name, this,
+ requiresNetwork, requiresSatellite,
requiresCell, hasMonetaryCost, supportsAltitude,
supportsSpeed, supportsBearing, powerRequirement, accuracy);
if (LocationProviderImpl.getProvider(name) != null) {
@@ -2563,12 +2513,6 @@ public class LocationManagerService extends ILocationManager.Stub
j.dump(pw, " ");
}
}
- pw.println(" Locations by Provider:");
- for (Map.Entry i
- : mLocationsByProvider.entrySet()) {
- pw.println(" " + i.getKey() + ":");
- i.getValue().dump(new PrintWriterPrinter(pw), " ");
- }
pw.println(" Last Known Locations:");
for (Map.Entry i
: mLastKnownLocation.entrySet()) {
diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java
index 00c1ce8b7aa2c..69747d228c413 100644
--- a/test-runner/android/test/TestLocationProvider.java
+++ b/test-runner/android/test/TestLocationProvider.java
@@ -18,6 +18,7 @@ package android.test;
import android.location.Criteria;
+import android.location.ILocationManager;
import android.location.Location;
import android.location.LocationProviderImpl;
import android.os.Bundle;
@@ -36,14 +37,45 @@ public class TestLocationProvider extends LocationProviderImpl {
public static final float SPEED = 10;
public static final float BEARING = 1;
public static final int STATUS = AVAILABLE;
+ private static final long LOCATION_INTERVAL = 1000;
private Location mLocation;
private boolean mEnabled;
+ private TestLocationProviderThread mThread;
- public TestLocationProvider() {
- super(PROVIDER_NAME);
+ private class TestLocationProviderThread extends Thread {
+
+ private boolean mDone = false;
+
+ public TestLocationProviderThread() {
+ super("TestLocationProviderThread");
+ }
+
+ public void run() {
+ // thread exits after disable() is called
+ synchronized (this) {
+ while (!mDone) {
+ try {
+ wait(LOCATION_INTERVAL);
+ } catch (InterruptedException e) {
+ }
+
+ if (!mDone) {
+ TestLocationProvider.this.updateLocation();
+ }
+ }
+ }
+ }
+
+ synchronized void setDone() {
+ mDone = true;
+ notify();
+ }
+ }
+
+ public TestLocationProvider(ILocationManager locationManager) {
+ super(PROVIDER_NAME, locationManager);
mLocation = new Location(PROVIDER_NAME);
- updateLocation();
}
//LocationProvider methods
@@ -95,13 +127,23 @@ public class TestLocationProvider extends LocationProviderImpl {
//LocationProviderImpl methods
@Override
- public void disable() {
+ public synchronized void disable() {
mEnabled = false;
+ if (mThread != null) {
+ mThread.setDone();
+ try {
+ mThread.join();
+ } catch (InterruptedException e) {
+ }
+ mThread = null;
+ }
}
@Override
- public void enable() {
- mEnabled = true;
+ public synchronized void enable() {
+ mEnabled = true;
+ mThread = new TestLocationProviderThread();
+ mThread.start();
}
@Override
@@ -109,13 +151,6 @@ public class TestLocationProvider extends LocationProviderImpl {
return mEnabled;
}
- @Override
- public boolean getLocation(Location l) {
- updateLocation();
- l.set(mLocation);
- return true;
- }
-
@Override
public int getStatus(Bundle extras) {
return STATUS;
@@ -134,6 +169,7 @@ public class TestLocationProvider extends LocationProviderImpl {
extras.putInt("extraTest", 24);
mLocation.setExtras(extras);
mLocation.setTime(time);
+ reportLocationChanged(mLocation);
}
}