* Use cached resources for widgets
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index ec8d56b..27e8fb5 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -34,6 +34,7 @@
import android.content.pm.ServiceInfo;
import android.content.pm.PackageParser.Component;
import android.content.res.AssetManager;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
@@ -166,43 +167,52 @@
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) {
- //Log.w(TAG, "getTopLevelResources: " + appDir);
- WeakReference<Resources> wr = mActiveResources.get(appDir);
+ // Resources is app scale dependent.
+ 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;
if (r != null && r.getAssets().isUpToDate()) {
- //Log.w(TAG, "Returning cached resources " + r + " " + appDir);
+ //Log.w(TAG, "Returning cached resources " + r + " " + resDir);
return r;
}
//if (r != null) {
// Log.w(TAG, "Throwing away out-of-date resources!!!! "
- // + r + " " + appDir);
+ // + r + " " + resDir);
//}
AssetManager assets = new AssetManager();
- if (assets.addAssetPath(appDir) == 0) {
+ if (assets.addAssetPath(resDir) == 0) {
return null;
}
- ApplicationInfo appInfo;
- try {
- appInfo = getPackageManager().getApplicationInfo(
- pkgInfo.getPackageName(),
- PackageManager.GET_SUPPORTS_DENSITIES);
- } catch (RemoteException e) {
- throw new AssertionError(e);
- }
- //Log.i(TAG, "Resource:" + appDir + ", display metrics=" + metrics);
+
+ //Log.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
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());
// 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;
}
}
+ /**
+ * Creates the top level resources for the given package.
+ */
+ Resources getTopLevelResources(String resDir, PackageInfo pkgInfo) {
+ return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo);
+ }
+
final Handler getHandler() {
return mH;
}
@@ -223,6 +233,7 @@
private Resources mResources;
private ClassLoader mClassLoader;
private Application mApplication;
+ private CompatibilityInfo mCompatibilityInfo;
private final HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new HashMap<Context, HashMap<BroadcastReceiver, ReceiverDispatcher>>();
@@ -250,6 +261,7 @@
mBaseClassLoader = baseLoader;
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
+ mCompatibilityInfo = new CompatibilityInfo(aInfo);
if (mAppDir == null) {
if (mSystemContext == null) {
@@ -283,6 +295,7 @@
mIncludeCode = true;
mClassLoader = systemContext.getClassLoader();
mResources = systemContext.getResources();
+ mCompatibilityInfo = new CompatibilityInfo(mApplicationInfo);
}
public String getPackageName() {
@@ -1894,6 +1907,32 @@
}
}
+ 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;
final ApplicationThread mAppThread = new ApplicationThread();
@@ -1939,8 +1978,8 @@
= new HashMap<String, WeakReference<PackageInfo>>();
Display mDisplay = null;
DisplayMetrics mDisplayMetrics = null;
- HashMap<String, WeakReference<Resources> > mActiveResources
- = new HashMap<String, WeakReference<Resources> >();
+ HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
+ = new HashMap<ResourcesKey, WeakReference<Resources> >();
// The lock of mProviderMap protects the following variables.
final HashMap<String, ProviderRecord> mProviderMap
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 38ea686..afb2fe9 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -1341,21 +1341,8 @@
if (pi != null) {
ApplicationContext c = new ApplicationContext();
c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
- c.init(pi, null, mMainThread);
+ c.init(pi, null, mMainThread, mResources);
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;
}
}
@@ -1417,8 +1404,24 @@
final void init(ActivityThread.PackageInfo packageInfo,
IBinder activityToken, ActivityThread mainThread) {
+ init(packageInfo, activityToken, mainThread, null);
+ }
+
+ final void init(ActivityThread.PackageInfo packageInfo,
+ IBinder activityToken, ActivityThread mainThread,
+ Resources container) {
mPackageInfo = packageInfo;
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;
mContentResolver = new ApplicationContentResolver(this, mainThread);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index cebb696..903f482 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -979,12 +979,12 @@
/**
* TODO: enable this before code freeze. b/1967935
* *
+ */
if ((densities == null || densities.length == 0)
&& (pkg.applicationInfo.targetSdkVersion
>= android.os.Build.VERSION_CODES.CUR_DEVELOPMENT)) {
pkg.supportsDensities = ApplicationInfo.ANY_DENSITIES_ARRAY;
}
- */
return pkg;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 49ad656..8de938d 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -129,53 +129,30 @@
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
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 metrics Current display metrics to consider when
* selecting/computing resource values.
* @param config Desired device configuration to consider when
* 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
*/
public Resources(AssetManager assets, DisplayMetrics metrics,
- Configuration config, ApplicationInfo appInfo) {
+ Configuration config, CompatibilityInfo compInfo) {
mAssets = assets;
- mConfiguration.setToDefaults();
mMetrics.setToDefaults();
- if (appInfo != null) {
- mCompatibilityInfo = new CompatibilityInfo(appInfo);
- if (DEBUG_CONFIG) {
- Log.d(TAG, "compatibility for " + appInfo.packageName + " : " + mCompatibilityInfo);
- }
- } else {
+ if (compInfo == null) {
mCompatibilityInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
- }
- updateConfiguration(config, metrics);
- assets.ensureStringBlocks();
- if (mCompatibilityInfo.isScalingRequired()) {
- mPreloadedDrawables = emptySparseArray();
} 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);
assets.ensureStringBlocks();
if (mCompatibilityInfo.isScalingRequired()) {