diff options
8 files changed, 179 insertions, 220 deletions
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index d0f9877..a7fb04d 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<Address> addrs); diff --git a/location/java/android/location/LocationProviderImpl.java b/location/java/android/location/LocationProviderImpl.java index 0962992..bb225e2 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<String, LocationProviderImpl> sProvidersByName = new HashMap<String, LocationProviderImpl>(); + 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(); @@ -175,15 +186,6 @@ public abstract class LocationProviderImpl extends LocationProvider { } /** - * 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 * called with enable set to false when the last client is removed. diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java index f595050..d09318a 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 @@ -449,19 +450,6 @@ public class GpsLocationProvider extends LocationProviderImpl { } @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) { return; @@ -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 730cb48..f8947a6 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 bd5cdd8..c8d5b4f 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; @@ -74,15 +76,6 @@ public class MockProvider extends LocationProviderImpl { } @Override - public boolean getLocation(Location l) { - if (mHasLocation) { - l.set(mLocation); - return true; - } - return false; - } - - @Override public int getStatus(Bundle extras) { if (mHasStatus) { extras.clear(); @@ -94,6 +87,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 545d7dc..1686260 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<Waypoint> 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 f3187d7..952fdc5 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<String,ArrayList<UpdateRecord>> mRecordsByProvider = new HashMap<String,ArrayList<UpdateRecord>>(); - /** - * Mappings from provider name to object to use for current location. Locations - * contained in this list may not always be valid. - */ - private final HashMap<String,Location> mLocationsByProvider = - new HashMap<String,Location>(); - // Proximity listeners private Receiver mProximityListener = null; private HashMap<PendingIntent,ProximityAlert> 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<UpdateRecord> 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; + // Update last known location for provider + Location lastLocation = mLastKnownLocation.get(provider); + if (lastLocation == null) { + mLastKnownLocation.put(provider, new Location(location)); } else { - locationValid = p.getLocation(loc); + lastLocation.set(location); } + writeLastKnownLocationLocked(provider, location); - // 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); - - 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<Receiver> 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<String,Location> map = mLastFixBroadcast.get(receiver); - if (map == null) { - map = new HashMap<String,Location>(); - mLastFixBroadcast.put(receiver, map); + HashMap<String,Location> map = mLastFixBroadcast.get(receiver); + if (map == null) { + map = new HashMap<String,Location>(); + 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<Receiver>(); - } - deadReceivers.add(receiver); + if (!receiver.callLocationChangedLocked(location)) { + Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver); + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); } + 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<UpdateRecord> 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<String, Location> i - : mLocationsByProvider.entrySet()) { - pw.println(" " + i.getKey() + ":"); - i.getValue().dump(new PrintWriterPrinter(pw), " "); - } pw.println(" Last Known Locations:"); for (Map.Entry<String, Location> i : mLastKnownLocation.entrySet()) { diff --git a/test-runner/android/test/TestLocationProvider.java b/test-runner/android/test/TestLocationProvider.java index 00c1ce8..69747d2 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; - - public TestLocationProvider() { - super(PROVIDER_NAME); + private TestLocationProviderThread mThread; + + 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 @@ -110,13 +152,6 @@ public class TestLocationProvider extends LocationProviderImpl { } @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); } } |