summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDianne Hackborn <hackbod@google.com>2010-05-04 17:22:49 -0700
committerDianne Hackborn <hackbod@google.com>2010-05-04 17:22:49 -0700
commit4416c3d6e4becd9ed39b89a03db0239c8225a135 (patch)
treeee83724da376bd99e2a35880c87522a20e2572da
parent5e5202bd6f9e7687fc6399762529b0ef5625e515 (diff)
downloadframeworks_base-4416c3d6e4becd9ed39b89a03db0239c8225a135.zip
frameworks_base-4416c3d6e4becd9ed39b89a03db0239c8225a135.tar.gz
frameworks_base-4416c3d6e4becd9ed39b89a03db0239c8225a135.tar.bz2
Fix issue #2643754: Launcher is caching widget layouts for too long
With the .apk file names now changing during an update, we need to make sure to flush all caches related to a package when the package is removed. Otherwise we can continue to use the old package, since its old file may still exist if we try to load it too soon. Change-Id: I15f08dffca3feac999dbca4f24bef12a30ca0a66
-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});
+ }
}
}
}