diff options
author | Mike Lockwood <lockwood@android.com> | 2009-04-23 09:12:08 -0700 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2009-04-23 19:27:41 -0700 |
commit | 48f17518223a2917fd82195004fbb206cb9a05a3 (patch) | |
tree | d87449f59ab8b22dada31f595c688bcee9bd3961 | |
parent | 0a57e5b730beaea75c1c1b1ca51b40c463918b4d (diff) | |
download | frameworks_base-48f17518223a2917fd82195004fbb206cb9a05a3.zip frameworks_base-48f17518223a2917fd82195004fbb206cb9a05a3.tar.gz frameworks_base-48f17518223a2917fd82195004fbb206cb9a05a3.tar.bz2 |
location: Location Manager wakelock cleanup, phase 2
Remove two second timeout for wakelock when broadcasting events to
location listeners. Instead, hold wakelock until receipt of the event
is acknowledged, either via a Binder call or the
PendingIntent.OnFinished interface.
Signed-off-by: Mike Lockwood <lockwood@android.com>
3 files changed, 176 insertions, 82 deletions
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index 7d35814..096622a 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -45,7 +45,10 @@ interface ILocationManager boolean addGpsStatusListener(IGpsStatusListener listener); void removeGpsStatusListener(IGpsStatusListener listener); - + + // for reporting callback completion + void locationCallbackFinished(ILocationListener listener); + boolean sendExtraCommand(String provider, String command, inout Bundle extras); void addProximityAlert(double latitude, double longitude, float distance, diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 0c7254e..f587f96 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -194,6 +194,11 @@ public class LocationManager { mListener.onProviderDisabled((String) msg.obj); break; } + try { + mService.locationCallbackFinished(this); + } catch (RemoteException e) { + Log.e(TAG, "locationCallbackFinished: RemoteException", e); + } } } /** diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index 5e079d4..2def877 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -93,10 +93,6 @@ public class LocationManagerService extends ILocationManager.Stub { // Max time to hold wake lock for, in milliseconds. private static final long MAX_TIME_FOR_WAKE_LOCK = 60 * 1000L; - // Time to wait after releasing a wake lock for clients to process location update, - // in milliseconds. - private static final long TIME_AFTER_WAKE_LOCK = 2 * 1000L; - // The last time a location was written, by provider name. private HashMap<String,Long> mLastWriteTime = new HashMap<String,Long>(); @@ -130,7 +126,6 @@ public class LocationManagerService extends ILocationManager.Stub { // Handler messages private static final int MESSAGE_LOCATION_CHANGED = 1; - private static final int MESSAGE_RELEASE_WAKE_LOCK = 2; // Alarm manager and wakelock variables private final static String ALARM_INTENT = "com.android.location.ALARM_INTENT"; @@ -138,6 +133,7 @@ public class LocationManagerService extends ILocationManager.Stub { private AlarmManager mAlarmManager; private long mAlarmInterval = 0; private PowerManager.WakeLock mWakeLock = null; + private int mPendingBroadcasts; private long mWakeLockAcquireTime = 0; private boolean mWakeLockGpsReceived = true; private boolean mWakeLockNetworkReceived = true; @@ -159,7 +155,8 @@ public class LocationManagerService extends ILocationManager.Stub { new HashMap<String,ArrayList<UpdateRecord>>(); // Proximity listeners - private Receiver mProximityListener = null; + private Receiver mProximityReceiver = null; + private ILocationListener mProximityListener = null; private HashMap<PendingIntent,ProximityAlert> mProximityAlerts = new HashMap<PendingIntent,ProximityAlert>(); private HashSet<ProximityAlert> mProximitiesEntered = @@ -181,11 +178,12 @@ public class LocationManagerService extends ILocationManager.Stub { * A wrapper class holding either an ILocationListener or a PendingIntent to receive * location updates. */ - private final class Receiver implements IBinder.DeathRecipient { + private final class Receiver implements IBinder.DeathRecipient, PendingIntent.OnFinished { final ILocationListener mListener; final PendingIntent mPendingIntent; final Object mKey; final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>(); + int mPendingBroadcasts; Receiver(ILocationListener listener) { mListener = listener; @@ -252,7 +250,16 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { if (mListener != null) { try { - mListener.onStatusChanged(provider, status, extras); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mListener.onStatusChanged(provider, status, extras); + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } } catch (RemoteException e) { return false; } @@ -261,7 +268,14 @@ public class LocationManagerService extends ILocationManager.Stub { statusChanged.putExtras(extras); statusChanged.putExtra(LocationManager.KEY_STATUS_CHANGED, status); try { - mPendingIntent.send(mContext, 0, statusChanged, null, null); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, statusChanged, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { return false; } @@ -272,7 +286,16 @@ public class LocationManagerService extends ILocationManager.Stub { public boolean callLocationChangedLocked(Location location) { if (mListener != null) { try { - mListener.onLocationChanged(location); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mListener.onLocationChanged(location); + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } } catch (RemoteException e) { return false; } @@ -280,7 +303,53 @@ public class LocationManagerService extends ILocationManager.Stub { Intent locationChanged = new Intent(); locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); try { - mPendingIntent.send(mContext, 0, locationChanged, null, null); + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, locationChanged, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } catch (PendingIntent.CanceledException e) { + return false; + } + } + return true; + } + + public boolean callProviderEnabledLocked(String provider, boolean enabled) { + if (mListener != null) { + try { + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + if (enabled) { + mListener.onProviderEnabled(provider); + } else { + mListener.onProviderDisabled(provider); + } + if (mListener != mProximityListener) { + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } + } + } catch (RemoteException e) { + return false; + } + } else { + Intent providerIntent = new Intent(); + providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); + try { + synchronized (this) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + mPendingIntent.send(mContext, 0, providerIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { return false; } @@ -295,6 +364,42 @@ public class LocationManagerService extends ILocationManager.Stub { synchronized (mLock) { removeUpdatesLocked(this); } + synchronized (this) { + if (mPendingBroadcasts > 0) { + LocationManagerService.this.decrementPendingBroadcasts(); + mPendingBroadcasts = 0; + } + } + } + + public void onSendFinished(PendingIntent pendingIntent, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + decrementPendingBroadcasts(); + } + + // this must be called while synchronized by callerin a synchronized block + // containing the sending of the broadcaset + private void incrementPendingBroadcastsLocked() { + if (mPendingBroadcasts++ == 0) { + synchronized (mLock) { + LocationManagerService.this.incrementPendingBroadcastsLocked(); + } + } + } + + private void decrementPendingBroadcasts() { + synchronized (this) { + if (--mPendingBroadcasts == 0) { + LocationManagerService.this.decrementPendingBroadcasts(); + } + } + } + } + + public void locationCallbackFinished(ILocationListener listener) { + Receiver receiver = getReceiver(listener); + if (receiver != null) { + receiver.decrementPendingBroadcasts(); } } @@ -722,29 +827,11 @@ public class LocationManagerService extends ILocationManager.Stub { for (int i=0; i<N; i++) { UpdateRecord record = records.get(i); // Sends a notification message to the receiver - try { - Receiver receiver = record.mReceiver; - if (receiver.isListener()) { - if (enabled) { - receiver.getListener().onProviderEnabled(provider); - } else { - receiver.getListener().onProviderDisabled(provider); - } - } else { - Intent providerIntent = new Intent(); - providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); - try { - receiver.getPendingIntent().send(mContext, 0, - providerIntent, null, null); - } catch (PendingIntent.CanceledException e) { - if (deadReceivers == null) { - deadReceivers = new ArrayList<Receiver>(); - deadReceivers.add(receiver); - } - } + if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) { + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + deadReceivers.add(record.mReceiver); } - } catch (RemoteException e) { - // The death link will clean this up. } listeners++; } @@ -958,15 +1045,8 @@ public class LocationManagerService extends ILocationManager.Stub { impl.enableLocationTracking(true); updateWakelockStatusLocked(); } else { - try { - // Notify the listener that updates are currently disabled - if (receiver.isListener()) { - receiver.getListener().onProviderDisabled(provider); - } - } catch(RemoteException e) { - Log.w(TAG, "RemoteException calling onProviderDisabled on " + - receiver.getListener()); - } + // Notify the listener that updates are currently disabled + receiver.callProviderEnabledLocked(provider, false); } } finally { Binder.restoreCallingIdentity(identity); @@ -1161,7 +1241,7 @@ public class LocationManagerService extends ILocationManager.Stub { } // Listener for receiving locations to trigger proximity alerts - class ProximityListener extends ILocationListener.Stub { + class ProximityListener extends ILocationListener.Stub implements PendingIntent.OnFinished { boolean isGpsAvailable = false; @@ -1198,7 +1278,14 @@ public class LocationManagerService extends ILocationManager.Stub { Intent enteredIntent = new Intent(); enteredIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, true); try { - intent.send(mContext, 0, enteredIntent, null, null); + synchronized (mLock) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + intent.send(mContext, 0, enteredIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { if (LOCAL_LOGV) { Log.v(TAG, "Canceled proximity alert: " + alert, e); @@ -1216,7 +1303,14 @@ public class LocationManagerService extends ILocationManager.Stub { Intent exitedIntent = new Intent(); exitedIntent.putExtra(LocationManager.KEY_PROXIMITY_ENTERING, false); try { - intent.send(mContext, 0, exitedIntent, null, null); + synchronized (mLock) { + // synchronize to ensure incrementPendingBroadcastsLocked() + // is called before decrementPendingBroadcasts() + intent.send(mContext, 0, exitedIntent, this, mLocationHandler); + // call this after broadcasting so we do not increment + // if we throw an exeption. + incrementPendingBroadcastsLocked(); + } } catch (PendingIntent.CanceledException e) { if (LOCAL_LOGV) { Log.v(TAG, "Canceled proximity alert: " + alert, e); @@ -1269,6 +1363,11 @@ public class LocationManagerService extends ILocationManager.Stub { isGpsAvailable = false; } } + + public void onSendFinished(PendingIntent pendingIntent, Intent intent, + int resultCode, String resultData, Bundle resultExtras) { + decrementPendingBroadcasts(); + } } public void addProximityAlert(double latitude, double longitude, @@ -1306,19 +1405,20 @@ public class LocationManagerService extends ILocationManager.Stub { latitude, longitude, radius, expiration, intent); mProximityAlerts.put(intent, alert); - if (mProximityListener == null) { - mProximityListener = new Receiver(new ProximityListener()); + if (mProximityReceiver == null) { + mProximityListener = new ProximityListener(); + mProximityReceiver = new Receiver(mProximityListener); LocationProvider provider = LocationProviderImpl.getProvider( LocationManager.GPS_PROVIDER); if (provider != null) { - requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); } provider = LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER); if (provider != null) { - requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityReceiver); } } } @@ -1342,7 +1442,8 @@ public class LocationManagerService extends ILocationManager.Stub { mProximityAlerts.remove(intent); if (mProximityAlerts.size() == 0) { - removeUpdatesLocked(mProximityListener); + removeUpdatesLocked(mProximityReceiver); + mProximityReceiver = null; mProximityListener = null; } } @@ -1585,35 +1686,7 @@ public class LocationManagerService extends ILocationManager.Stub { } handleLocationChangedLocked(location); - - if ((mWakeLockAcquireTime != 0) && - (SystemClock.elapsedRealtime() - mWakeLockAcquireTime - > MAX_TIME_FOR_WAKE_LOCK)) { - - removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - - log("LocationWorkerHandler: Exceeded max time for wake lock"); - Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); - sendMessageAtFrontOfQueue(m); - - } else if (mWakeLockAcquireTime != 0 && - mWakeLockGpsReceived && mWakeLockNetworkReceived) { - - removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - - log("LocationWorkerHandler: Locations received."); - mWakeLockAcquireTime = 0; - Message m = Message.obtain(this, MESSAGE_RELEASE_WAKE_LOCK); - sendMessageDelayed(m, TIME_AFTER_WAKE_LOCK); - } - } - } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) { - log("LocationWorkerHandler: Release"); - - // Update wakelock status so the next alarm is set before releasing wakelock - synchronized (mLock) { updateWakelockStatusLocked(); - releaseWakeLockLocked(); } } } catch (Exception e) { @@ -1727,7 +1800,7 @@ public class LocationManagerService extends ILocationManager.Stub { long callerId = Binder.clearCallingIdentity(); - boolean needsLock = false; + boolean needsLock = (mPendingBroadcasts > 0); long minTime = Integer.MAX_VALUE; if (mNetworkLocationProvider != null && mNetworkLocationProvider.isLocationTracking()) { @@ -1757,8 +1830,6 @@ public class LocationManagerService extends ILocationManager.Stub { log("No need for alarm"); mAlarmInterval = -1; - // Clear out existing wakelocks - mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK); releaseWakeLockLocked(); } Binder.restoreCallingIdentity(callerId); @@ -1836,6 +1907,20 @@ public class LocationManagerService extends ILocationManager.Stub { } } + private void incrementPendingBroadcastsLocked() { + if (mPendingBroadcasts++ == 0) { + updateWakelockStatusLocked(); + } + } + + private void decrementPendingBroadcasts() { + synchronized (mLock) { + if (--mPendingBroadcasts == 0) { + updateWakelockStatusLocked(); + } + } + } + // Geocoder public String getFromLocation(double latitude, double longitude, int maxResults, @@ -2061,6 +2146,7 @@ public class LocationManagerService extends ILocationManager.Stub { i.dump(pw, " "); } } + pw.println(" mProximityReceiver=" + mProximityReceiver); pw.println(" mProximityListener=" + mProximityListener); if (mEnabledProviders.size() > 0) { pw.println(" Enabled Providers:"); |