diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-02-19 10:57:31 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-02-19 10:57:31 -0800 |
commit | 3001a035439d8134a7d70d796376d1dfbff3cdcd (patch) | |
tree | 343ccdba15a594ff6e50c874a145232753315a30 /services | |
parent | da996f390e17e16f2dfa60e972e7ebc4f868f37e (diff) | |
download | frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.zip frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.gz frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.bz2 |
auto import from //branches/cupcake/...@132276
Diffstat (limited to 'services')
13 files changed, 1305 insertions, 654 deletions
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java index e4fdd0c..9c9a580 100644 --- a/services/java/com/android/server/BatteryService.java +++ b/services/java/com/android/server/BatteryService.java @@ -121,9 +121,10 @@ class BatteryService extends Binder { } int plugTypeBit = 0; if (mAcOnline) { - plugTypeBit = BatteryManager.BATTERY_PLUGGED_AC; - } else if (mUsbOnline) { - plugTypeBit = BatteryManager.BATTERY_PLUGGED_USB; + plugTypeBit |= BatteryManager.BATTERY_PLUGGED_AC; + } + if (mUsbOnline) { + plugTypeBit |= BatteryManager.BATTERY_PLUGGED_USB; } return (plugTypeSet & plugTypeBit) != 0; } diff --git a/services/java/com/android/server/DeviceStorageMonitorService.java b/services/java/com/android/server/DeviceStorageMonitorService.java index 44f70f0..85861bb 100644 --- a/services/java/com/android/server/DeviceStorageMonitorService.java +++ b/services/java/com/android/server/DeviceStorageMonitorService.java @@ -67,6 +67,7 @@ class DeviceStorageMonitorService extends Binder { private static final int EVENT_LOG_LOW_STORAGE_NOTIFICATION = 2745; private static final int EVENT_LOG_FREE_STORAGE_LEFT = 2746; private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB + private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000; private long mFreeMem; private long mLastReportedFreeMem; private long mLastReportedFreeMemTime; @@ -82,6 +83,9 @@ class DeviceStorageMonitorService extends Binder { boolean mClearingCache; private Intent mStorageLowIntent; private Intent mStorageOkIntent; + private CachePackageDataObserver mClearCacheObserver; + private static final int _TRUE = 1; + private static final int _FALSE = 0; /** * This string is used for ServiceManager access to this class. @@ -100,7 +104,7 @@ class DeviceStorageMonitorService extends Binder { Log.e(TAG, "Will not process invalid message"); return; } - checkMemory(); + checkMemory(msg.arg1 == _TRUE); } }; @@ -109,7 +113,8 @@ class DeviceStorageMonitorService extends Binder { mClearSucceeded = succeeded; mClearingCache = false; if(localLOGV) Log.i(TAG, " Clear succeeded:"+mClearSucceeded - +", mClearingCache:"+mClearingCache); + +", mClearingCache:"+mClearingCache+" Forcing memory check"); + postCheckMemoryMsg(false, 0); } } @@ -145,11 +150,15 @@ class DeviceStorageMonitorService extends Binder { } private final void clearCache() { - CachePackageDataObserver observer = new CachePackageDataObserver(); + if (mClearCacheObserver == null) { + // Lazy instantiation + mClearCacheObserver = new CachePackageDataObserver(); + } mClearingCache = true; try { + if (localLOGV) Log.i(TAG, "Clearing cache"); IPackageManager.Stub.asInterface(ServiceManager.getService("package")). - freeStorageAndNotify(getMemThreshold(), observer); + freeStorageAndNotify(getMemThreshold(), mClearCacheObserver); } catch (RemoteException e) { Log.w(TAG, "Failed to get handle for PackageManger Exception: "+e); mClearingCache = false; @@ -157,7 +166,7 @@ class DeviceStorageMonitorService extends Binder { } } - private final void checkMemory() { + private final void checkMemory(boolean checkCache) { //if the thread that was started to clear cache is still running do nothing till its //finished clearing cache. Ideally this flag could be modified by clearCache // and should be accessed via a lock but even if it does this test will fail now and @@ -172,16 +181,23 @@ class DeviceStorageMonitorService extends Binder { } else { restatDataDir(); if (localLOGV) Log.v(TAG, "freeMemory="+mFreeMem); + //post intent to NotificationManager to display icon if necessary long memThreshold = getMemThreshold(); if (mFreeMem < memThreshold) { if (!mLowMemFlag) { - //see if clearing cache helps - mThreadStartTime = System.currentTimeMillis(); - clearCache(); - Log.i(TAG, "Running low on memory. Sending notification"); - sendNotification(); - mLowMemFlag = true; + if (checkCache) { + // See if clearing cache helps + // Note that clearing cache is asynchronous and so we do a + // memory check again once the cache has been cleared. + mThreadStartTime = System.currentTimeMillis(); + mClearSucceeded = false; + clearCache(); + } else { + Log.i(TAG, "Running low on memory. Sending notification"); + sendNotification(); + mLowMemFlag = true; + } } else { if (localLOGV) Log.v(TAG, "Running low on memory " + "notification already sent. do nothing"); @@ -196,8 +212,15 @@ class DeviceStorageMonitorService extends Binder { } if(localLOGV) Log.i(TAG, "Posting Message again"); //keep posting messages to itself periodically - mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT), - MONITOR_INTERVAL*60*1000); + postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL); + } + + private void postCheckMemoryMsg(boolean clearCache, long delay) { + // Remove queued messages + mHandler.removeMessages(DEVICE_MEMORY_WHAT); + mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT, + clearCache ?_TRUE : _FALSE, 0), + delay); } /* @@ -231,7 +254,7 @@ class DeviceStorageMonitorService extends Binder { mTotalMemory = (mFileStats.getBlockCount()*mBlkSize)/100; mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW); mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK); - checkMemory(); + checkMemory(true); } @@ -281,14 +304,11 @@ class DeviceStorageMonitorService extends Binder { } public void updateMemory() { - ActivityManagerService ams = (ActivityManagerService)ServiceManager.getService("activity"); int callingUid = getCallingUid(); if(callingUid != Process.SYSTEM_UID) { return; } - //remove queued messages - mHandler.removeMessages(DEVICE_MEMORY_WHAT); - //force an early check - checkMemory(); + // force an early check + postCheckMemoryMsg(true, 0); } } diff --git a/services/java/com/android/server/GadgetService.java b/services/java/com/android/server/GadgetService.java index ddf3afe..4a430e0 100644 --- a/services/java/com/android/server/GadgetService.java +++ b/services/java/com/android/server/GadgetService.java @@ -38,7 +38,6 @@ import android.os.Bundle; import android.os.RemoteException; import android.os.SystemClock; import android.util.AttributeSet; -import android.util.Config; import android.util.Log; import android.util.Xml; import android.widget.RemoteViews; @@ -66,7 +65,6 @@ import org.xmlpull.v1.XmlSerializer; class GadgetService extends IGadgetService.Stub { private static final String TAG = "GadgetService"; - private static final boolean LOGD = Config.LOGD || false; private static final String SETTINGS_FILENAME = "gadgets.xml"; private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp"; @@ -82,6 +80,7 @@ class GadgetService extends IGadgetService.Stub GadgetProviderInfo info; ArrayList<GadgetId> instances = new ArrayList(); PendingIntent broadcast; + boolean zombie; // if we're in safe mode, don't prune this just because nobody references it int tag; // for use while saving state (the index) } @@ -92,6 +91,7 @@ class GadgetService extends IGadgetService.Stub String packageName; ArrayList<GadgetId> instances = new ArrayList(); IGadgetHost callbacks; + boolean zombie; // if we're in safe mode, don't prune this just because nobody references it int tag; // for use while saving state (the index) } @@ -110,13 +110,18 @@ class GadgetService extends IGadgetService.Stub int mNextGadgetId = GadgetManager.INVALID_GADGET_ID + 1; ArrayList<GadgetId> mGadgetIds = new ArrayList(); ArrayList<Host> mHosts = new ArrayList(); + boolean mSafeMode; GadgetService(Context context) { mContext = context; mPackageManager = context.getPackageManager(); mAlarmManager = (AlarmManager)mContext.getSystemService(Context.ALARM_SERVICE); - - getGadgetList(); + } + + public void systemReady(boolean safeMode) { + mSafeMode = safeMode; + + loadGadgetList(); loadStateLocked(); // Register for the boot completed broadcast, so we can send the @@ -148,11 +153,12 @@ class GadgetService extends IGadgetService.Stub int N = mInstalledProviders.size(); pw.println("Providers: (size=" + N + ")"); for (int i=0; i<N; i++) { - GadgetProviderInfo info = mInstalledProviders.get(i).info; + Provider p = mInstalledProviders.get(i); + GadgetProviderInfo info = p.info; pw.println(" [" + i + "] provder=" + info.provider + " min=(" + info.minWidth + "x" + info.minHeight + ")" + " updatePeriodMillis=" + info.updatePeriodMillis - + " initialLayout=" + info.initialLayout); + + " initialLayout=" + info.initialLayout + " zombie=" + p.zombie); } N = mGadgetIds.size(); @@ -172,7 +178,7 @@ class GadgetService extends IGadgetService.Stub Host host = mHosts.get(i); pw.println(" [" + i + "] packageName=" + host.packageName + " uid=" + host.uid + " hostId=" + host.hostId + " callbacks=" + host.callbacks - + " instances.size=" + host.instances.size()); + + " instances.size=" + host.instances.size() + " zombie=" + host.zombie); } } } @@ -199,16 +205,10 @@ class GadgetService extends IGadgetService.Stub public void deleteGadgetId(int gadgetId) { synchronized (mGadgetIds) { - int callingUid = getCallingUid(); - final int N = mGadgetIds.size(); - for (int i=0; i<N; i++) { - GadgetId id = mGadgetIds.get(i); - if (id.provider != null && canAccessGadgetId(id, callingUid)) { - deleteGadgetLocked(id); - - saveStateLocked(); - return; - } + GadgetId id = lookupGadgetIdLocked(gadgetId); + if (id != null) { + deleteGadgetLocked(id); + saveStateLocked(); } } } @@ -264,19 +264,21 @@ class GadgetService extends IGadgetService.Stub Provider p = id.provider; if (p != null) { p.instances.remove(id); - // send the broacast saying that this gadgetId has been deleted - Intent intent = new Intent(GadgetManager.ACTION_GADGET_DELETED); - intent.setComponent(p.info.provider); - intent.putExtra(GadgetManager.EXTRA_GADGET_ID, id.gadgetId); - mContext.sendBroadcast(intent); - if (p.instances.size() == 0) { - // cancel the future updates - cancelBroadcasts(p); - - // send the broacast saying that the provider is not in use any more - intent = new Intent(GadgetManager.ACTION_GADGET_DISABLED); + if (!p.zombie) { + // send the broacast saying that this gadgetId has been deleted + Intent intent = new Intent(GadgetManager.ACTION_GADGET_DELETED); intent.setComponent(p.info.provider); + intent.putExtra(GadgetManager.EXTRA_GADGET_ID, id.gadgetId); mContext.sendBroadcast(intent); + if (p.instances.size() == 0) { + // cancel the future updates + cancelBroadcasts(p); + + // send the broacast saying that the provider is not in use any more + intent = new Intent(GadgetManager.ACTION_GADGET_DISABLED); + intent.setComponent(p.info.provider); + mContext.sendBroadcast(intent); + } } } } @@ -310,6 +312,10 @@ class GadgetService extends IGadgetService.Stub if (p == null) { throw new IllegalArgumentException("not a gadget provider: " + provider); } + if (p.zombie) { + throw new IllegalArgumentException("can't bind to a 3rd party provider in" + + " safe mode: " + provider); + } id.provider = p; p.instances.add(id); @@ -334,7 +340,7 @@ class GadgetService extends IGadgetService.Stub public GadgetProviderInfo getGadgetInfo(int gadgetId) { synchronized (mGadgetIds) { GadgetId id = lookupGadgetIdLocked(gadgetId); - if (id != null) { + if (id != null && id.provider != null && !id.provider.zombie) { return id.provider.info; } return null; @@ -356,7 +362,10 @@ class GadgetService extends IGadgetService.Stub final int N = mInstalledProviders.size(); ArrayList<GadgetProviderInfo> result = new ArrayList(N); for (int i=0; i<N; i++) { - result.add(mInstalledProviders.get(i).info); + Provider p = mInstalledProviders.get(i); + if (!p.zombie) { + result.add(p.info); + } } return result; } @@ -399,7 +408,7 @@ class GadgetService extends IGadgetService.Stub // allow for stale gadgetIds and other badness // lookup also checks that the calling process can access the gadget id // drop unbound gadget ids (shouldn't be possible under normal circumstances) - if (id != null && id.provider != null) { + if (id != null && id.provider != null && !id.provider.zombie && !id.host.zombie) { id.views = views; // is anyone listening? @@ -460,9 +469,7 @@ class GadgetService extends IGadgetService.Stub return true; } // Nobody else can access it. - // TODO: convert callingPackage over to use UID-based checking instead - // TODO: our temp solution is to short-circuit this security check - return true; + return false; } GadgetId lookupGadgetIdLocked(int gadgetId) { @@ -521,7 +528,7 @@ class GadgetService extends IGadgetService.Stub } } - void getGadgetList() { + void loadGadgetList() { PackageManager pm = mPackageManager; Intent intent = new Intent(GadgetManager.ACTION_GADGET_UPDATE); @@ -854,8 +861,16 @@ class GadgetService extends IGadgetService.Stub String pkg = parser.getAttributeValue(null, "pkg"); String cl = parser.getAttributeValue(null, "cl"); Provider p = lookupProviderLocked(new ComponentName(pkg, cl)); - // if it wasn't uninstalled or something + if (p == null && mSafeMode) { + // if we're in safe mode, make a temporary one + p = new Provider(); + p.info = new GadgetProviderInfo(); + p.info.provider = new ComponentName(pkg, cl); + p.zombie = true; + mInstalledProviders.add(p); + } if (p != null) { + // if it wasn't uninstalled or something loadedProviders.put(providerIndex, p); } providerIndex++; @@ -868,13 +883,15 @@ class GadgetService extends IGadgetService.Stub host.packageName = parser.getAttributeValue(null, "pkg"); try { host.uid = getUidForPackage(host.packageName); + } catch (PackageManager.NameNotFoundException ex) { + host.zombie = true; + } + if (!host.zombie || mSafeMode) { + // In safe mode, we don't discard the hosts we don't recognize + // so that they're not pruned from our list. Otherwise, we do. host.hostId = Integer.parseInt( parser.getAttributeValue(null, "id"), 16); mHosts.add(host); - } catch (PackageManager.NameNotFoundException ex) { - // Just ignore drop this entry, as if it has been uninstalled. - // We need to deal with this case because of safe mode, but there's - // a bug filed about it. } } else if ("g".equals(tag)) { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 7588129..4b45828 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1062,6 +1062,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Do nothing. break; case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN: + if ((softInputMode & + WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { + if (DEBUG) Log.v(TAG, "Window asks to hide input going forward"); + hideCurrentInputLocked(0); + } + break; + case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN: if (DEBUG) Log.v(TAG, "Window asks to hide input"); hideCurrentInputLocked(0); break; diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java index db4daa5..bc8da93 100644 --- a/services/java/com/android/server/LocationManagerService.java +++ b/services/java/com/android/server/LocationManagerService.java @@ -18,14 +18,16 @@ package com.android.server; import java.io.BufferedReader; import java.io.File; +import java.io.FileDescriptor; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.regex.Pattern; @@ -46,6 +48,7 @@ import android.location.LocationManager; import android.location.LocationProvider; import android.location.LocationProviderImpl; import android.net.ConnectivityManager; +import android.net.Uri; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.os.Binder; @@ -57,12 +60,13 @@ import android.os.PowerManager; import android.os.RemoteException; import android.os.SystemClock; import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; import android.telephony.CellLocation; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Config; import android.util.Log; +import android.util.PrintWriterPrinter; +import android.util.SparseIntArray; import com.android.internal.app.IBatteryStats; import com.android.internal.location.CellState; @@ -124,6 +128,7 @@ public class LocationManagerService extends ILocationManager.Stub private final Context mContext; private GpsLocationProvider mGpsLocationProvider; + private boolean mGpsNavigating; private LocationProviderImpl mNetworkLocationProvider; private INetworkLocationProvider mNetworkLocationInterface; private LocationWorkerHandler mLocationHandler; @@ -151,35 +156,38 @@ public class LocationManagerService extends ILocationManager.Stub private final IBatteryStats mBatteryStats; - // The calling UID when we are in a clearCallingIdentity/restoreCallingIdentity block, or -1 - private int mCallingUid = -1; - /** * Mapping from listener IBinder/PendingIntent to local Listener wrappers. */ - private final HashMap<Object,Receiver> mListeners = - new HashMap<Object,Receiver>(); + private final ArrayList<Receiver> mListeners = new ArrayList<Receiver>(); /** + * Used for reporting which UIDs are causing the GPS to run. + */ + private final SparseIntArray mReportedGpsUids = new SparseIntArray(); + private int mReportedGpsSeq = 0; + + /** * Mapping from listener IBinder/PendingIntent to a map from provider name to UpdateRecord. + * This also serves as the lock for our state. */ - private final HashMap<Object,HashMap<String,UpdateRecord>> mLocationListeners = - new HashMap<Object,HashMap<String,UpdateRecord>>(); + private final HashMap<Receiver,HashMap<String,UpdateRecord>> mLocationListeners = + new HashMap<Receiver,HashMap<String,UpdateRecord>>(); /** * Mapping from listener IBinder/PendingIntent to a map from provider name to last broadcast * location. */ - private final HashMap<Object,HashMap<String,Location>> mLastFixBroadcast = - new HashMap<Object,HashMap<String,Location>>(); - private final HashMap<Object,HashMap<String,Long>> mLastStatusBroadcast = - new HashMap<Object,HashMap<String,Long>>(); + private final HashMap<Receiver,HashMap<String,Location>> mLastFixBroadcast = + new HashMap<Receiver,HashMap<String,Location>>(); + private final HashMap<Receiver,HashMap<String,Long>> mLastStatusBroadcast = + new HashMap<Receiver,HashMap<String,Long>>(); /** * Mapping from provider name to all its UpdateRecords */ - private final HashMap<String,HashSet<UpdateRecord>> mRecordsByProvider = - new HashMap<String,HashSet<UpdateRecord>>(); + private final HashMap<String,ArrayList<UpdateRecord>> mRecordsByProvider = + new HashMap<String,ArrayList<UpdateRecord>>(); /** * Mappings from provider name to object to use for current location. Locations @@ -221,22 +229,48 @@ public class LocationManagerService extends ILocationManager.Stub private final class Receiver implements IBinder.DeathRecipient { final ILocationListener mListener; final PendingIntent mPendingIntent; + final int mUid; + final Object mKey; - Receiver(ILocationListener listener) { + Receiver(ILocationListener listener, int uid) { mListener = listener; mPendingIntent = null; + mUid = uid; + mKey = listener.asBinder(); } - Receiver(PendingIntent intent) { + Receiver(PendingIntent intent, int uid) { mPendingIntent = intent; mListener = null; + mUid = uid; + mKey = intent; } - public Object getKey() { + @Override + public boolean equals(Object otherObj) { + if (otherObj instanceof Receiver) { + return mKey.equals( + ((Receiver)otherObj).mKey); + } + return false; + } + + @Override + public int hashCode() { + return mKey.hashCode(); + } + + + @Override + public String toString() { if (mListener != null) { - return mListener.asBinder(); + return "Receiver{" + + Integer.toHexString(System.identityHashCode(this)) + + " uid " + mUid + " Listener " + mKey + "}"; } else { - return mPendingIntent; + return "Receiver{" + + Integer.toHexString(System.identityHashCode(this)) + + " uid " + mUid + " Intent " + mKey + "}"; } } @@ -262,10 +296,13 @@ public class LocationManagerService extends ILocationManager.Stub throw new IllegalStateException("Request for non-existent intent"); } - public void onStatusChanged(String provider, int status, Bundle extras) - throws RemoteException { + public boolean callStatusChangedLocked(String provider, int status, Bundle extras) { if (mListener != null) { - mListener.onStatusChanged(provider, status, extras); + try { + mListener.onStatusChanged(provider, status, extras); + } catch (RemoteException e) { + return false; + } } else { Intent statusChanged = new Intent(); statusChanged.putExtras(extras); @@ -273,23 +310,29 @@ public class LocationManagerService extends ILocationManager.Stub try { mPendingIntent.send(mContext, 0, statusChanged, null, null); } catch (PendingIntent.CanceledException e) { - _removeUpdates(this); + return false; } } + return true; } - public void onLocationChanged(Location location) throws RemoteException { + public boolean callLocationChangedLocked(Location location) { if (mListener != null) { - mListener.onLocationChanged(location); + try { + mListener.onLocationChanged(location); + } catch (RemoteException e) { + return false; + } } else { Intent locationChanged = new Intent(); locationChanged.putExtra(LocationManager.KEY_LOCATION_CHANGED, location); try { mPendingIntent.send(mContext, 0, locationChanged, null, null); } catch (PendingIntent.CanceledException e) { - _removeUpdates(this); + return false; } } + return true; } public void binderDied() { @@ -297,12 +340,12 @@ public class LocationManagerService extends ILocationManager.Stub Log.d(TAG, "Location listener died"); } synchronized (mLocationListeners) { - _removeUpdates(this); + removeUpdatesLocked(this); } } } - private Location readLastKnownLocation(String provider) { + private Location readLastKnownLocationLocked(String provider) { Location location = null; String s = null; try { @@ -345,7 +388,7 @@ public class LocationManagerService extends ILocationManager.Stub return location; } - private void writeLastKnownLocation(String provider, + private void writeLastKnownLocationLocked(String provider, Location location) { long now = SystemClock.elapsedRealtime(); Long last = mLastWriteTime.get(provider); @@ -403,26 +446,26 @@ public class LocationManagerService extends ILocationManager.Stub * properties */ private void loadProviders() { - synchronized (LocationManagerService.class) { + synchronized (mLocationListeners) { if (sProvidersLoaded) { return; } // Load providers - loadProvidersNoSync(); + loadProvidersLocked(); sProvidersLoaded = true; } } - private void loadProvidersNoSync() { + private void loadProvidersLocked() { try { - _loadProvidersNoSync(); + _loadProvidersLocked(); } catch (Exception e) { Log.e(TAG, "Exception loading providers:", e); } } - private void _loadProvidersNoSync() { + private void _loadProvidersLocked() { // Attempt to load "real" providers first if (GpsLocationProvider.isSupported()) { // Create a gps location provider @@ -495,7 +538,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - updateProviders(); + updateProvidersLocked(); } /** @@ -546,13 +589,15 @@ public class LocationManagerService extends ILocationManager.Stub intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED); + intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED); + intentFilter.addAction(Intent.ACTION_PACKAGE_RESTARTED); context.registerReceiver(powerStateReceiver, intentFilter); // Get the wifi manager mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); // Create a wifi lock for future use - mWifiLock = getWifiWakelock(); + mWifiLock = getWifiWakelockLocked(); // There might be an existing wifi scan available if (mWifiManager != null) { @@ -566,28 +611,34 @@ public class LocationManagerService extends ILocationManager.Stub } public void setInstallCallback(InstallCallback callback) { - mLocationHandler.removeMessages(MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER); - Message m = Message.obtain(mLocationHandler, - MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER, callback); - mLocationHandler.sendMessageAtFrontOfQueue(m); + synchronized (mLocationListeners) { + mLocationHandler.removeMessages(MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER); + Message m = Message.obtain(mLocationHandler, + MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER, callback); + mLocationHandler.sendMessageAtFrontOfQueue(m); + } } public void setNetworkLocationProvider(INetworkLocationProvider provider) { - mNetworkLocationInterface = provider; - provider.addListener(getPackageNames()); - mNetworkLocationProvider = (LocationProviderImpl)provider; - LocationProviderImpl.addProvider(mNetworkLocationProvider); - updateProviders(); + synchronized (mLocationListeners) { + mNetworkLocationInterface = provider; + provider.addListener(getPackageNames()); + mNetworkLocationProvider = (LocationProviderImpl)provider; + LocationProviderImpl.addProvider(mNetworkLocationProvider); + updateProvidersLocked(); + } } public void setLocationCollector(ILocationCollector collector) { - mCollector = collector; - if (mGpsLocationProvider != null) { + synchronized (mLocationListeners) { + mCollector = collector; + if (mGpsLocationProvider != null) { mGpsLocationProvider.setLocationCollector(mCollector); + } } } - private WifiManager.WifiLock getWifiWakelock() { + private WifiManager.WifiLock getWifiWakelockLocked() { if (mWifiLock == null && mWifiManager != null) { mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_SCAN_ONLY, WIFILOCK_KEY); mWifiLock.setReferenceCounted(false); @@ -595,7 +646,7 @@ public class LocationManagerService extends ILocationManager.Stub return mWifiLock; } - private boolean isAllowedBySettings(String provider) { + private boolean isAllowedBySettingsLocked(String provider) { if (mEnabledProviders.contains(provider)) { return true; } @@ -610,7 +661,7 @@ public class LocationManagerService extends ILocationManager.Stub return ((allowedProviders != null) && (allowedProviders.contains(provider))); } - private void checkPermissions(String provider) { + private void checkPermissionsSafe(String provider) { if (LocationManager.GPS_PROVIDER.equals(provider) && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { @@ -626,7 +677,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - private boolean isAllowedProvider(String provider) { + private boolean isAllowedProviderSafe(String provider) { if (LocationManager.GPS_PROVIDER.equals(provider) && (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED)) { @@ -651,7 +702,9 @@ public class LocationManagerService extends ILocationManager.Stub public List<String> getAllProviders() { try { - return _getAllProviders(); + synchronized (mLocationListeners) { + return _getAllProvidersLocked(); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -660,7 +713,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - private List<String> _getAllProviders() { + private List<String> _getAllProvidersLocked() { if (Config.LOGD) { Log.d(TAG, "getAllProviders"); } @@ -675,7 +728,9 @@ public class LocationManagerService extends ILocationManager.Stub public List<String> getProviders(boolean enabledOnly) { try { - return _getProviders(enabledOnly); + synchronized (mLocationListeners) { + return _getProvidersLocked(enabledOnly); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -684,7 +739,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - private List<String> _getProviders(boolean enabledOnly) { + private List<String> _getProvidersLocked(boolean enabledOnly) { if (Config.LOGD) { Log.d(TAG, "getProviders"); } @@ -693,8 +748,8 @@ public class LocationManagerService extends ILocationManager.Stub for (LocationProviderImpl p : providers) { String name = p.getName(); - if (isAllowedProvider(name)) { - if (enabledOnly && !isAllowedBySettings(name)) { + if (isAllowedProviderSafe(name)) { + if (enabledOnly && !isAllowedBySettingsLocked(name)) { continue; } out.add(name); @@ -704,10 +759,16 @@ public class LocationManagerService extends ILocationManager.Stub } public void updateProviders() { + synchronized (mLocationListeners) { + updateProvidersLocked(); + } + } + + private void updateProvidersLocked() { for (LocationProviderImpl p : LocationProviderImpl.getProviders()) { boolean isEnabled = p.isEnabled(); String name = p.getName(); - boolean shouldBeEnabled = isAllowedBySettings(name); + boolean shouldBeEnabled = isAllowedBySettingsLocked(name); // Collection is only allowed when network provider is being used if (mCollector != null && @@ -716,15 +777,15 @@ public class LocationManagerService extends ILocationManager.Stub } if (isEnabled && !shouldBeEnabled) { - updateProviderListeners(name, false); + updateProviderListenersLocked(name, false); } else if (!isEnabled && shouldBeEnabled) { - updateProviderListeners(name, true); + updateProviderListenersLocked(name, true); } } } - private void updateProviderListeners(String provider, boolean enabled) { + private void updateProviderListenersLocked(String provider, boolean enabled) { int listeners = 0; LocationProviderImpl p = LocationProviderImpl.getProvider(provider); @@ -732,49 +793,63 @@ public class LocationManagerService extends ILocationManager.Stub return; } - synchronized (mRecordsByProvider) { - HashSet<UpdateRecord> records = mRecordsByProvider.get(provider); - if (records != null) { - for (UpdateRecord record : records) { - // 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); - } + ArrayList<Receiver> deadReceivers = null; + + ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); + if (records != null) { + final int N = records.size(); + 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 { - PendingIntent intent = receiver.getPendingIntent(); - Intent providerIntent = new Intent(); - providerIntent.putExtra(LocationManager.KEY_PROVIDER_ENABLED, enabled); - try { - receiver.getPendingIntent().send(mContext, 0, - providerIntent, null, null); - } catch (PendingIntent.CanceledException e) { - _removeUpdates(receiver); + 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); } } - } catch (RemoteException e) { - // The death link will clean this up. } - listeners++; + } catch (RemoteException e) { + // The death link will clean this up. } + listeners++; } } + if (deadReceivers != null) { + for (int i=deadReceivers.size()-1; i>=0; i--) { + removeUpdatesLocked(deadReceivers.get(i)); + } + } + if (enabled) { p.enable(); if (listeners > 0) { - p.setMinTime(getMinTime(provider)); + p.setMinTime(getMinTimeLocked(provider)); p.enableLocationTracking(true); - updateWakelockStatus(mScreenOn); + updateWakelockStatusLocked(mScreenOn); } } else { p.enableLocationTracking(false); + if (p == mGpsLocationProvider) { + mGpsNavigating = false; + reportStopGpsLocked(); + } p.disable(); - updateWakelockStatus(mScreenOn); + updateWakelockStatusLocked(mScreenOn); } if (enabled && listeners > 0) { @@ -786,40 +861,43 @@ public class LocationManagerService extends ILocationManager.Stub } } - private long getMinTime(String provider) { + private long getMinTimeLocked(String provider) { long minTime = Long.MAX_VALUE; - synchronized (mRecordsByProvider) { - HashSet<UpdateRecord> records = mRecordsByProvider.get(provider); - if (records != null) { - for (UpdateRecord r : records) { - minTime = Math.min(minTime, r.mMinTime); - } + ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); + if (records != null) { + for (int i=records.size()-1; i>=0; i--) { + minTime = Math.min(minTime, records.get(i).mMinTime); } } return minTime; } private class UpdateRecord { - String mProvider; - Receiver mReceiver; - long mMinTime; - float mMinDistance; - String[] mPackages; + final String mProvider; + final Receiver mReceiver; + final long mMinTime; + final float mMinDistance; + final int mUid; + final String[] mPackages; + /** + * Note: must be constructed with lock held. + */ UpdateRecord(String provider, long minTime, float minDistance, - Receiver receiver, String[] packages) { + Receiver receiver, int uid, String[] packages) { mProvider = provider; mReceiver = receiver; mMinTime = minTime; mMinDistance = minDistance; + mUid = uid; mPackages = packages; - synchronized (mRecordsByProvider) { - HashSet<UpdateRecord> records = mRecordsByProvider.get(provider); - if (records == null) { - records = new HashSet<UpdateRecord>(); - mRecordsByProvider.put(provider, records); - } + ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); + if (records == null) { + records = new ArrayList<UpdateRecord>(); + mRecordsByProvider.put(provider, records); + } + if (!records.contains(this)) { records.add(this); } } @@ -828,18 +906,39 @@ public class LocationManagerService extends ILocationManager.Stub * Method to be called when a record will no longer be used. Calling this multiple times * must have the same effect as calling it once. */ - public void dispose() { - synchronized (mRecordsByProvider) { - HashSet<UpdateRecord> records = mRecordsByProvider.get(this.mProvider); - records.remove(this); - } + void disposeLocked() { + ArrayList<UpdateRecord> records = mRecordsByProvider.get(this.mProvider); + records.remove(this); } + @Override + public String toString() { + return "UpdateRecord{" + + Integer.toHexString(System.identityHashCode(this)) + + " " + mProvider + " " + mReceiver + "}"; + } + + void dump(PrintWriter pw, String prefix) { + pw.println(prefix + this); + pw.println(prefix + "mProvider=" + mProvider + " mReceiver=" + mReceiver); + pw.println(prefix + "mMinTime=" + mMinTime + " mMinDistance=" + mMinDistance); + StringBuilder sb = new StringBuilder(); + if (mPackages != null) { + for (int i=0; i<mPackages.length; i++) { + if (i > 0) sb.append(", "); + sb.append(mPackages[i]); + } + } + pw.println(prefix + "mUid=" + mUid + " mPackages=" + sb); + } + /** * Calls dispose(). */ @Override protected void finalize() { - dispose(); + synchronized (mLocationListeners) { + disposeLocked(); + } } } @@ -847,8 +946,10 @@ public class LocationManagerService extends ILocationManager.Stub long minTime, float minDistance, ILocationListener listener) { try { - _requestLocationUpdates(provider, minTime, minDistance, - new Receiver(listener)); + synchronized (mLocationListeners) { + requestLocationUpdatesLocked(provider, minTime, minDistance, + new Receiver(listener, Binder.getCallingUid())); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -859,8 +960,10 @@ public class LocationManagerService extends ILocationManager.Stub public void requestLocationUpdatesPI(String provider, long minTime, float minDistance, PendingIntent intent) { try { - _requestLocationUpdates(provider, minTime, minDistance, - new Receiver(intent)); + synchronized (mLocationListeners) { + requestLocationUpdatesLocked(provider, minTime, minDistance, + new Receiver(intent, Binder.getCallingUid())); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -868,11 +971,10 @@ public class LocationManagerService extends ILocationManager.Stub } } - private synchronized void _requestLocationUpdates(String provider, + private void requestLocationUpdatesLocked(String provider, long minTime, float minDistance, Receiver receiver) { - Object key = receiver.getKey(); if (Config.LOGD) { - Log.d(TAG, "_requestLocationUpdates: listener = " + key); + Log.d(TAG, "_requestLocationUpdates: listener = " + receiver); } LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); @@ -880,77 +982,75 @@ public class LocationManagerService extends ILocationManager.Stub throw new IllegalArgumentException("provider=" + provider); } - checkPermissions(provider); + checkPermissionsSafe(provider); String[] packages = getPackageNames(); // so wakelock calls will succeed - mCallingUid = getCallingUid(); + final int callingUid = Binder.getCallingUid(); long identity = Binder.clearCallingIdentity(); try { - UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, receiver, packages); - synchronized (mLocationListeners) { - if (mListeners.get(key) == null) { - try { - if (receiver.isListener()) { - receiver.getListener().asBinder().linkToDeath(receiver, 0); - } - mListeners.put(key, receiver); - } catch (RemoteException e) { - return; + UpdateRecord r = new UpdateRecord(provider, minTime, minDistance, + receiver, callingUid, packages); + if (!mListeners.contains(receiver)) { + try { + if (receiver.isListener()) { + receiver.getListener().asBinder().linkToDeath(receiver, 0); } + mListeners.add(receiver); + } catch (RemoteException e) { + return; } + } - HashMap<String,UpdateRecord> records = mLocationListeners.get(key); - if (records == null) { - records = new HashMap<String,UpdateRecord>(); - mLocationListeners.put(key, records); - } - UpdateRecord oldRecord = records.put(provider, r); - if (oldRecord != null) { - oldRecord.dispose(); - } + HashMap<String,UpdateRecord> records = mLocationListeners.get(receiver); + if (records == null) { + records = new HashMap<String,UpdateRecord>(); + mLocationListeners.put(receiver, records); + } + UpdateRecord oldRecord = records.put(provider, r); + if (oldRecord != null) { + oldRecord.disposeLocked(); + } - boolean isProviderEnabled = isAllowedBySettings(provider); - if (isProviderEnabled) { - if (provider.equals(LocationManager.GPS_PROVIDER)) { - try { - mBatteryStats.noteRequestGpsOn(mCallingUid); - } catch (RemoteException e) { - Log.w(TAG, "Got RemoteException calling noteRequestGpsOff", e); - } + boolean isProviderEnabled = isAllowedBySettingsLocked(provider); + if (isProviderEnabled) { + long minTimeForProvider = getMinTimeLocked(provider); + impl.setMinTime(minTimeForProvider); + impl.enableLocationTracking(true); + updateWakelockStatusLocked(mScreenOn); + + if (provider.equals(LocationManager.GPS_PROVIDER)) { + if (mGpsNavigating) { + updateReportedGpsLocked(); } - - long minTimeForProvider = getMinTime(provider); - impl.setMinTime(minTimeForProvider); - impl.enableLocationTracking(true); - updateWakelockStatus(mScreenOn); - - // 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 - if (receiver.isListener()) { - receiver.getListener().onProviderDisabled(provider); - } - } catch(RemoteException e) { - Log.w(TAG, "RemoteException calling onProviderDisabled on " + - receiver.getListener()); + } + + // 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 + if (receiver.isListener()) { + receiver.getListener().onProviderDisabled(provider); } + } catch(RemoteException e) { + Log.w(TAG, "RemoteException calling onProviderDisabled on " + + receiver.getListener()); } } } finally { Binder.restoreCallingIdentity(identity); - mCallingUid = -1; } } public void removeUpdates(ILocationListener listener) { try { - _removeUpdates(new Receiver(listener)); + synchronized (mLocationListeners) { + removeUpdatesLocked(new Receiver(listener, Binder.getCallingUid())); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -960,7 +1060,9 @@ public class LocationManagerService extends ILocationManager.Stub public void removeUpdatesPI(PendingIntent intent) { try { - _removeUpdates(new Receiver(intent)); + synchronized (mLocationListeners) { + removeUpdatesLocked(new Receiver(intent, Binder.getCallingUid())); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -968,84 +1070,77 @@ public class LocationManagerService extends ILocationManager.Stub } } - private synchronized void _removeUpdates(Receiver receiver) { - Object key = receiver.getKey(); + private void removeUpdatesLocked(Receiver receiver) { if (Config.LOGD) { - Log.d(TAG, "_removeUpdates: listener = " + key); + Log.d(TAG, "_removeUpdates: listener = " + receiver); } // so wakelock calls will succeed - mCallingUid = getCallingUid(); + final int callingUid = Binder.getCallingUid(); long identity = Binder.clearCallingIdentity(); try { - synchronized (mLocationListeners) { - Receiver myReceiver = mListeners.remove(key); - if ((myReceiver != null) && (myReceiver.isListener())) { + int idx = mListeners.indexOf(receiver); + if (idx >= 0) { + Receiver myReceiver = mListeners.remove(idx); + if (myReceiver.isListener()) { myReceiver.getListener().asBinder().unlinkToDeath(myReceiver, 0); } + } - // Record which providers were associated with this listener - HashSet<String> providers = new HashSet<String>(); - HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(key); - if (oldRecords != null) { - // Call dispose() on the obsolete update records. - for (UpdateRecord record : oldRecords.values()) { - if (record.mProvider.equals(LocationManager.NETWORK_PROVIDER)) { - if (mNetworkLocationInterface != null) { - mNetworkLocationInterface.removeListener(record.mPackages); - } + // Record which providers were associated with this listener + HashSet<String> providers = new HashSet<String>(); + HashMap<String,UpdateRecord> oldRecords = mLocationListeners.get(receiver); + if (oldRecords != null) { + // Call dispose() on the obsolete update records. + for (UpdateRecord record : oldRecords.values()) { + if (record.mProvider.equals(LocationManager.NETWORK_PROVIDER)) { + if (mNetworkLocationInterface != null) { + mNetworkLocationInterface.removeListener(record.mPackages); } - record.dispose(); } - // Accumulate providers - providers.addAll(oldRecords.keySet()); + record.disposeLocked(); } - - if (providers.contains("gps")) { - try { - mBatteryStats.noteRequestGpsOff(mCallingUid); - } catch (RemoteException e) { - Log.w(TAG, "Got RemoteException calling noteRequestGpsOff", e); - } + // Accumulate providers + providers.addAll(oldRecords.keySet()); + } + + mLocationListeners.remove(receiver); + mLastFixBroadcast.remove(receiver); + mLastStatusBroadcast.remove(receiver); + + // See if the providers associated with this listener have any + // other listeners; if one does, inform it of the new smallest minTime + // value; if one does not, disable location tracking for it + for (String provider : providers) { + // If provider is already disabled, don't need to do anything + if (!isAllowedBySettingsLocked(provider)) { + continue; } - mLocationListeners.remove(key); - mLastFixBroadcast.remove(key); - mLastStatusBroadcast.remove(key); - - // See if the providers associated with this listener have any - // other listeners; if one does, inform it of the new smallest minTime - // value; if one does not, disable location tracking for it - for (String provider : providers) { - // If provider is already disabled, don't need to do anything - if (!isAllowedBySettings(provider)) { - continue; - } + boolean hasOtherListener = false; + ArrayList<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider); + if (recordsForProvider != null && recordsForProvider.size() > 0) { + hasOtherListener = true; + } - boolean hasOtherListener = false; - synchronized (mRecordsByProvider) { - HashSet<UpdateRecord> recordsForProvider = mRecordsByProvider.get(provider); - if (recordsForProvider != null && recordsForProvider.size() > 0) { - hasOtherListener = true; - } + LocationProviderImpl p = LocationProviderImpl.getProvider(provider); + if (p != null) { + if (hasOtherListener) { + p.setMinTime(getMinTimeLocked(provider)); + } else { + mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider); + p.enableLocationTracking(false); } - - LocationProviderImpl p = LocationProviderImpl.getProvider(provider); - if (p != null) { - if (hasOtherListener) { - p.setMinTime(getMinTime(provider)); - } else { - mLocationHandler.removeMessages(MESSAGE_HEARTBEAT, provider); - p.enableLocationTracking(false); - } + + if (p == mGpsLocationProvider && mGpsNavigating) { + updateReportedGpsLocked(); } } - - updateWakelockStatus(mScreenOn); } + + updateWakelockStatusLocked(mScreenOn); } finally { Binder.restoreCallingIdentity(identity); - mCallingUid = -1; } } @@ -1054,7 +1149,7 @@ public class LocationManagerService extends ILocationManager.Stub return false; } if (mContext.checkCallingPermission(ACCESS_FINE_LOCATION) != - PackageManager.PERMISSION_GRANTED) { + PackageManager.PERMISSION_GRANTED) { throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); } @@ -1068,36 +1163,42 @@ public class LocationManagerService extends ILocationManager.Stub } public void removeGpsStatusListener(IGpsStatusListener listener) { - mGpsLocationProvider.removeGpsStatusListener(listener); + synchronized (mLocationListeners) { + mGpsLocationProvider.removeGpsStatusListener(listener); + } } public boolean sendExtraCommand(String provider, String command, Bundle extras) { // first check for permission to the provider - checkPermissions(provider); + checkPermissionsSafe(provider); // and check for ACCESS_LOCATION_EXTRA_COMMANDS if ((mContext.checkCallingPermission(ACCESS_LOCATION_EXTRA_COMMANDS) != PackageManager.PERMISSION_GRANTED)) { throw new SecurityException("Requires ACCESS_LOCATION_EXTRA_COMMANDS permission"); } - LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); - if (provider == null) { - return false; + synchronized (mLocationListeners) { + LocationProviderImpl impl = LocationProviderImpl.getProvider(provider); + if (provider == null) { + return false; + } + + return impl.sendExtraCommand(command, extras); } - - return impl.sendExtraCommand(command, extras); } class ProximityAlert { - double mLatitude; - double mLongitude; - float mRadius; - long mExpiration; - PendingIntent mIntent; - Location mLocation; - - public ProximityAlert(double latitude, double longitude, + final int mUid; + final double mLatitude; + final double mLongitude; + final float mRadius; + final long mExpiration; + final PendingIntent mIntent; + final Location mLocation; + + public ProximityAlert(int uid, double latitude, double longitude, float radius, long expiration, PendingIntent intent) { + mUid = uid; mLatitude = latitude; mLongitude = longitude; mRadius = radius; @@ -1109,15 +1210,15 @@ public class LocationManagerService extends ILocationManager.Stub mLocation.setLongitude(longitude); } - public long getExpiration() { + long getExpiration() { return mExpiration; } - public PendingIntent getIntent() { + PendingIntent getIntent() { return mIntent; } - public boolean isInProximity(double latitude, double longitude) { + boolean isInProximity(double latitude, double longitude) { Location loc = new Location(""); loc.setLatitude(latitude); loc.setLongitude(longitude); @@ -1125,6 +1226,22 @@ public class LocationManagerService extends ILocationManager.Stub double radius = loc.distanceTo(mLocation); return radius <= mRadius; } + + @Override + public String toString() { + return "ProximityAlert{" + + Integer.toHexString(System.identityHashCode(this)) + + " uid " + mUid + mIntent + "}"; + } + + void dump(PrintWriter pw, String prefix) { + pw.println(prefix + this); + pw.println(prefix + "mLatitude=" + mLatitude + " mLongitude=" + mLongitude); + pw.println(prefix + "mRadius=" + mRadius + " mExpiration=" + mExpiration); + pw.println(prefix + "mIntent=" + mIntent); + pw.println(prefix + "mLocation:"); + mLocation.dump(new PrintWriterPrinter(pw), prefix + " "); + } } // Listener for receiving locations to trigger proximity alerts @@ -1132,6 +1249,7 @@ public class LocationManagerService extends ILocationManager.Stub boolean isGpsAvailable = false; + // Note: this is called with the lock held. public void onLocationChanged(Location loc) { // If Gps is available, then ignore updates from NetworkLocationProvider @@ -1216,16 +1334,19 @@ public class LocationManagerService extends ILocationManager.Stub } + // Note: this is called with the lock held. public void onProviderDisabled(String provider) { if (provider.equals(LocationManager.GPS_PROVIDER)) { isGpsAvailable = false; } } + // Note: this is called with the lock held. public void onProviderEnabled(String provider) { // ignore } + // Note: this is called with the lock held. public void onStatusChanged(String provider, int status, Bundle extras) { if ((provider.equals(LocationManager.GPS_PROVIDER)) && (status != LocationProvider.AVAILABLE)) { @@ -1237,7 +1358,9 @@ public class LocationManagerService extends ILocationManager.Stub public void addProximityAlert(double latitude, double longitude, float radius, long expiration, PendingIntent intent) { try { - _addProximityAlert(latitude, longitude, radius, expiration, intent); + synchronized (mLocationListeners) { + addProximityAlertLocked(latitude, longitude, radius, expiration, intent); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -1245,7 +1368,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void _addProximityAlert(double latitude, double longitude, + private void addProximityAlertLocked(double latitude, double longitude, float radius, long expiration, PendingIntent intent) { if (Config.LOGD) { Log.d(TAG, "addProximityAlert: latitude = " + latitude + @@ -1255,37 +1378,42 @@ public class LocationManagerService extends ILocationManager.Stub } // Require ability to access all providers for now - if (!isAllowedProvider(LocationManager.GPS_PROVIDER) || - !isAllowedProvider(LocationManager.NETWORK_PROVIDER)) { + if (!isAllowedProviderSafe(LocationManager.GPS_PROVIDER) || + !isAllowedProviderSafe(LocationManager.NETWORK_PROVIDER)) { throw new SecurityException("Requires ACCESS_FINE_LOCATION permission"); } if (expiration != -1) { expiration += System.currentTimeMillis(); } - ProximityAlert alert = new ProximityAlert(latitude, longitude, radius, expiration, intent); + ProximityAlert alert = new ProximityAlert(Binder.getCallingUid(), + latitude, longitude, radius, expiration, intent); mProximityAlerts.put(intent, alert); if (mProximityListener == null) { - mProximityListener = new Receiver(new ProximityListener()); + mProximityListener = new Receiver(new ProximityListener(), -1); LocationProvider provider = LocationProviderImpl.getProvider( LocationManager.GPS_PROVIDER); if (provider != null) { - _requestLocationUpdates(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); } provider = LocationProviderImpl.getProvider(LocationManager.NETWORK_PROVIDER); if (provider != null) { - _requestLocationUpdates(provider.getName(), 1000L, 1.0f, mProximityListener); + requestLocationUpdatesLocked(provider.getName(), 1000L, 1.0f, mProximityListener); } + } else if (mGpsNavigating) { + updateReportedGpsLocked(); } } public void removeProximityAlert(PendingIntent intent) { try { - _removeProximityAlert(intent); + synchronized (mLocationListeners) { + removeProximityAlertLocked(intent); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -1293,15 +1421,17 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void _removeProximityAlert(PendingIntent intent) { + private void removeProximityAlertLocked(PendingIntent intent) { if (Config.LOGD) { Log.d(TAG, "removeProximityAlert: intent = " + intent); } mProximityAlerts.remove(intent); if (mProximityAlerts.size() == 0) { - _removeUpdates(mProximityListener); + removeUpdatesLocked(mProximityListener); mProximityListener = null; + } else if (mGpsNavigating) { + updateReportedGpsLocked(); } } @@ -1312,7 +1442,9 @@ public class LocationManagerService extends ILocationManager.Stub */ public Bundle getProviderInfo(String provider) { try { - return _getProviderInfo(provider); + synchronized (mLocationListeners) { + return _getProviderInfoLocked(provider); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -1321,13 +1453,13 @@ public class LocationManagerService extends ILocationManager.Stub } } - private Bundle _getProviderInfo(String provider) { + private Bundle _getProviderInfoLocked(String provider) { LocationProviderImpl p = LocationProviderImpl.getProvider(provider); if (p == null) { return null; } - checkPermissions(provider); + checkPermissionsSafe(provider); Bundle b = new Bundle(); b.putBoolean("network", p.requiresNetwork()); @@ -1345,7 +1477,9 @@ public class LocationManagerService extends ILocationManager.Stub public boolean isProviderEnabled(String provider) { try { - return _isProviderEnabled(provider); + synchronized (mLocationListeners) { + return _isProviderEnabledLocked(provider); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -1354,19 +1488,21 @@ public class LocationManagerService extends ILocationManager.Stub } } - private boolean _isProviderEnabled(String provider) { - checkPermissions(provider); + private boolean _isProviderEnabledLocked(String provider) { + checkPermissionsSafe(provider); LocationProviderImpl p = LocationProviderImpl.getProvider(provider); if (p == null) { throw new IllegalArgumentException("provider=" + provider); } - return isAllowedBySettings(provider); + return isAllowedBySettingsLocked(provider); } public Location getLastKnownLocation(String provider) { try { - return _getLastKnownLocation(provider); + synchronized (mLocationListeners) { + return _getLastKnownLocationLocked(provider); + } } catch (SecurityException se) { throw se; } catch (Exception e) { @@ -1375,22 +1511,22 @@ public class LocationManagerService extends ILocationManager.Stub } } - private Location _getLastKnownLocation(String provider) { - checkPermissions(provider); + private Location _getLastKnownLocationLocked(String provider) { + checkPermissionsSafe(provider); LocationProviderImpl p = LocationProviderImpl.getProvider(provider); if (p == null) { throw new IllegalArgumentException("provider=" + provider); } - if (!isAllowedBySettings(provider)) { + if (!isAllowedBySettingsLocked(provider)) { return null; } Location location = mLastKnownLocation.get(provider); if (location == null) { // Get the persistent last known location for the provider - location = readLastKnownLocation(provider); + location = readLastKnownLocationLocked(provider); if (location != null) { mLastKnownLocation.put(provider, location); } @@ -1399,7 +1535,7 @@ public class LocationManagerService extends ILocationManager.Stub return location; } - private boolean shouldBroadcast(Location loc, Location lastLoc, UpdateRecord record) { + private static boolean shouldBroadcastSafe(Location loc, Location lastLoc, UpdateRecord record) { // Always broadcast the first update if (lastLoc == null) { return true; @@ -1422,8 +1558,8 @@ public class LocationManagerService extends ILocationManager.Stub return true; } - private void handleLocationChanged(String provider) { - HashSet<UpdateRecord> records = mRecordsByProvider.get(provider); + private void handleLocationChangedLocked(String provider) { + ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider); if (records == null || records.size() == 0) { return; } @@ -1460,7 +1596,7 @@ public class LocationManagerService extends ILocationManager.Stub } else { location.set(loc); } - writeLastKnownLocation(provider, loc); + writeLastKnownLocationLocked(provider, loc); if (p instanceof INetworkLocationProvider) { mWakeLockNetworkReceived = true; @@ -1495,40 +1631,44 @@ public class LocationManagerService extends ILocationManager.Stub extras.putAll(mockExtras); } + ArrayList<Receiver> deadReceivers = null; + // Broadcast location or status to all listeners - for (UpdateRecord r : records) { + final int N = records.size(); + for (int i=0; i<N; i++) { + UpdateRecord r = records.get(i); Receiver receiver = r.mReceiver; - Object key = receiver.getKey(); // Broadcast location only if it is valid if (locationValid) { - HashMap<String,Location> map = mLastFixBroadcast.get(key); + HashMap<String,Location> map = mLastFixBroadcast.get(receiver); if (map == null) { map = new HashMap<String,Location>(); - mLastFixBroadcast.put(key, map); + mLastFixBroadcast.put(receiver, map); } Location lastLoc = map.get(provider); - if ((lastLoc == null) || shouldBroadcast(loc, lastLoc, r)) { + if ((lastLoc == null) || shouldBroadcastSafe(loc, lastLoc, r)) { if (lastLoc == null) { lastLoc = new Location(loc); map.put(provider, lastLoc); } else { lastLoc.set(loc); } - try { - receiver.onLocationChanged(loc); - } catch (RemoteException doe) { + if (!receiver.callLocationChangedLocked(loc)) { Log.w(TAG, "RemoteException calling onLocationChanged on " + receiver); - _removeUpdates(receiver); + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + } + deadReceivers.add(receiver); } } } // Broadcast status message - HashMap<String,Long> statusMap = mLastStatusBroadcast.get(key); + HashMap<String,Long> statusMap = mLastStatusBroadcast.get(receiver); if (statusMap == null) { statusMap = new HashMap<String,Long>(); - mLastStatusBroadcast.put(key, statusMap); + mLastStatusBroadcast.put(receiver, statusMap); } long prevStatusUpdateTime = (statusMap.get(provider) != null) ? statusMap.get(provider) : 0; @@ -1537,14 +1677,23 @@ public class LocationManagerService extends ILocationManager.Stub (prevStatusUpdateTime != 0 || status != LocationProvider.AVAILABLE)) { statusMap.put(provider, newStatusUpdateTime); - try { - receiver.onStatusChanged(provider, status, extras); - } catch (RemoteException doe) { + if (!receiver.callStatusChangedLocked(provider, status, extras)) { Log.w(TAG, "RemoteException calling onStatusChanged on " + receiver); - _removeUpdates(receiver); + if (deadReceivers == null) { + deadReceivers = new ArrayList<Receiver>(); + } + if (!deadReceivers.contains(receiver)) { + deadReceivers.add(receiver); + } } } } + + if (deadReceivers != null) { + for (int i=deadReceivers.size()-1; i>=0; i--) { + removeUpdatesLocked(deadReceivers.get(i)); + } + } } private class LocationWorkerHandler extends Handler { @@ -1555,59 +1704,63 @@ public class LocationManagerService extends ILocationManager.Stub if (msg.what == MESSAGE_HEARTBEAT) { // log("LocationWorkerHandler: Heartbeat!"); - synchronized (mRecordsByProvider) { + synchronized (mLocationListeners) { String provider = (String) msg.obj; - if (!isAllowedBySettings(provider)) { + if (!isAllowedBySettingsLocked(provider)) { return; } // Process the location fix if the screen is on or we're holding a wakelock if (mScreenOn || (mWakeLockAcquireTime != 0)) { - handleLocationChanged(provider); + handleLocationChangedLocked(provider); } // If it continues to have listeners - HashSet<UpdateRecord> records = mRecordsByProvider.get(provider); + 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); } - } - - if ((mWakeLockAcquireTime != 0) && - (SystemClock.elapsedRealtime() - mWakeLockAcquireTime - > MAX_TIME_FOR_WAKE_LOCK)) { - removeMessages(MESSAGE_ACQUIRE_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_ACQUIRE_WAKE_LOCK); - 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); + if ((mWakeLockAcquireTime != 0) && + (SystemClock.elapsedRealtime() - mWakeLockAcquireTime + > MAX_TIME_FOR_WAKE_LOCK)) { + + removeMessages(MESSAGE_ACQUIRE_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_ACQUIRE_WAKE_LOCK); + 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_ACQUIRE_WAKE_LOCK) { log("LocationWorkerHandler: Acquire"); - acquireWakeLock(); + synchronized (mLocationListeners) { + acquireWakeLockLocked(); + } } else if (msg.what == MESSAGE_RELEASE_WAKE_LOCK) { log("LocationWorkerHandler: Release"); // Update wakelock status so the next alarm is set before releasing wakelock - updateWakelockStatus(mScreenOn); - releaseWakeLock(); + synchronized (mLocationListeners) { + updateWakelockStatusLocked(mScreenOn); + releaseWakeLockLocked(); + } } else if (msg.what == MESSAGE_INSTALL_NETWORK_LOCATION_PROVIDER) { - synchronized (LocationManagerService.class) { + synchronized (mLocationListeners) { Log.d(TAG, "installing network location provider"); INetworkLocationManager.InstallCallback callback = (INetworkLocationManager.InstallCallback)msg.obj; @@ -1627,21 +1780,23 @@ public class LocationManagerService extends ILocationManager.Stub @Override public void onCellLocationChanged(CellLocation cellLocation) { try { - int asu = mSignalStrength; - - // Gets cell state - mLastCellState = new CellState(mTelephonyManager, cellLocation, asu); - - // Notify collector - if (mCollector != null) { - mCollector.updateCellState(mLastCellState); - } - - // Updates providers - List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); - for (LocationProviderImpl provider : providers) { - if (provider.requiresCell()) { - provider.updateCellState(mLastCellState); + synchronized (mLocationListeners) { + int asu = mSignalStrength; + + // Gets cell state + mLastCellState = new CellState(mTelephonyManager, cellLocation, asu); + + // Notify collector + if (mCollector != null) { + mCollector.updateCellState(mLastCellState); + } + + // Updates providers + List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); + for (LocationProviderImpl provider : providers) { + if (provider.requiresCell()) { + provider.updateCellState(mLastCellState); + } } } } catch (Exception e) { @@ -1651,17 +1806,21 @@ public class LocationManagerService extends ILocationManager.Stub @Override public void onSignalStrengthChanged(int asu) { - mSignalStrength = asu; - - if (mLastCellState != null) { - mLastCellState.updateSignalStrength(asu); + synchronized (mLocationListeners) { + mSignalStrength = asu; + + if (mLastCellState != null) { + mLastCellState.updateSignalStrength(asu); + } } } @Override public void onDataConnectionStateChanged(int state) { - if (mLastCellState != null) { - mLastCellState.updateRadioType(mTelephonyManager); + synchronized (mLocationListeners) { + if (mLastCellState != null) { + mLastCellState.updateRadioType(mTelephonyManager); + } } } }; @@ -1671,30 +1830,81 @@ public class LocationManagerService extends ILocationManager.Stub String action = intent.getAction(); if (action.equals(ALARM_INTENT)) { - mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); - mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - - log("PowerStateBroadcastReceiver: Alarm received"); - Message m = mLocationHandler.obtainMessage(MESSAGE_ACQUIRE_WAKE_LOCK); - mLocationHandler.sendMessageAtFrontOfQueue(m); + synchronized (mLocationListeners) { + log("PowerStateBroadcastReceiver: Alarm received"); + mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); + // Have to do this immediately, rather than posting a + // message, so we execute our code while the system + // is holding a wake lock until the alarm broadcast + // is finished. + acquireWakeLockLocked(); + } } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { log("PowerStateBroadcastReceiver: Screen off"); - updateWakelockStatus(false); + synchronized (mLocationListeners) { + updateWakelockStatusLocked(false); + } } else if (action.equals(Intent.ACTION_SCREEN_ON)) { log("PowerStateBroadcastReceiver: Screen on"); - updateWakelockStatus(true); + synchronized (mLocationListeners) { + updateWakelockStatusLocked(true); + } } else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { log("PowerStateBroadcastReceiver: Battery changed"); - int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100); - int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0); - boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0; - - // Notify collector battery state - if (mCollector != null) { - mCollector.updateBatteryState(scale, level, plugged); + synchronized (mLocationListeners) { + int scale = intent.getIntExtra(BATTERY_EXTRA_SCALE, 100); + int level = intent.getIntExtra(BATTERY_EXTRA_LEVEL, 0); + boolean plugged = intent.getIntExtra(BATTERY_EXTRA_PLUGGED, 0) != 0; + + // Notify collector battery state + if (mCollector != null) { + mCollector.updateBatteryState(scale, level, plugged); + } + } + } else if (action.equals(Intent.ACTION_PACKAGE_REMOVED) + || action.equals(Intent.ACTION_PACKAGE_RESTARTED)) { + synchronized (mLocationListeners) { + int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); + if (uid >= 0) { + ArrayList<Receiver> removedRecs = null; + for (ArrayList<UpdateRecord> i : mRecordsByProvider.values()) { + for (int j=i.size()-1; j>=0; j--) { + UpdateRecord ur = i.get(j); + if (ur.mReceiver.isPendingIntent() && ur.mUid == uid) { + if (removedRecs == null) { + removedRecs = new ArrayList<Receiver>(); + } + if (!removedRecs.contains(ur.mReceiver)) { + removedRecs.add(ur.mReceiver); + } + } + } + } + ArrayList<ProximityAlert> removedAlerts = null; + for (ProximityAlert i : mProximityAlerts.values()) { + if (i.mUid == uid) { + if (removedAlerts == null) { + removedAlerts = new ArrayList<ProximityAlert>(); + } + if (!removedAlerts.contains(i)) { + removedAlerts.add(i); + } + } + } + if (removedRecs != null) { + for (int i=removedRecs.size()-1; i>=0; i--) { + removeUpdatesLocked(removedRecs.get(i)); + } + } + if (removedAlerts != null) { + for (int i=removedAlerts.size()-1; i>=0; i--) { + removeProximityAlertLocked(removedAlerts.get(i).mIntent); + } + } + } } } } @@ -1713,11 +1923,13 @@ public class LocationManagerService extends ILocationManager.Stub } // Notify provider and collector of Wifi scan results - if (mCollector != null) { - mCollector.updateWifiScanResults(wifiScanResults); - } - if (mNetworkLocationInterface != null) { - mNetworkLocationInterface.updateWifiScanResults(wifiScanResults); + synchronized (mLocationListeners) { + if (mCollector != null) { + mCollector.updateWifiScanResults(wifiScanResults); + } + if (mNetworkLocationInterface != null) { + mNetworkLocationInterface.updateWifiScanResults(wifiScanResults); + } } } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) { @@ -1730,10 +1942,12 @@ public class LocationManagerService extends ILocationManager.Stub } // Notify location providers of current network state - List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); - for (LocationProviderImpl provider : providers) { - if (provider.requiresNetwork()) { - provider.updateNetworkState(networkState); + synchronized (mLocationListeners) { + List<LocationProviderImpl> providers = LocationProviderImpl.getProviders(); + for (LocationProviderImpl provider : providers) { + if (provider.requiresNetwork()) { + provider.updateNetworkState(networkState); + } } } @@ -1751,8 +1965,10 @@ public class LocationManagerService extends ILocationManager.Stub } // Notify network provider of current wifi enabled state - if (mNetworkLocationInterface != null) { - mNetworkLocationInterface.updateWifiEnabledState(enabled); + synchronized (mLocationListeners) { + if (mNetworkLocationInterface != null) { + mNetworkLocationInterface.updateWifiEnabledState(enabled); + } } } else if (action.equals(GpsLocationProvider.GPS_ENABLED_CHANGE_ACTION)) { @@ -1760,9 +1976,16 @@ public class LocationManagerService extends ILocationManager.Stub final boolean enabled = intent.getBooleanExtra(GpsLocationProvider.EXTRA_ENABLED, false); - if (!enabled) { - // When GPS is disabled, we are OK to release wake-lock - mWakeLockGpsReceived = true; + synchronized (mLocationListeners) { + if (enabled) { + updateReportedGpsLocked(); + mGpsNavigating = true; + } else { + reportStopGpsLocked(); + mGpsNavigating = false; + // When GPS is disabled, we are OK to release wake-lock + mWakeLockGpsReceived = true; + } } } @@ -1771,7 +1994,7 @@ public class LocationManagerService extends ILocationManager.Stub // Wake locks - private void updateWakelockStatus(boolean screenOn) { + private void updateWakelockStatusLocked(boolean screenOn) { log("updateWakelockStatus(): " + screenOn); boolean needsLock = false; @@ -1786,11 +2009,10 @@ public class LocationManagerService extends ILocationManager.Stub needsLock = true; minTime = Math.min(mGpsLocationProvider.getMinTime(), minTime); if (screenOn) { - startGps(); + startGpsLocked(); } else if (mScreenOn && !screenOn) { - // We just turned the screen off so stop navigating - stopGps(); + stopGpsLocked(); } } @@ -1816,13 +2038,13 @@ public class LocationManagerService extends ILocationManager.Stub // Clear out existing wakelocks mLocationHandler.removeMessages(MESSAGE_ACQUIRE_WAKE_LOCK); mLocationHandler.removeMessages(MESSAGE_RELEASE_WAKE_LOCK); - releaseWakeLock(); + releaseWakeLockLocked(); } } - private void acquireWakeLock() { + private void acquireWakeLockLocked() { try { - acquireWakeLockX(); + acquireWakeLockXLocked(); } catch (Exception e) { // This is to catch a runtime exception thrown when we try to release an // already released lock. @@ -1830,7 +2052,7 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void acquireWakeLockX() { + private void acquireWakeLockXLocked() { if (mWakeLock.isHeld()) { log("Must release wakelock before acquiring"); mWakeLockAcquireTime = 0; @@ -1857,7 +2079,7 @@ public class LocationManagerService extends ILocationManager.Stub log("Acquired wakelock"); // Start the gps provider - startGps(); + startGpsLocked(); // Acquire cell lock if (mCellWakeLockAcquired) { @@ -1875,7 +2097,7 @@ public class LocationManagerService extends ILocationManager.Stub } // Acquire wifi lock - WifiManager.WifiLock wifiLock = getWifiWakelock(); + WifiManager.WifiLock wifiLock = getWifiWakelockLocked(); if (wifiLock != null) { if (mWifiWakeLockAcquired) { // Lock is already acquired @@ -1889,41 +2111,104 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void startGps() { + private boolean reportGpsUidLocked(int curSeq, int nextSeq, int uid) { + int seq = mReportedGpsUids.get(uid, -1); + if (seq == curSeq) { + // Already reported; propagate to next sequence. + mReportedGpsUids.put(uid, nextSeq); + return true; + } else if (seq != nextSeq) { + try { + // New UID; report it. + mBatteryStats.noteStartGps(uid); + mReportedGpsUids.put(uid, nextSeq); + return true; + } catch (RemoteException e) { + } + } + return false; + } + + private void updateReportedGpsLocked() { + if (mGpsLocationProvider == null) { + return; + } + + final String name = mGpsLocationProvider.getName(); + final int curSeq = mReportedGpsSeq; + final int nextSeq = (curSeq+1) >= 0 ? (curSeq+1) : 0; + mReportedGpsSeq = nextSeq; + + ArrayList<UpdateRecord> urs = mRecordsByProvider.get(name); + int num = 0; + final int N = urs.size(); + for (int i=0; i<N; i++) { + UpdateRecord ur = urs.get(i); + if (ur.mReceiver == mProximityListener) { + // We don't want the system to take the blame for this one. + continue; + } + if (reportGpsUidLocked(curSeq, nextSeq, ur.mUid)) { + num++; + } + } + + for (ProximityAlert pe : mProximityAlerts.values()) { + if (reportGpsUidLocked(curSeq, nextSeq, pe.mUid)) { + num++; + } + } + + if (num != mReportedGpsUids.size()) { + // The number of uids is processed is different than the + // array; report any that are no longer active. + for (int i=mReportedGpsUids.size()-1; i>=0; i--) { + if (mReportedGpsUids.valueAt(i) != nextSeq) { + try { + mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i)); + } catch (RemoteException e) { + } + mReportedGpsUids.removeAt(i); + } + } + } + } + + private void reportStopGpsLocked() { + int curSeq = mReportedGpsSeq; + for (int i=mReportedGpsUids.size()-1; i>=0; i--) { + if (mReportedGpsUids.valueAt(i) == curSeq) { + try { + mBatteryStats.noteStopGps(mReportedGpsUids.keyAt(i)); + } catch (RemoteException e) { + } + } + } + curSeq++; + if (curSeq < 0) curSeq = 0; + mReportedGpsSeq = curSeq; + mReportedGpsUids.clear(); + } + + private void startGpsLocked() { boolean gpsActive = (mGpsLocationProvider != null) && mGpsLocationProvider.isLocationTracking(); if (gpsActive) { mGpsLocationProvider.startNavigating(); - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteStartGps(mCallingUid == -1 ? getCallingUid() : mCallingUid); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException calling noteStartGps on BatteryStatsService", e); - } finally { - Binder.restoreCallingIdentity(identity); - } } } - private void stopGps() { + private void stopGpsLocked() { boolean gpsActive = mGpsLocationProvider != null && mGpsLocationProvider.isLocationTracking(); if (gpsActive) { mGpsLocationProvider.stopNavigating(); - long identity = Binder.clearCallingIdentity(); - try { - mBatteryStats.noteStopGps(mCallingUid == -1 ? getCallingUid() : mCallingUid); - } catch (RemoteException e) { - Log.w(TAG, "RemoteException calling noteStopGps on BatteryStatsService", e); - } finally { - Binder.restoreCallingIdentity(identity); - } } } - private void releaseWakeLock() { + private void releaseWakeLockLocked() { try { - releaseWakeLockX(); + releaseWakeLockXLocked(); } catch (Exception e) { // This is to catch a runtime exception thrown when we try to release an // already released lock. @@ -1931,9 +2216,9 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void releaseWakeLockX() { + private void releaseWakeLockXLocked() { // Release wifi lock - WifiManager.WifiLock wifiLock = getWifiWakelock(); + WifiManager.WifiLock wifiLock = getWifiWakelockLocked(); if (wifiLock != null) { if (mWifiWakeLockAcquired) { wifiLock.release(); @@ -1943,7 +2228,7 @@ public class LocationManagerService extends ILocationManager.Stub if (!mScreenOn) { // Stop the gps - stopGps(); + stopGpsLocked(); } // Release cell lock @@ -1971,11 +2256,13 @@ public class LocationManagerService extends ILocationManager.Stub public String getFromLocation(double latitude, double longitude, int maxResults, String language, String country, String variant, String appName, List<Address> addrs) { - if (mNetworkLocationInterface != null) { - return mNetworkLocationInterface.getFromLocation(latitude, longitude, maxResults, - language, country, variant, appName, addrs); - } else { - return null; + synchronized (mLocationListeners) { + if (mNetworkLocationInterface != null) { + return mNetworkLocationInterface.getFromLocation(latitude, longitude, maxResults, + language, country, variant, appName, addrs); + } else { + return null; + } } } @@ -1983,12 +2270,14 @@ public class LocationManagerService extends ILocationManager.Stub double lowerLeftLatitude, double lowerLeftLongitude, double upperRightLatitude, double upperRightLongitude, int maxResults, String language, String country, String variant, String appName, List<Address> addrs) { - if (mNetworkLocationInterface != null) { - return mNetworkLocationInterface.getFromLocationName(locationName, lowerLeftLatitude, - lowerLeftLongitude, upperRightLatitude, upperRightLongitude, maxResults, - language, country, variant, appName, addrs); - } else { - return null; + synchronized (mLocationListeners) { + if (mNetworkLocationInterface != null) { + return mNetworkLocationInterface.getFromLocationName(locationName, lowerLeftLatitude, + lowerLeftLongitude, upperRightLatitude, upperRightLongitude, maxResults, + language, country, variant, appName, addrs); + } else { + return null; + } } } @@ -2024,43 +2313,63 @@ public class LocationManagerService extends ILocationManager.Stub @Override public void disable() { String name = getName(); - mEnabledProviders.remove(name); - mDisabledProviders.add(name); + // We shouldn't normally need to lock, since this should only be called + // by the service with the lock held, but let's be paranid. + synchronized (mLocationListeners) { + mEnabledProviders.remove(name); + mDisabledProviders.add(name); + } } @Override public void enable() { String name = getName(); - mEnabledProviders.add(name); - mDisabledProviders.remove(name); + // We shouldn't normally need to lock, since this should only be called + // by the service with the lock held, but let's be paranid. + synchronized (mLocationListeners) { + mEnabledProviders.add(name); + mDisabledProviders.remove(name); + } } @Override public boolean getLocation(Location l) { - Location loc = mMockProviderLocation.get(getName()); - if (loc == null) { - return false; + // We shouldn't normally need to lock, since this should only be called + // by the service with the lock held, but let's be paranid. + synchronized (mLocationListeners) { + Location loc = mMockProviderLocation.get(getName()); + if (loc == null) { + return false; + } + l.set(loc); + return true; } - l.set(loc); - return true; } @Override public int getStatus(Bundle extras) { - String name = getName(); - Integer s = mMockProviderStatus.get(name); - int status = (s == null) ? AVAILABLE : s.intValue(); - Bundle newExtras = mMockProviderStatusExtras.get(name); - if (newExtras != null) { - extras.clear(); - extras.putAll(newExtras); + // We shouldn't normally need to lock, since this should only be called + // by the service with the lock held, but let's be paranid. + synchronized (mLocationListeners) { + String name = getName(); + Integer s = mMockProviderStatus.get(name); + int status = (s == null) ? AVAILABLE : s.intValue(); + Bundle newExtras = mMockProviderStatusExtras.get(name); + if (newExtras != null) { + extras.clear(); + extras.putAll(newExtras); + } + return status; } - return status; } @Override public boolean isEnabled() { - return mEnabledProviders.contains(getName()); + // We shouldn't normally need to lock, since this should only be called + // by the service with the lock held, but let's be paranid. + synchronized (mLocationListeners) { + return mEnabledProviders.contains(getName()); + } } @Override @@ -2109,14 +2418,9 @@ public class LocationManagerService extends ILocationManager.Stub } } - private void checkMockPermissions() { - boolean allowMocks = false; - try { - allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), - Settings.Secure.ALLOW_MOCK_LOCATION) == 1; - } catch (SettingNotFoundException e) { - // Do nothing - } + private void checkMockPermissionsSafe() { + boolean allowMocks = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ALLOW_MOCK_LOCATION, 0) == 1; if (!allowMocks) { throw new SecurityException("Requires ACCESS_MOCK_LOCATION secure setting"); } @@ -2130,87 +2434,103 @@ public class LocationManagerService extends ILocationManager.Stub public void addTestProvider(String name, boolean requiresNetwork, boolean requiresSatellite, boolean requiresCell, boolean hasMonetaryCost, boolean supportsAltitude, boolean supportsSpeed, boolean supportsBearing, int powerRequirement, int accuracy) { - checkMockPermissions(); - - MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite, - requiresCell, hasMonetaryCost, supportsAltitude, - supportsSpeed, supportsBearing, powerRequirement, accuracy); - if (LocationProviderImpl.getProvider(name) != null) { - throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); + checkMockPermissionsSafe(); + + synchronized (mLocationListeners) { + MockProvider provider = new MockProvider(name, requiresNetwork, requiresSatellite, + requiresCell, hasMonetaryCost, supportsAltitude, + supportsSpeed, supportsBearing, powerRequirement, accuracy); + if (LocationProviderImpl.getProvider(name) != null) { + throw new IllegalArgumentException("Provider \"" + name + "\" already exists"); + } + LocationProviderImpl.addProvider(provider); + updateProvidersLocked(); } - LocationProviderImpl.addProvider(provider); - updateProviders(); } public void removeTestProvider(String provider) { - checkMockPermissions(); - LocationProviderImpl p = LocationProviderImpl.getProvider(provider); - if (p == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + LocationProviderImpl p = LocationProviderImpl.getProvider(provider); + if (p == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + LocationProviderImpl.removeProvider(p); + updateProvidersLocked(); } - LocationProviderImpl.removeProvider(p); - updateProviders(); } public void setTestProviderLocation(String provider, Location loc) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + mMockProviderLocation.put(provider, loc); } - mMockProviderLocation.put(provider, loc); } public void clearTestProviderLocation(String provider) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + mMockProviderLocation.remove(provider); } - mMockProviderLocation.remove(provider); } public void setTestProviderEnabled(String provider, boolean enabled) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); - } - if (enabled) { - mEnabledProviders.add(provider); - mDisabledProviders.remove(provider); - } else { - mEnabledProviders.remove(provider); - mDisabledProviders.add(provider); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + if (enabled) { + mEnabledProviders.add(provider); + mDisabledProviders.remove(provider); + } else { + mEnabledProviders.remove(provider); + mDisabledProviders.add(provider); + } + updateProvidersLocked(); } - updateProviders(); } public void clearTestProviderEnabled(String provider) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + mEnabledProviders.remove(provider); + mDisabledProviders.remove(provider); + updateProvidersLocked(); } - mEnabledProviders.remove(provider); - mDisabledProviders.remove(provider); - updateProviders(); } public void setTestProviderStatus(String provider, int status, Bundle extras, long updateTime) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + mMockProviderStatus.put(provider, new Integer(status)); + mMockProviderStatusExtras.put(provider, extras); + mMockProviderStatusUpdateTime.put(provider, new Long(updateTime)); } - mMockProviderStatus.put(provider, new Integer(status)); - mMockProviderStatusExtras.put(provider, extras); - mMockProviderStatusUpdateTime.put(provider, new Long(updateTime)); } public void clearTestProviderStatus(String provider) { - checkMockPermissions(); - if (LocationProviderImpl.getProvider(provider) == null) { - throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + checkMockPermissionsSafe(); + synchronized (mLocationListeners) { + if (LocationProviderImpl.getProvider(provider) == null) { + throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); + } + mMockProviderStatus.remove(provider); + mMockProviderStatusExtras.remove(provider); + mMockProviderStatusUpdateTime.remove(provider); } - mMockProviderStatus.remove(provider); - mMockProviderStatusExtras.remove(provider); - mMockProviderStatusUpdateTime.remove(provider); } private void log(String log) { @@ -2218,5 +2538,154 @@ public class LocationManagerService extends ILocationManager.Stub Log.d(TAG, log); } } + + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump AlarmManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + synchronized (mLocationListeners) { + pw.println("Current Location Manager state:"); + pw.println(" sProvidersLoaded=" + sProvidersLoaded); + pw.println(" mGpsLocationProvider=" + mGpsLocationProvider); + pw.println(" mGpsNavigating=" + mGpsNavigating); + pw.println(" mNetworkLocationProvider=" + mNetworkLocationProvider); + pw.println(" mNetworkLocationInterface=" + mNetworkLocationInterface); + pw.println(" mCollector=" + mCollector); + pw.println(" mSignalStrength=" + mSignalStrength); + pw.println(" mAlarmInterval=" + mAlarmInterval + + " mScreenOn=" + mScreenOn + + " mWakeLockAcquireTime=" + mWakeLockAcquireTime); + pw.println(" mWakeLockGpsReceived=" + mWakeLockGpsReceived + + " mWakeLockNetworkReceived=" + mWakeLockNetworkReceived); + pw.println(" mWifiWakeLockAcquired=" + mWifiWakeLockAcquired + + " mCellWakeLockAcquired=" + mCellWakeLockAcquired); + pw.println(" Listeners:"); + int N = mListeners.size(); + for (int i=0; i<N; i++) { + pw.println(" " + mListeners.get(i)); + } + pw.println(" Location Listeners:"); + for (Map.Entry<Receiver, HashMap<String,UpdateRecord>> i + : mLocationListeners.entrySet()) { + pw.println(" " + i.getKey() + ":"); + for (Map.Entry<String,UpdateRecord> j : i.getValue().entrySet()) { + pw.println(" " + j.getKey() + ":"); + j.getValue().dump(pw, " "); + } + } + pw.println(" Last Fix Broadcasts:"); + for (Map.Entry<Receiver, HashMap<String,Location>> i + : mLastFixBroadcast.entrySet()) { + pw.println(" " + i.getKey() + ":"); + for (Map.Entry<String,Location> j : i.getValue().entrySet()) { + pw.println(" " + j.getKey() + ":"); + j.getValue().dump(new PrintWriterPrinter(pw), " "); + } + } + pw.println(" Last Status Broadcasts:"); + for (Map.Entry<Receiver, HashMap<String,Long>> i + : mLastStatusBroadcast.entrySet()) { + pw.println(" " + i.getKey() + ":"); + for (Map.Entry<String,Long> j : i.getValue().entrySet()) { + pw.println(" " + j.getKey() + " -> 0x" + + Long.toHexString(j.getValue())); + } + } + pw.println(" Records by Provider:"); + for (Map.Entry<String, ArrayList<UpdateRecord>> i + : mRecordsByProvider.entrySet()) { + pw.println(" " + i.getKey() + ":"); + for (UpdateRecord j : i.getValue()) { + pw.println(" " + j + ":"); + 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()) { + pw.println(" " + i.getKey() + ":"); + i.getValue().dump(new PrintWriterPrinter(pw), " "); + } + if (mProximityAlerts.size() > 0) { + pw.println(" Proximity Alerts:"); + for (Map.Entry<PendingIntent, ProximityAlert> i + : mProximityAlerts.entrySet()) { + pw.println(" " + i.getKey() + ":"); + i.getValue().dump(pw, " "); + } + } + if (mProximitiesEntered.size() > 0) { + pw.println(" Proximities Entered:"); + for (ProximityAlert i : mProximitiesEntered) { + pw.println(" " + i + ":"); + i.dump(pw, " "); + } + } + pw.println(" mProximityListener=" + mProximityListener); + if (mEnabledProviders.size() > 0) { + pw.println(" Enabled Providers:"); + for (String i : mEnabledProviders) { + pw.println(" " + i); + } + + } + if (mDisabledProviders.size() > 0) { + pw.println(" Disabled Providers:"); + for (String i : mDisabledProviders) { + pw.println(" " + i); + } + + } + if (mMockProviders.size() > 0) { + pw.println(" Mock Providers:"); + for (Map.Entry<String, MockProvider> i : mMockProviders.entrySet()) { + pw.println(" " + i.getKey() + " -> " + i.getValue()); + } + } + if (mMockProviderLocation.size() > 0) { + pw.println(" Mock Provider Location:"); + for (Map.Entry<String, Location> i : mMockProviderLocation.entrySet()) { + pw.println(" " + i.getKey() + ":"); + i.getValue().dump(new PrintWriterPrinter(pw), " "); + } + } + if (mMockProviderStatus.size() > 0) { + pw.println(" Mock Provider Status:"); + for (Map.Entry<String, Integer> i : mMockProviderStatus.entrySet()) { + pw.println(" " + i.getKey() + " -> 0x" + + Integer.toHexString(i.getValue())); + } + } + if (mMockProviderStatusExtras.size() > 0) { + pw.println(" Mock Provider Status Extras:"); + for (Map.Entry<String, Bundle> i : mMockProviderStatusExtras.entrySet()) { + pw.println(" " + i.getKey() + " -> " + i.getValue()); + } + } + if (mMockProviderStatusUpdateTime.size() > 0) { + pw.println(" Mock Provider Status Update Time:"); + for (Map.Entry<String, Long> i : mMockProviderStatusUpdateTime.entrySet()) { + pw.println(" " + i.getKey() + " -> " + i.getValue()); + } + } + pw.println(" Reported GPS UIDs @ seq " + mReportedGpsSeq + ":"); + N = mReportedGpsUids.size(); + for (int i=0; i<N; i++) { + pw.println(" UID " + mReportedGpsUids.keyAt(i) + + " seq=" + mReportedGpsUids.valueAt(i)); + } + } + } } diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index 6974b5e..16b5819 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -182,6 +182,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private long mScreenOnTime; private long mScreenOnStartTime; private boolean mPreventScreenOn; + private int mScreenBrightnessOverride = -1; // Used when logging number and duration of touch-down cycles private long mTotalTouchDownTime; @@ -245,7 +246,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage public void acquire() { if (!mRefCounted || mCount++ == 0) { - PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken, mTag); + PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken, + MY_UID, mTag); } } @@ -486,17 +488,18 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage public void acquireWakeLock(int flags, IBinder lock, String tag) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null); + int uid = Binder.getCallingUid(); long ident = Binder.clearCallingIdentity(); try { synchronized (mLocks) { - acquireWakeLockLocked(flags, lock, tag); + acquireWakeLockLocked(flags, lock, uid, tag); } } finally { Binder.restoreCallingIdentity(ident); } } - public void acquireWakeLockLocked(int flags, IBinder lock, String tag) { + public void acquireWakeLockLocked(int flags, IBinder lock, int uid, String tag) { int acquireUid = -1; String acquireName = null; int acquireType = -1; @@ -509,7 +512,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage WakeLock wl; boolean newlock; if (index < 0) { - wl = new WakeLock(flags, lock, tag, Binder.getCallingUid()); + wl = new WakeLock(flags, lock, tag, uid); switch (wl.flags & LOCK_MASK) { case PowerManager.FULL_WAKE_LOCK: @@ -577,13 +580,10 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } if (acquireType >= 0) { - long origId = Binder.clearCallingIdentity(); try { mBatteryStats.noteStartWakelock(acquireUid, acquireName, acquireType); } catch (RemoteException e) { // Ignore - } finally { - Binder.restoreCallingIdentity(origId); } } } @@ -797,6 +797,8 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage + " mUserActivityAllowed=" + mUserActivityAllowed); pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay); + pw.println(" mPreventScreenOn=" + mPreventScreenOn + + " mScreenBrightnessOverride=" + mScreenBrightnessOverride); pw.println(" mTotalDelaySetting=" + mTotalDelaySetting); pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock); pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock); @@ -1077,7 +1079,6 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage * lock (rather than an IPowerManager call). */ public void preventScreenOn(boolean prevent) { - // TODO: use a totally new permission (separate from DEVICE_POWER) for this? mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); synchronized (mLocks) { @@ -1126,6 +1127,17 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } } + public void setScreenBrightnessOverride(int brightness) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null); + + synchronized (mLocks) { + if (mScreenBrightnessOverride != brightness) { + mScreenBrightnessOverride = brightness; + updateLightsLocked(mPowerState, SCREEN_ON_BIT); + } + } + } + /** * Sanity-check that gets called 5 seconds after any call to * preventScreenOn(true). This ensures that the original call @@ -1211,7 +1223,7 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage } if (mPowerState != newState) { - err = updateLightsLocked(newState, becauseOfUser); + err = updateLightsLocked(newState, 0); if (err != 0) { return; } @@ -1294,6 +1306,15 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mScreenOnTime += SystemClock.elapsedRealtime() - mScreenOnStartTime; mScreenOnStartTime = 0; if (err == 0) { + // + // FIXME(joeo) + // + // The problem that causes the screen not to come on is that this isn't + // called until after the animation is done. It needs to be set right + // away, and the anmiation's state needs to be recorded separately. + // + // + mPowerState &= ~SCREEN_ON_BIT; int why = becauseOfUser ? WindowManagerPolicy.OFF_BECAUSE_OF_USER @@ -1310,9 +1331,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD); } - private int updateLightsLocked(int newState, boolean becauseOfUser) { + private int updateLightsLocked(int newState, int forceState) { int oldState = mPowerState; - int difference = newState ^ oldState; + int difference = (newState ^ oldState) | forceState; if (difference == 0) { return 0; } @@ -1544,6 +1565,9 @@ class PowerManagerService extends IPowerManager.Stub implements LocalPowerManage private int getPreferredBrightness() { try { + if (mScreenBrightnessOverride >= 0) { + return mScreenBrightnessOverride; + } final int brightness = Settings.System.getInt(mContext.getContentResolver(), SCREEN_BRIGHTNESS); // Don't let applications turn the screen all the way off diff --git a/services/java/com/android/server/SensorService.java b/services/java/com/android/server/SensorService.java index 461b006..29b45ab 100644 --- a/services/java/com/android/server/SensorService.java +++ b/services/java/com/android/server/SensorService.java @@ -113,9 +113,9 @@ class SensorService extends ISensorService.Stub { int uid = Binder.getCallingUid(); long identity = Binder.clearCallingIdentity(); if (enable == SENSOR_DISABLE) { - mBatteryStats.noteStopSensor(uid, name, sensor); + mBatteryStats.noteStopSensor(uid, sensor); } else { - mBatteryStats.noteStartSensor(uid, name, sensor); + mBatteryStats.noteStartSensor(uid, sensor); } Binder.restoreCallingIdentity(identity); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index d624573..fc25e38 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -181,6 +181,7 @@ class ServerThread extends Thread { StatusBarService statusBar = null; InputMethodManagerService imm = null; + GadgetService gadget = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { @@ -309,7 +310,8 @@ class ServerThread extends Thread { try { Log.i(TAG, "Starting Gadget Service"); - ServiceManager.addService(Context.GADGET_SERVICE, new GadgetService(context)); + gadget = new GadgetService(context); + ServiceManager.addService(Context.GADGET_SERVICE, gadget); } catch (Throwable e) { Log.e(TAG, "Failure starting Gadget Service", e); } @@ -337,6 +339,9 @@ class ServerThread extends Thread { pm.systemReady(); } catch (RemoteException e) { } + if (gadget != null) { + gadget.systemReady(safeMode); + } // After making the following code, third party code may be running... try { diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index fed6d12..fc22bad 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -66,6 +66,7 @@ import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.os.ParcelFileDescriptor; +import android.os.Power; import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; @@ -326,6 +327,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo long mFreezeGcPending = 0; int mAppsFreezingScreen = 0; + // This is held as long as we have the screen frozen, to give us time to + // perform a rotation animation when turning off shows the lock screen which + // changes the orientation. + PowerManager.WakeLock mScreenFrozenLock; + // State management of app transitions. When we are preparing for a // transition, mNextAppTransition will be the kind of transition to // perform or TRANSIT_NONE if we are not waiting. If we are waiting, @@ -351,6 +357,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // This just indicates the window the input method is on top of, not // necessarily the window its input is going to. WindowState mInputMethodTarget = null; + WindowState mUpcomingInputMethodTarget = null; boolean mInputMethodTargetWaitingAnim; int mInputMethodAnimLayerAdjustment; @@ -472,6 +479,10 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mPowerManager = pm; mPowerManager.setPolicy(mPolicy); + PowerManager pmc = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mScreenFrozenLock = pmc.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, + "SCREEN_FROZEN"); + mScreenFrozenLock.setReferenceCounted(false); mActivityManager = ActivityManagerNative.getDefault(); mBatteryStats = BatteryStatsService.getService(); @@ -742,6 +753,15 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } } + static boolean canBeImeTarget(WindowState w) { + final int fl = w.mAttrs.flags + & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); + if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) { + return w.isVisibleOrAdding(); + } + return false; + } + int findDesiredInputMethodWindowIndexLocked(boolean willMove) { final ArrayList localmWindows = mWindows; final int N = localmWindows.size(); @@ -750,18 +770,32 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo while (i > 0) { i--; w = (WindowState)localmWindows.get(i); - final int fl = w.mAttrs.flags - & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM); + //Log.i(TAG, "Checking window @" + i + " " + w + " fl=0x" - // + Integer.toHexString(fl)); - if (fl == 0 || fl == (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM)) { + // + Integer.toHexString(w.mAttrs.flags)); + if (canBeImeTarget(w)) { //Log.i(TAG, "Putting input method here!"); - if (w.isVisibleOrAdding()) { - break; + + // Yet more tricksyness! If this window is a "starting" + // window, we do actually want to be on top of it, but + // it is not -really- where input will go. So if the caller + // is not actually looking to move the IME, look down below + // for a real window to target... + if (!willMove + && w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING + && i > 0) { + WindowState wb = (WindowState)localmWindows.get(i-1); + if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) { + i--; + w = wb; + } } + break; } } + mUpcomingInputMethodTarget = w; + if (DEBUG_INPUT_METHOD) Log.v(TAG, "Desired input method target=" + w + " willMove=" + willMove); @@ -1209,8 +1243,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo addWindowToListInOrderLocked(win, true); } - Binder.restoreCallingIdentity(origId); - win.mEnterAnimationPending = true; mPolicy.getContentInsetHintLw(attrs, outContentInsets); @@ -1542,6 +1574,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo && !win.mCommitDrawPending && !mDisplayFrozen) { applyEnterAnimationLocked(win); } + if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) { + // To change the format, we need to re-build the surface. + win.destroySurfaceLocked(); + displayed = true; + } try { Surface surface = win.createSurfaceLocked(); if (surface != null) { @@ -7169,11 +7206,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // The focus for the client is the window immediately below // where we would place the input method window. int idx = findDesiredInputMethodWindowIndexLocked(false); + WindowState imFocus; if (idx > 0) { - WindowState imFocus = (WindowState)mWindows.get(idx-1); - if (imFocus != null && imFocus.mSession.mClient != null && - imFocus.mSession.mClient.asBinder() == client.asBinder()) { - return true; + imFocus = (WindowState)mWindows.get(idx-1); + if (imFocus != null) { + if (imFocus.mSession.mClient != null && + imFocus.mSession.mClient.asBinder() == client.asBinder()) { + return true; + } } } } @@ -7393,6 +7433,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean orientationChangeComplete = true; Session holdScreen = null; + float screenBrightness = -1; boolean focusDisplayed = false; boolean animating = false; @@ -7622,7 +7663,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean blurring = false; boolean dimming = false; boolean covered = false; - int tint = 0; for (i=N-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); @@ -7878,9 +7918,13 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // Update effect. if (!obscured) { - if (w.mSurface != null && - (attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { - holdScreen = w.mSession; + if (w.mSurface != null) { + if ((attrFlags&FLAG_KEEP_SCREEN_ON) != 0) { + holdScreen = w.mSession; + } + if (w.mAttrs.screenBrightness >= 0 && screenBrightness < 0) { + screenBrightness = w.mAttrs.screenBrightness; + } } if (w.isFullscreenOpaque(dw, dh)) { // This window completely covers everything behind it, @@ -8122,6 +8166,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis()); } mQueue.setHoldScreenLocked(holdScreen != null); + if (screenBrightness < 0 || screenBrightness > 1.0f) { + mPowerManager.setScreenBrightnessOverride(-1); + } else { + mPowerManager.setScreenBrightnessOverride((int) + (screenBrightness * Power.BRIGHTNESS_ON)); + } if (holdScreen != mHoldingScreenOn) { mHoldingScreenOn = holdScreen; Message m = mH.obtainMessage(H.HOLD_SCREEN_CHANGED, holdScreen); @@ -8354,6 +8404,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return; } + mScreenFrozenLock.acquire(); + long now = SystemClock.uptimeMillis(); //Log.i(TAG, "Freezing, gc pending: " + mFreezeGcPending + ", now " + now); if (mFreezeGcPending != 0) { @@ -8409,6 +8461,8 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo mH.removeMessages(H.FORCE_GC); mH.sendMessageDelayed(mH.obtainMessage(H.FORCE_GC), 2000); + + mScreenFrozenLock.release(); } @Override diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index e391da3..6443d53 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -204,6 +204,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen */ static final int LAUNCH_TIMEOUT = 10*1000; + // How long we wait for a launched process to attach to the activity manager + // before we decide it's never going to come up for real. + static final int PROC_START_TIMEOUT = 10*1000; + // How long we wait until giving up on the last activity telling us it // is idle. static final int IDLE_TIMEOUT = 10*1000; @@ -811,6 +815,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen static final int DESTROY_TIMEOUT_MSG = 17; static final int SERVICE_ERROR_MSG = 18; static final int RESUME_TOP_ACTIVITY_MSG = 19; + static final int PROC_START_TIMEOUT_MSG = 20; AlertDialog mUidAlert; @@ -852,12 +857,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } break; case SHOW_NOT_RESPONDING_MSG: { - HashMap data = (HashMap) msg.obj; - // This needs to be *un*synchronized to avoid deadlock. - Checkin.logEvent(mContext.getContentResolver(), - Checkin.Events.Tag.SYSTEM_APP_NOT_RESPONDING, - (String)data.get("info")); synchronized (ActivityManagerService.this) { + HashMap data = (HashMap) msg.obj; ProcessRecord proc = (ProcessRecord)data.get("app"); if (proc != null && proc.anrDialog != null) { Log.e(TAG, "App already has anr dialog: " + proc); @@ -993,6 +994,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen resumeTopActivityLocked(null); } } + case PROC_START_TIMEOUT_MSG: { + ProcessRecord app = (ProcessRecord)msg.obj; + synchronized (ActivityManagerService.this) { + processStartTimedOutLocked(app); + } + } } } }; @@ -1685,6 +1692,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen if (app.pid > 0 && app.pid != MY_PID) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); + mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } app.pid = 0; } @@ -1777,6 +1785,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen app.removed = false; synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(pid, app); + Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); + msg.obj = app; + mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT); } } else { app.pid = 0; @@ -4033,9 +4044,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen info.append("\nCPU usage:\n"); info.append(processInfo); } - info.append("\n/proc/meminfo:\n"); - info.append(readFile("/proc/meminfo")); - Log.i(TAG, info.toString()); // The application is not responding. Dump as many thread traces as we can. @@ -4087,7 +4095,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen msg.what = SHOW_NOT_RESPONDING_MSG; msg.obj = map; map.put("app", app); - map.put("info", info.toString()); if (activity != null) { map.put("activity", activity); } @@ -4390,6 +4397,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen int pid = app.pid; synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(pid); + mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } handleAppDiedLocked(app, true); mLRUProcesses.remove(app); @@ -4409,6 +4417,31 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return needRestart; } + private final void processStartTimedOutLocked(ProcessRecord app) { + final int pid = app.pid; + boolean gone = false; + synchronized (mPidsSelfLocked) { + ProcessRecord knownApp = mPidsSelfLocked.get(pid); + if (knownApp != null && knownApp.thread == null) { + mPidsSelfLocked.remove(pid); + gone = true; + } + } + + if (gone) { + Log.w(TAG, "Process " + app + " failed to attach"); + mProcessNames.remove(app.processName, app.info.uid); + Process.killProcess(pid); + if (mPendingBroadcast.curApp.pid == pid) { + Log.w(TAG, "Unattached app died before broadcast acknowledged, skipping"); + mPendingBroadcast = null; + scheduleBroadcastsLocked(); + } + } else { + Log.w(TAG, "Spurious process start timeout - pid not known for " + app); + } + } + private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { @@ -4472,6 +4505,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen app.foregroundServices = false; app.debugging = false; + mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); + List providers = generateApplicationProvidersLocked(app); if (localLOGV) Log.v( @@ -8630,6 +8665,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // Goodbye! synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); + mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } app.pid = 0; } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 1cd6298..9ba1198 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -22,8 +22,10 @@ import com.android.internal.os.BatteryStatsImpl; import android.content.Context; import android.os.Binder; import android.os.IBinder; +import android.os.Parcel; import android.os.Process; import android.os.ServiceManager; +import android.util.PrintWriterPrinter; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -58,16 +60,25 @@ public final class BatteryStatsService extends IBatteryStats.Stub { /** * @return the current statistics object, which may be modified - * to reflect events that affect battery usage. + * to reflect events that affect battery usage. You must lock the + * stats object before doing anything with it. */ public BatteryStatsImpl getActiveStatistics() { return mStats; } - public BatteryStatsImpl getStatistics() { + public byte[] getStatistics() { mContext.enforceCallingPermission( android.Manifest.permission.BATTERY_STATS, null); - return mStats; + synchronized (mStats) { + //Log.i("foo", "SENDING BATTERY INFO:"); + //mStats.dumpLocked(new LogPrinter(Log.INFO, "foo")); + Parcel out = Parcel.obtain(); + mStats.writeToParcel(out, 0); + byte[] data = out.marshall(); + out.recycle(); + return data; + } } public void noteStartWakelock(int uid, String name, int type) { @@ -84,17 +95,17 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } - public void noteStartSensor(int uid, String name, int sensor) { + public void noteStartSensor(int uid, int sensor) { enforceCallingPermission(); synchronized (mStats) { - mStats.getUidStatsLocked(uid).noteStartSensor(name, sensor); + mStats.getUidStatsLocked(uid).noteStartSensor(sensor); } } - public void noteStopSensor(int uid, String name, int sensor) { + public void noteStopSensor(int uid, int sensor) { enforceCallingPermission(); synchronized (mStats) { - mStats.getUidStatsLocked(uid).noteStopSensor(name, sensor); + mStats.getUidStatsLocked(uid).noteStopSensor(sensor); } } @@ -111,32 +122,18 @@ public final class BatteryStatsService extends IBatteryStats.Stub { mStats.noteStopGps(uid); } } - - public void noteRequestGpsOn(int uid) { - enforceCallingPermission(); - synchronized (mStats) { - mStats.noteRequestGpsOn(uid); - } - } - - public void noteRequestGpsOff(int uid) { - enforceCallingPermission(); - synchronized (mStats) { - mStats.noteRequestGpsOff(uid); - } - } - + public void noteScreenOn() { enforceCallingPermission(); synchronized (mStats) { - mStats.noteScreenOn(); + mStats.noteScreenOnLocked(); } } public void noteScreenOff() { enforceCallingPermission(); synchronized (mStats) { - mStats.noteScreenOff(); + mStats.noteScreenOffLocked(); } } @@ -171,8 +168,18 @@ public final class BatteryStatsService extends IBatteryStats.Stub { @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - synchronized (this) { - mStats.dumpLocked(fd, pw, args); + synchronized (mStats) { + boolean isCheckin = false; + if (args != null) { + for (String arg : args) { + if ("-c".equals(arg)) { + isCheckin = true; + break; + } + } + } + if (isCheckin) mStats.dumpCheckinLocked(pw, args); + else mStats.dumpLocked(new PrintWriterPrinter(pw)); } } } diff --git a/services/java/com/android/server/status/AnimatedImageView.java b/services/java/com/android/server/status/AnimatedImageView.java index 36492da..cd581c4 100644 --- a/services/java/com/android/server/status/AnimatedImageView.java +++ b/services/java/com/android/server/status/AnimatedImageView.java @@ -42,6 +42,7 @@ public class AnimatedImageView extends ImageView { } @Override + @android.view.RemotableViewMethod public void setImageResource(int resid) { super.setImageResource(resid); updateAnim(); diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java index a4844b1..4748389 100644 --- a/services/java/com/android/server/status/StatusBarService.java +++ b/services/java/com/android/server/status/StatusBarService.java @@ -27,6 +27,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageManager; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; @@ -1326,80 +1327,89 @@ public class StatusBarService extends IStatusBar.Stub } protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump StatusBar from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + synchronized (mQueue) { - pw.println("mExpanded=" + mExpanded + pw.println("Current Status Bar state:"); + pw.println(" mExpanded=" + mExpanded + ", mExpandedVisible=" + mExpandedVisible); - pw.println("mTicking=" + mTicking); - pw.println("mTracking=" + mTracking); - pw.println("mAnimating=" + mAnimating + pw.println(" mTicking=" + mTicking); + pw.println(" mTracking=" + mTracking); + pw.println(" mAnimating=" + mAnimating + ", mAnimY=" + mAnimY + ", mAnimVel=" + mAnimVel + ", mAnimAccel=" + mAnimAccel); - pw.println("mCurAnimationTime=" + mCurAnimationTime + pw.println(" mCurAnimationTime=" + mCurAnimationTime + " mAnimLastTime=" + mAnimLastTime); - pw.println("mDisplayHeight=" + mDisplayHeight + pw.println(" mDisplayHeight=" + mDisplayHeight + " mAnimatingReveal=" + mAnimatingReveal + " mViewDelta=" + mViewDelta); - pw.println("mDisplayHeight=" + mDisplayHeight); + pw.println(" mDisplayHeight=" + mDisplayHeight); final int N = mQueue.size(); - pw.println("mQueue.size=" + N); + pw.println(" mQueue.size=" + N); for (int i=0; i<N; i++) { PendingOp op = mQueue.get(i); - pw.println(" [" + i + "] key=" + op.key + " code=" + op.code + " visible=" + pw.println(" [" + i + "] key=" + op.key + " code=" + op.code + " visible=" + op.visible); - pw.println(" iconData=" + op.iconData); - pw.println(" notificationData=" + op.notificationData); + pw.println(" iconData=" + op.iconData); + pw.println(" notificationData=" + op.notificationData); } - pw.println("mExpandedParams: " + mExpandedParams); - pw.println("mExpandedView: " + viewInfo(mExpandedView)); - pw.println("mExpandedDialog: " + mExpandedDialog); - pw.println("mTrackingParams: " + mTrackingParams); - pw.println("mTrackingView: " + viewInfo(mTrackingView)); - pw.println("mOngoingTitle: " + viewInfo(mOngoingTitle)); - pw.println("mOngoingItems: " + viewInfo(mOngoingItems)); - pw.println("mLatestTitle: " + viewInfo(mLatestTitle)); - pw.println("mLatestItems: " + viewInfo(mLatestItems)); - pw.println("mNoNotificationsTitle: " + viewInfo(mNoNotificationsTitle)); - pw.println("mCloseView: " + viewInfo(mCloseView)); - pw.println("mTickerView: " + viewInfo(mTickerView)); - pw.println("mScrollView: " + viewInfo(mScrollView) + pw.println(" mExpandedParams: " + mExpandedParams); + pw.println(" mExpandedView: " + viewInfo(mExpandedView)); + pw.println(" mExpandedDialog: " + mExpandedDialog); + pw.println(" mTrackingParams: " + mTrackingParams); + pw.println(" mTrackingView: " + viewInfo(mTrackingView)); + pw.println(" mOngoingTitle: " + viewInfo(mOngoingTitle)); + pw.println(" mOngoingItems: " + viewInfo(mOngoingItems)); + pw.println(" mLatestTitle: " + viewInfo(mLatestTitle)); + pw.println(" mLatestItems: " + viewInfo(mLatestItems)); + pw.println(" mNoNotificationsTitle: " + viewInfo(mNoNotificationsTitle)); + pw.println(" mCloseView: " + viewInfo(mCloseView)); + pw.println(" mTickerView: " + viewInfo(mTickerView)); + pw.println(" mScrollView: " + viewInfo(mScrollView) + " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY()); pw.println("mNotificationLinearLayout: " + viewInfo(mNotificationLinearLayout)); } synchronized (mIconMap) { final int N = mIconMap.size(); - pw.println("mIconMap.size=" + N); + pw.println(" mIconMap.size=" + N); Set<IBinder> keys = mIconMap.keySet(); int i=0; for (IBinder key: keys) { StatusBarIcon icon = mIconMap.get(key); - pw.println(" [" + i + "] key=" + key); - pw.println(" data=" + icon.mData); + pw.println(" [" + i + "] key=" + key); + pw.println(" data=" + icon.mData); i++; } } synchronized (mNotificationData) { int N = mNotificationData.ongoingCount(); - pw.println("ongoingCount.size=" + N); + pw.println(" ongoingCount.size=" + N); for (int i=0; i<N; i++) { StatusBarNotification n = mNotificationData.getOngoing(i); - pw.println(" [" + i + "] key=" + n.key + " view=" + n.view); - pw.println(" data=" + n.data); + pw.println(" [" + i + "] key=" + n.key + " view=" + n.view); + pw.println(" data=" + n.data); } N = mNotificationData.latestCount(); - pw.println("ongoingCount.size=" + N); + pw.println(" ongoingCount.size=" + N); for (int i=0; i<N; i++) { StatusBarNotification n = mNotificationData.getLatest(i); - pw.println(" [" + i + "] key=" + n.key + " view=" + n.view); - pw.println(" data=" + n.data); + pw.println(" [" + i + "] key=" + n.key + " view=" + n.view); + pw.println(" data=" + n.data); } } synchronized (mDisableRecords) { final int N = mDisableRecords.size(); - pw.println("mDisableRecords.size=" + N + pw.println(" mDisableRecords.size=" + N + " mDisabled=0x" + Integer.toHexString(mDisabled)); for (int i=0; i<N; i++) { DisableRecord tok = mDisableRecords.get(i); - pw.println(" [" + i + "] what=0x" + Integer.toHexString(tok.what) + pw.println(" [" + i + "] what=0x" + Integer.toHexString(tok.what) + " pkg=" + tok.pkg + " token=" + tok.token); } } |