diff options
author | Dianne Hackborn <hackbod@google.com> | 2010-05-04 17:22:49 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2010-05-04 17:22:49 -0700 |
commit | 4416c3d6e4becd9ed39b89a03db0239c8225a135 (patch) | |
tree | ee83724da376bd99e2a35880c87522a20e2572da | |
parent | 5e5202bd6f9e7687fc6399762529b0ef5625e515 (diff) | |
download | frameworks_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.java | 62 | ||||
-rw-r--r-- | core/java/android/app/ApplicationThreadNative.java | 20 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 87 | ||||
-rw-r--r-- | core/java/android/app/IApplicationThread.java | 4 | ||||
-rw-r--r-- | services/java/com/android/server/am/ActivityManagerService.java | 18 |
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}); + } } } } |