* Use cached resources for widgets

This commit is contained in:
Mitsuru Oshima
2009-07-08 18:49:26 -07:00
parent cf29e11612
commit ba3ba57921
4 changed files with 83 additions and 64 deletions

View File

@@ -34,6 +34,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ServiceInfo; import android.content.pm.ServiceInfo;
import android.content.pm.PackageParser.Component; import android.content.pm.PackageParser.Component;
import android.content.res.AssetManager; import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
@@ -166,43 +167,52 @@ public final class ActivityThread {
return metrics; return metrics;
} }
Resources getTopLevelResources(String appDir, PackageInfo pkgInfo) { /**
* Creates the top level Resources for applications with the given compatibility info.
*
* @param resDir the resource directory.
* @param compInfo the compability info. It will use the default compatibility info when it's
* null.
*/
Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
synchronized (mPackages) { synchronized (mPackages) {
//Log.w(TAG, "getTopLevelResources: " + appDir); // Resources is app scale dependent.
WeakReference<Resources> wr = mActiveResources.get(appDir); ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
//Log.w(TAG, "getTopLevelResources: " + resDir);
WeakReference<Resources> wr = mActiveResources.get(key);
Resources r = wr != null ? wr.get() : null; Resources r = wr != null ? wr.get() : null;
if (r != null && r.getAssets().isUpToDate()) { if (r != null && r.getAssets().isUpToDate()) {
//Log.w(TAG, "Returning cached resources " + r + " " + appDir); //Log.w(TAG, "Returning cached resources " + r + " " + resDir);
return r; return r;
} }
//if (r != null) { //if (r != null) {
// Log.w(TAG, "Throwing away out-of-date resources!!!! " // Log.w(TAG, "Throwing away out-of-date resources!!!! "
// + r + " " + appDir); // + r + " " + resDir);
//} //}
AssetManager assets = new AssetManager(); AssetManager assets = new AssetManager();
if (assets.addAssetPath(appDir) == 0) { if (assets.addAssetPath(resDir) == 0) {
return null; return null;
} }
ApplicationInfo appInfo;
try { //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
appInfo = getPackageManager().getApplicationInfo(
pkgInfo.getPackageName(),
PackageManager.GET_SUPPORTS_DENSITIES);
} catch (RemoteException e) {
throw new AssertionError(e);
}
//Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics);
DisplayMetrics metrics = getDisplayMetricsLocked(false); DisplayMetrics metrics = getDisplayMetricsLocked(false);
r = new Resources(assets, metrics, getConfiguration(), appInfo); r = new Resources(assets, metrics, getConfiguration(), compInfo);
//Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration()); //Log.i(TAG, "Created app resources " + r + ": " + r.getConfiguration());
// XXX need to remove entries when weak references go away // XXX need to remove entries when weak references go away
mActiveResources.put(appDir, new WeakReference<Resources>(r)); mActiveResources.put(key, new WeakReference<Resources>(r));
return r; return r;
} }
} }
/**
* Creates the top level resources for the given package.
*/
Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
}
final Handler getHandler() { final Handler getHandler() {
return mH; return mH;
} }
@@ -223,6 +233,7 @@ public final class ActivityThread {
private Resources mResources; private Resources mResources;
private ClassLoader mClassLoader; private ClassLoader mClassLoader;
private Application mApplication; private Application mApplication;
private CompatibilityInfo mCompatibilityInfo;
private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>(); = new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
@@ -250,6 +261,7 @@ public final class ActivityThread {
mBaseClassLoader = baseLoader; mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation; mSecurityViolation = securityViolation;
mIncludeCode = includeCode; mIncludeCode = includeCode;
mCompatibilityInfo = new CompatibilityInfo(aInfo);
if (mAppDir == null) { if (mAppDir == null) {
if (mSystemContext == null) { if (mSystemContext == null) {
@@ -283,6 +295,7 @@ public final class ActivityThread {
mIncludeCode = true; mIncludeCode = true;
mClassLoader = systemContext.getClassLoader(); mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources(); mResources = systemContext.getResources();
mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
} }
public String getPackageName() { public String getPackageName() {
@@ -1894,6 +1907,32 @@ public final class ActivityThread {
} }
} }
private final static class ResourcesKey {
final private String mResDir;
final private float mScale;
final private int mHash;
ResourcesKey(String resDir, float scale) {
mResDir = resDir;
mScale = scale;
mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
}
@Override
public int hashCode() {
return mHash;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ResourcesKey)) {
return false;
}
ResourcesKey peer = (ResourcesKey) obj;
return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
}
}
static IPackageManager sPackageManager; static IPackageManager sPackageManager;
final ApplicationThread mAppThread = new ApplicationThread(); final ApplicationThread mAppThread = new ApplicationThread();
@@ -1939,8 +1978,8 @@ 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<String, WeakReference<Resources> > mActiveResources HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
= new HashMap<String, WeakReference<Resources> >(); = new HashMap<ResourcesKey, WeakReference<Resources> >();
// The lock of mProviderMap protects the following variables. // The lock of mProviderMap protects the following variables.
final HashMap<String, ProviderRecord> mProviderMap final HashMap<String, ProviderRecord> mProviderMap

View File

@@ -1341,21 +1341,8 @@ class ApplicationContext extends Context {
if (pi != null) { if (pi != null) {
ApplicationContext c = new ApplicationContext(); ApplicationContext c = new ApplicationContext();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED; c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
c.init(pi, null, mMainThread); c.init(pi, null, mMainThread, mResources);
if (c.mResources != null) { if (c.mResources != null) {
Resources newRes = c.mResources;
if (mResources.getCompatibilityInfo().applicationScale !=
newRes.getCompatibilityInfo().applicationScale) {
DisplayMetrics dm = mMainThread.getDisplayMetricsLocked(false);
c.mResources = new Resources(newRes.getAssets(), dm,
newRes.getConfiguration(),
mResources.getCompatibilityInfo().copy());
if (DEBUG) {
Log.d(TAG, "loaded context has different scaling. Using container's" +
" compatiblity info:" + mResources.getDisplayMetrics());
}
}
return c; return c;
} }
} }
@@ -1417,8 +1404,24 @@ class ApplicationContext extends Context {
final void init(ActivityThread.PackageInfo packageInfo, final void init(ActivityThread.PackageInfo packageInfo,
IBinder activityToken, ActivityThread mainThread) { IBinder activityToken, ActivityThread mainThread) {
init(packageInfo, activityToken, mainThread, null);
}
final void init(ActivityThread.PackageInfo packageInfo,
IBinder activityToken, ActivityThread mainThread,
Resources container) {
mPackageInfo = packageInfo; mPackageInfo = packageInfo;
mResources = mPackageInfo.getResources(mainThread); mResources = mPackageInfo.getResources(mainThread);
if (container != null && container.getCompatibilityInfo().applicationScale !=
mResources.getCompatibilityInfo().applicationScale) {
if (DEBUG) {
Log.d(TAG, "loaded context has different scaling. Using container's" +
" compatiblity info:" + container.getDisplayMetrics());
}
mResources = mainThread.getTopLevelResources(
mPackageInfo.getResDir(), container.getCompatibilityInfo().copy());
}
mMainThread = mainThread; mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread); mContentResolver = new ApplicationContentResolver(this, mainThread);

View File

@@ -979,12 +979,12 @@ public class PackageParser {
/** /**
* TODO: enable this before code freeze. b/1967935 * TODO: enable this before code freeze. b/1967935
* * * *
*/
if ((densities == null || densities.length == 0) if ((densities == null || densities.length == 0)
&& (pkg.applicationInfo.targetSdkVersion && (pkg.applicationInfo.targetSdkVersion
>= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) { >= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY; pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
} }
*/
return pkg; return pkg;
} }

View File

@@ -129,53 +129,30 @@ public class Resources {
*/ */
public Resources(AssetManager assets, DisplayMetrics metrics, public Resources(AssetManager assets, DisplayMetrics metrics,
Configuration config) { Configuration config) {
this(assets, metrics, config, (ApplicationInfo) null); this(assets, metrics, config, (CompatibilityInfo) null);
} }
/** /**
* Creates a new Resources object with ApplicationInfo. * Creates a new Resources object with CompatibilityInfo.
* *
* @param assets Previously created AssetManager. * @param assets Previously created AssetManager.
* @param metrics Current display metrics to consider when * @param metrics Current display metrics to consider when
* selecting/computing resource values. * selecting/computing resource values.
* @param config Desired device configuration to consider when * @param config Desired device configuration to consider when
* selecting/computing resource values (optional). * selecting/computing resource values (optional).
* @param appInfo this resource's application info. * @param compInfo this resource's compatibility info. It will use the default compatibility
* info when it's null.
* @hide * @hide
*/ */
public Resources(AssetManager assets, DisplayMetrics metrics, public Resources(AssetManager assets, DisplayMetrics metrics,
Configuration config, ApplicationInfo appInfo) { Configuration config, CompatibilityInfo compInfo) {
mAssets = assets; mAssets = assets;
mConfiguration.setToDefaults();
mMetrics.setToDefaults(); mMetrics.setToDefaults();
if (appInfo != null) { if (compInfo == null) {
mCompatibilityInfo = new CompatibilityInfo(appInfo);
if (DEBUG_CONFIG) {
Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo);
}
} else {
mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO; mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
}
updateConfiguration(config, metrics);
assets.ensureStringBlocks();
if (mCompatibilityInfo.isScalingRequired()) {
mPreloadedDrawables = emptySparseArray();
} else { } else {
mPreloadedDrawables = sPreloadedDrawables; mCompatibilityInfo = compInfo;
} }
}
/**
* Creates a new resources that uses the given compatibility info. Used to create
* a context for widgets using the container's compatibility info.
* {@see ApplicationContext#createPackageCotnext}.
* @hide
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
Configuration config, CompatibilityInfo info) {
mAssets = assets;
mMetrics.setToDefaults();
mCompatibilityInfo = info;
updateConfiguration(config, metrics); updateConfiguration(config, metrics);
assets.ensureStringBlocks(); assets.ensureStringBlocks();
if (mCompatibilityInfo.isScalingRequired()) { if (mCompatibilityInfo.isScalingRequired()) {