summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-02-19 10:57:31 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-02-19 10:57:31 -0800
commit3001a035439d8134a7d70d796376d1dfbff3cdcd (patch)
tree343ccdba15a594ff6e50c874a145232753315a30 /services
parentda996f390e17e16f2dfa60e972e7ebc4f868f37e (diff)
downloadframeworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.zip
frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.gz
frameworks_base-3001a035439d8134a7d70d796376d1dfbff3cdcd.tar.bz2
auto import from //branches/cupcake/...@132276
Diffstat (limited to 'services')
-rw-r--r--services/java/com/android/server/BatteryService.java7
-rw-r--r--services/java/com/android/server/DeviceStorageMonitorService.java58
-rw-r--r--services/java/com/android/server/GadgetService.java97
-rw-r--r--services/java/com/android/server/InputMethodManagerService.java7
-rw-r--r--services/java/com/android/server/LocationManagerService.java1453
-rw-r--r--services/java/com/android/server/PowerManagerService.java46
-rw-r--r--services/java/com/android/server/SensorService.java4
-rw-r--r--services/java/com/android/server/SystemServer.java7
-rw-r--r--services/java/com/android/server/WindowManagerService.java86
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java54
-rw-r--r--services/java/com/android/server/am/BatteryStatsService.java59
-rw-r--r--services/java/com/android/server/status/AnimatedImageView.java1
-rw-r--r--services/java/com/android/server/status/StatusBarService.java80
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);
}
}