am 3445dae3: am 65b2561c: Merge "Fix issue #2643754: Launcher is caching widget layouts for too long" into froyo

Merge commit '3445dae3f52fa8421e3b93496ac93c5753a43bd2' into kraken

* commit '3445dae3f52fa8421e3b93496ac93c5753a43bd2':
  Fix issue #2643754: Launcher is caching widget layouts for too long
This commit is contained in:
Dianne Hackborn
2010-05-04 18:30:51 -07:00
committed by Android Git Automerger
5 changed files with 106 additions and 85 deletions

View File

@ -194,6 +194,7 @@ public final class ActivityThread {
} }
WeakReference<Resources> wr = mActiveResources.get(key); WeakReference<Resources> wr = mActiveResources.get(key);
r = wr != null ? wr.get() : null; r = wr != null ? wr.get() : null;
//if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
if (r != null && r.getAssets().isUpToDate()) { if (r != null && r.getAssets().isUpToDate()) {
if (false) { if (false) {
Slog.w(TAG, "Returning cached resources " + r + " " + resDir Slog.w(TAG, "Returning cached resources " + r + " " + resDir
@ -1752,6 +1753,10 @@ public final class ActivityThread {
Debug.getMemoryInfo(outInfo); Debug.getMemoryInfo(outInfo);
} }
public void dispatchPackageBroadcast(int cmd, String[] packages) {
queueOrSendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
}
@Override @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
long nativeMax = Debug.getNativeHeapSize() / 1024; long nativeMax = Debug.getNativeHeapSize() / 1024;
@ -1976,6 +1981,7 @@ public final class ActivityThread {
public static final int SUICIDE = 130; public static final int SUICIDE = 130;
public static final int REMOVE_PROVIDER = 131; public static final int REMOVE_PROVIDER = 131;
public static final int ENABLE_JIT = 132; public static final int ENABLE_JIT = 132;
public static final int DISPATCH_PACKAGE_BROADCAST = 133;
String codeToString(int code) { String codeToString(int code) {
if (localLOGV) { if (localLOGV) {
switch (code) { switch (code) {
@ -2012,6 +2018,7 @@ public final class ActivityThread {
case SUICIDE: return "SUICIDE"; case SUICIDE: return "SUICIDE";
case REMOVE_PROVIDER: return "REMOVE_PROVIDER"; case REMOVE_PROVIDER: return "REMOVE_PROVIDER";
case ENABLE_JIT: return "ENABLE_JIT"; case ENABLE_JIT: return "ENABLE_JIT";
case DISPATCH_PACKAGE_BROADCAST: return "DISPATCH_PACKAGE_BROADCAST";
} }
} }
return "(unknown)"; return "(unknown)";
@ -2132,6 +2139,9 @@ public final class ActivityThread {
case ENABLE_JIT: case ENABLE_JIT:
ensureJitEnabled(); ensureJitEnabled();
break; break;
case DISPATCH_PACKAGE_BROADCAST:
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
break;
} }
} }
@ -2244,7 +2254,7 @@ public final class ActivityThread {
= new HashMap<String, WeakReference<PackageInfo>>(); = new HashMap<String, WeakReference<PackageInfo>>();
Display mDisplay = null; Display mDisplay = null;
DisplayMetrics mDisplayMetrics = null; DisplayMetrics mDisplayMetrics = null;
HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
= new HashMap<ResourcesKey, WeakReference<Resources> >(); = new HashMap<ResourcesKey, WeakReference<Resources> >();
final ArrayList<ActivityRecord> mRelaunchingActivities final ArrayList<ActivityRecord> mRelaunchingActivities
= new ArrayList<ActivityRecord>(); = new ArrayList<ActivityRecord>();
@ -2271,6 +2281,8 @@ public final class ActivityThread {
} }
PackageInfo packageInfo = ref != null ? ref.get() : null; PackageInfo packageInfo = ref != null ? ref.get() : null;
//Slog.i(TAG, "getPackageInfo " + packageName + ": " + packageInfo); //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 if (packageInfo != null && (packageInfo.mResources == null
|| packageInfo.mResources.getAssets().isUpToDate())) { || packageInfo.mResources.getAssets().isUpToDate())) {
if (packageInfo.isSecurityViolation() 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() { 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() { final void handleLowMemory() {
ArrayList<ComponentCallbacks> callbacks ArrayList<ComponentCallbacks> callbacks
= new ArrayList<ComponentCallbacks>(); = new ArrayList<ComponentCallbacks>();

View File

@ -393,6 +393,15 @@ public abstract class ApplicationThreadNative extends Binder
mi.writeToParcel(reply, 0); mi.writeToParcel(reply, 0);
return true; 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); return super.onTransact(code, data, reply, flags);
@ -806,5 +815,16 @@ class ApplicationThreadProxy implements IApplicationThread {
data.recycle(); data.recycle();
reply.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();
}
} }

View File

@ -2277,33 +2277,7 @@ class ContextImpl extends Context {
return null; 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) { private void putCachedIcon(ResourceName name, Drawable dr) {
establishPackageRemovedReceiver();
synchronized (sSync) { synchronized (sSync) {
sIconCache.put(name, new WeakReference<Drawable>(dr)); sIconCache.put(name, new WeakReference<Drawable>(dr));
if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for " if (DEBUG_ICONS) Log.v(TAG, "Added cached drawable for "
@ -2311,29 +2285,17 @@ class ContextImpl extends Context {
} }
} }
private static final class PackageRemovedReceiver extends BroadcastReceiver { static final void handlePackageBroadcast(int cmd, String[] pkgList,
@Override boolean hasPkgInfo) {
public void onReceive(Context context, Intent intent) {
String pkgList[] = null;
String action = intent.getAction();
boolean immediateGc = false; boolean immediateGc = false;
if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) { if (cmd == IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE) {
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
immediateGc = true; 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)) { if (pkgList != null && (pkgList.length > 0)) {
boolean needCleanup = false; boolean needCleanup = false;
boolean hasPkgInfo = false;
for (String ssp : pkgList) { for (String ssp : pkgList) {
synchronized (sSync) { synchronized (sSync) {
if (sIconCache.size() > 0) {
Iterator<ResourceName> it = sIconCache.keySet().iterator(); Iterator<ResourceName> it = sIconCache.keySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
ResourceName nm = it.next(); ResourceName nm = it.next();
@ -2343,7 +2305,9 @@ class ContextImpl extends Context {
needCleanup = true; needCleanup = true;
} }
} }
it = sStringCache.keySet().iterator(); }
if (sStringCache.size() > 0) {
Iterator<ResourceName> it = sStringCache.keySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
ResourceName nm = it.next(); ResourceName nm = it.next();
if (nm.packageName.equals(ssp)) { if (nm.packageName.equals(ssp)) {
@ -2353,8 +2317,6 @@ class ContextImpl extends Context {
} }
} }
} }
if (!hasPkgInfo) {
hasPkgInfo = ActivityThread.currentActivityThread().hasPackageInfo(ssp);
} }
} }
if (needCleanup || hasPkgInfo) { if (needCleanup || hasPkgInfo) {
@ -2367,7 +2329,6 @@ class ContextImpl extends Context {
} }
} }
} }
}
private static final class ResourceName { private static final class ResourceName {
final String packageName; final String packageName;
@ -2433,8 +2394,6 @@ class ContextImpl extends Context {
} }
private void putCachedString(ResourceName name, CharSequence cs) { private void putCachedString(ResourceName name, CharSequence cs) {
establishPackageRemovedReceiver();
synchronized (sSync) { synchronized (sSync) {
sStringCache.put(name, new WeakReference<CharSequence>(cs)); sStringCache.put(name, new WeakReference<CharSequence>(cs));
} }
@ -2698,8 +2657,6 @@ class ContextImpl extends Context {
private final IPackageManager mPM; private final IPackageManager mPM;
private static final Object sSync = new Object(); 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 private static HashMap<ResourceName, WeakReference<Drawable> > sIconCache
= new HashMap<ResourceName, WeakReference<Drawable> >(); = new HashMap<ResourceName, WeakReference<Drawable> >();
private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache private static HashMap<ResourceName, WeakReference<CharSequence> > sStringCache

View File

@ -100,6 +100,9 @@ public interface IApplicationThread extends IInterface {
throws RemoteException; throws RemoteException;
void setSchedulingGroup(int group) throws RemoteException; void setSchedulingGroup(int group) throws RemoteException;
void getMemoryInfo(Debug.MemoryInfo outInfo) 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"; 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 SCHEDULE_DESTROY_BACKUP_AGENT_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+30;
int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31; int GET_MEMORY_INFO_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+31;
int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32; int SCHEDULE_SUICIDE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+32;
int DISPATCH_PACKAGE_BROADCAST_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+33;
} }

View File

@ -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, private final int broadcastIntentLocked(ProcessRecord callerApp,
String callerPackage, Intent intent, String resolvedType, String callerPackage, Intent intent, String resolvedType,
IIntentReceiver resultTo, int resultCode, String resultData, IIntentReceiver resultTo, int resultCode, String resultData,
@ -12315,6 +12327,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
for (String pkg : list) { for (String pkg : list) {
forceStopPackageLocked(pkg, -1, false, true, true); forceStopPackageLocked(pkg, -1, false, true, true);
} }
sendPackageBroadcastLocked(
IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list);
} }
} else { } else {
Uri data = intent.getData(); Uri data = intent.getData();
@ -12324,6 +12338,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
forceStopPackageLocked(ssp, forceStopPackageLocked(ssp,
intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true); intent.getIntExtra(Intent.EXTRA_UID, -1), false, true, true);
} }
if (intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
new String[] {ssp});
}
} }
} }
} }