summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/ActivityThread.java62
-rw-r--r--core/java/android/app/ApplicationThreadNative.java20
-rw-r--r--core/java/android/app/ContextImpl.java87
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java18
5 files changed, 106 insertions, 85 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index fd84859..773c344 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -194,6 +194,7 @@ public final class ActivityThread {
}
WeakReference<Resources> wr = mActiveResources.get(key);
r = wr != null ? wr.get() : null;
+ //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
if (r != null && r.getAssets().isUpToDate()) {
if (false) {
Slog.w(TAG, "Returning cached resources " + r + " " + resDir
@@ -1752,6 +1753,10 @@ public final class ActivityThread {
Debug.getMemoryInfo(outInfo);
}
+ public void dispatchPackageBroadcast(int cmd, String[] packages) {
+ queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
+ }
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
@@ -1976,6 +1981,7 @@ public final class ActivityThread {
public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132;
+ public static final int DISPATCH_PACKAGE_BROADCAST = 133;
String codeToString(int code) {
if (localLOGV) {
switch (code) {
@@ -2012,6 +2018,7 @@ public final class ActivityThread {
case SUICIDE: return "SUICIDE";
case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
case ENABLE_JIT: return "ENABLE_JIT";
+ case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
}
}
return "(unknown)";
@@ -2132,6 +2139,9 @@ public final class ActivityThread {
case ENABLE_JIT:
ensureJitEnabled();
break;
+ case DISPATCH_PACKAGE_BROADCAST:
+ handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
+ break;
}
}
@@ -2239,16 +2249,16 @@ public final class ActivityThread {
// XXX For now we keep around information about all packages we have
// seen, not removing entries from this map.
final HashMap<String, WeakReference<PackageInfo>> mPackages
- = new HashMap<String, WeakReference<PackageInfo>>();
+ = new HashMap<String, WeakReference<PackageInfo>>();
final HashMap<String, WeakReference<PackageInfo>> mResourcePackages
- = new HashMap<String, WeakReference<PackageInfo>>();
+ = new HashMap<String, WeakReference<PackageInfo>>();
Display mDisplay = null;
DisplayMetrics mDisplayMetrics = null;
- HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
- = new HashMap<ResourcesKey, WeakReference<Resources> >();
+ final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
+ = new HashMap<ResourcesKey, WeakReference<Resources> >();
final ArrayList<ActivityRecord> mRelaunchingActivities
= new ArrayList<ActivityRecord>();
- Configuration mPendingConfiguration = null;
+ Configuration mPendingConfiguration = null;
// The lock of mProviderMap protects the following variables.
final HashMap<String, ProviderRecord> mProviderMap
@@ -2271,6 +2281,8 @@ public final class ActivityThread {
}
PackageInfo packageInfo = ref != null ? ref.get() : null;
//Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo);
+ //if (packageInfo != null) Slog.i(TAG, "isUptoDate " + packageInfo.mResDir
+ // + ": " + packageInfo.mResources.getAssets().isUpToDate());
if (packageInfo != null && (packageInfo.mResources == null
|| packageInfo.mResources.getAssets().isUpToDate())) {
if (packageInfo.isSecurityViolation()
@@ -2358,21 +2370,6 @@ public final class ActivityThread {
}
}
- public final boolean hasPackageInfo(String packageName) {
- synchronized (mPackages) {
- WeakReference<PackageInfo> ref;
- ref = mPackages.get(packageName);
- if (ref != null && ref.get() != null) {
- return true;
- }
- ref = mResourcePackages.get(packageName);
- if (ref != null && ref.get() != null) {
- return true;
- }
- return false;
- }
- }
-
ActivityThread() {
}
@@ -4054,6 +4051,31 @@ public final class ActivityThread {
}
}
+ final void handleDispatchPackageBroadcast(int cmd, String[] packages) {
+ boolean hasPkgInfo = false;
+ if (packages != null) {
+ for (int i=packages.length-1; i>=0; i--) {
+ //Slog.i(TAG, "Cleaning old package: " + packages[i]);
+ if (!hasPkgInfo) {
+ WeakReference<PackageInfo> ref;
+ ref = mPackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ } else {
+ ref = mResourcePackages.get(packages[i]);
+ if (ref != null && ref.get() != null) {
+ hasPkgInfo = true;
+ }
+ }
+ }
+ mPackages.remove(packages[i]);
+ mResourcePackages.remove(packages[i]);
+ }
+ }
+ ContextImpl.ApplicationPackageManager.handlePackageBroadcast(cmd, packages,
+ hasPkgInfo);
+ }
+
final void handleLowMemory() {
ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>();
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index 7cba13f..da26a78 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -393,6 +393,15 @@ public abstract class ApplicationThreadNative extends Binder
mi.writeToParcel(reply, 0);
return true;
}
+
+ case DISPATCH_PACKAGE_BROADCAST_TRANSACTION:
+ {
+ data.enforceInterface(IApplicationThread.descriptor);
+ int cmd = data.readInt();
+ String[] packages = data.readStringArray();
+ dispatchPackageBroadcast(cmd, packages);
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
@@ -806,5 +815,16 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle();
reply.recycle();
}
+
+ public void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken(IApplicationThread.descriptor);
+ data.writeInt(cmd);
+ data.writeStringArray(packages);
+ mRemote.transact(DISPATCH_PACKAGE_BROADCAST_TRANSACTION, data, null,
+ IBinder.FLAG_ONEWAY);
+ data.recycle();
+
+ }
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index fd0edaa..f471f57 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2244,33 +2244,7 @@ class ContextImpl extends Context {
return null;
}
- private void establishPackageRemovedReceiver() {
- // mContext.registerReceiverInternal() winds up acquiring the
- // main ActivityManagerService.this lock. If we hold our usual
- // sSync global lock at the same time, we impose a required ordering
- // on those two locks, which is not good for deadlock prevention.
- // Use a dedicated lock around initialization of
- // sPackageRemovedReceiver to avoid this.
- synchronized (sPackageRemovedSync) {
- if (sPackageRemovedReceiver == null) {
- sPackageRemovedReceiver = new PackageRemovedReceiver();
- IntentFilter filter = new IntentFilter(
- Intent.ACTION_PACKAGE_REMOVED);
- filter.addDataScheme("package");
- mContext.registerReceiverInternal(sPackageRemovedReceiver,
- filter, null, null, null);
- // Register for events related to sdcard installation.
- IntentFilter sdFilter = new IntentFilter();
- sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
- mContext.registerReceiverInternal(sPackageRemovedReceiver,
- sdFilter, null, null, null);
- }
- }
- }
-
private void putCachedIcon(ResourceName name, Drawable dr) {
- establishPackageRemovedReceiver();
-
synchronized (sSync) {
sIconCache.put(name, new WeakReference<Drawable>(dr));
if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
@@ -2278,29 +2252,17 @@ class ContextImpl extends Context {
}
}
- private static final class PackageRemovedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- String pkgList[] = null;
- String action = intent.getAction();
- boolean immediateGc = false;
- if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
- pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- immediateGc = true;
- } else {
- Uri data = intent.getData();
- if (data != null) {
- String ssp = data.getSchemeSpecificPart();
- if (ssp != null) {
- pkgList = new String[] { ssp };
- }
- }
- }
- if (pkgList != null && (pkgList.length > 0)) {
- boolean needCleanup = false;
- boolean hasPkgInfo = false;
- for (String ssp : pkgList) {
- synchronized (sSync) {
+ static final void handlePackageBroadcast(int cmd, String[] pkgList,
+ boolean hasPkgInfo) {
+ boolean immediateGc = false;
+ if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
+ immediateGc = true;
+ }
+ if (pkgList != null && (pkgList.length > 0)) {
+ boolean needCleanup = false;
+ for (String ssp : pkgList) {
+ synchronized (sSync) {
+ if (sIconCache.size() > 0) {
Iterator<ResourceName> it = sIconCache.keySet().iterator();
while (it.hasNext()) {
ResourceName nm = it.next();
@@ -2310,7 +2272,9 @@ class ContextImpl extends Context {
needCleanup = true;
}
}
- it = sStringCache.keySet().iterator();
+ }
+ if (sStringCache.size() > 0) {
+ Iterator<ResourceName> it = sStringCache.keySet().iterator();
while (it.hasNext()) {
ResourceName nm = it.next();
if (nm.packageName.equals(ssp)) {
@@ -2320,22 +2284,19 @@ class ContextImpl extends Context {
}
}
}
- if (!hasPkgInfo) {
- hasPkgInfo = ActivityThread.currentActivityThread().hasPackageInfo(ssp);
- }
}
- if (needCleanup || hasPkgInfo) {
- if (immediateGc) {
- // Schedule an immediate gc.
- Runtime.getRuntime().gc();
- } else {
- ActivityThread.currentActivityThread().scheduleGcIdler();
- }
+ }
+ if (needCleanup || hasPkgInfo) {
+ if (immediateGc) {
+ // Schedule an immediate gc.
+ Runtime.getRuntime().gc();
+ } else {
+ ActivityThread.currentActivityThread().scheduleGcIdler();
}
}
}
}
-
+
private static final class ResourceName {
final String packageName;
final int iconId;
@@ -2400,8 +2361,6 @@ class ContextImpl extends Context {
}
private void putCachedString(ResourceName name, CharSequence cs) {
- establishPackageRemovedReceiver();
-
synchronized (sSync) {
sStringCache.put(name, new WeakReference<CharSequence>(cs));
}
@@ -2665,8 +2624,6 @@ class ContextImpl extends Context {
private final IPackageManager mPM;
private static final Object sSync = new Object();
- private static final Object sPackageRemovedSync = new Object();
- private static BroadcastReceiver sPackageRemovedReceiver;
private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
= new HashMap<ResourceName, WeakReference<Drawable> >();
private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index ed810d3..c917e81 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -100,6 +100,9 @@ public interface IApplicationThread extends IInterface {
throws RemoteException;
void setSchedulingGroup(int group) throws RemoteException;
void getMemoryInfo(Debug.MemoryInfo outInfo) throws RemoteException;
+ static final int PACKAGE_REMOVED = 0;
+ static final int EXTERNAL_STORAGE_UNAVAILABLE = 1;
+ void dispatchPackageBroadcast(int cmd, String[] packages) throws RemoteException;
String descriptor = "android.app.IApplicationThread";
@@ -135,4 +138,5 @@ public interface IApplicationThread extends IInterface {
int SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
+ int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 8383ca3..706e15a 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -12269,6 +12269,18 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
+ private final void sendPackageBroadcastLocked(int cmd, String[] packages) {
+ for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) {
+ ProcessRecord r = mLruProcesses.get(i);
+ if (r.thread != null) {
+ try {
+ r.thread.dispatchPackageBroadcast(cmd, packages);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+ }
+
private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData,
@@ -12315,6 +12327,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
for (String pkg : list) {
forceStopPackageLocked(pkg, -1, false, true, true);
}
+ sendPackageBroadcastLocked(
+ IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
}
} else {
Uri data = intent.getData();
@@ -12324,6 +12338,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
forceStopPackageLocked(ssp,
intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
}
+ if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
+ sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
+ new String[] {ssp});
+ }
}
}
}