* 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()) {