diff options
-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}); + } } } } |