diff options
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/app/ActivityThread.java | 81 | ||||
-rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 2 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 22 | ||||
-rw-r--r-- | core/java/android/app/LoadedApk.java | 2 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 18 | ||||
-rw-r--r-- | core/java/android/content/ContextWrapper.java | 6 | ||||
-rw-r--r-- | core/java/android/content/res/Configuration.java | 3 | ||||
-rwxr-xr-x | core/java/android/content/res/Resources.java | 11 | ||||
-rw-r--r-- | core/java/android/view/ContextThemeWrapper.java | 38 |
9 files changed, 154 insertions, 29 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index bb35ddd..0789c60 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -1471,13 +1471,25 @@ public final class ActivityThread { private static class ResourcesKey { final private String mResDir; + final private Configuration mOverrideConfiguration; final private float mScale; final private int mHash; - ResourcesKey(String resDir, float scale) { + ResourcesKey(String resDir, Configuration overrideConfiguration, float scale) { mResDir = resDir; + if (overrideConfiguration != null) { + if (Configuration.EMPTY.equals(overrideConfiguration)) { + overrideConfiguration = null; + } + } + mOverrideConfiguration = overrideConfiguration; mScale = scale; - mHash = mResDir.hashCode() << 2 + (int) (mScale * 2); + int hash = 17; + hash = 31 * hash + mResDir.hashCode(); + hash = 31 * hash + (mOverrideConfiguration != null + ? mOverrideConfiguration.hashCode() : 0); + hash = 31 * hash + Float.floatToIntBits(mScale); + mHash = hash; } @Override @@ -1491,7 +1503,21 @@ public final class ActivityThread { return false; } ResourcesKey peer = (ResourcesKey) obj; - return mResDir.equals(peer.mResDir) && mScale == peer.mScale; + if (!mResDir.equals(peer.mResDir)) { + return false; + } + if (mOverrideConfiguration != peer.mOverrideConfiguration) { + if (mOverrideConfiguration == null || peer.mOverrideConfiguration == null) { + return false; + } + if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) { + return false; + } + } + if (mScale != peer.mScale) { + return false; + } + return true; } } @@ -1562,8 +1588,10 @@ public final class ActivityThread { * @param compInfo the compability info. It will use the default compatibility info when it's * null. */ - Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) { - ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale); + Resources getTopLevelResources(String resDir, Configuration overrideConfiguration, + CompatibilityInfo compInfo) { + ResourcesKey key = new ResourcesKey(resDir, overrideConfiguration, + compInfo.applicationScale); Resources r; synchronized (mPackages) { // Resources is app scale dependent. @@ -1595,13 +1623,20 @@ public final class ActivityThread { //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); DisplayMetrics metrics = getDisplayMetricsLocked(null, false); - r = new Resources(assets, metrics, getConfiguration(), compInfo); + Configuration config; + if (key.mOverrideConfiguration != null) { + config = new Configuration(getConfiguration()); + config.updateFrom(key.mOverrideConfiguration); + } else { + config = getConfiguration(); + } + r = new Resources(assets, metrics, config, compInfo); if (false) { Slog.i(TAG, "Created app resources " + resDir + " " + r + ": " + r.getConfiguration() + " appScale=" + r.getCompatibilityInfo().applicationScale); } - + synchronized (mPackages) { WeakReference<Resources> wr = mActiveResources.get(key); Resources existing = wr != null ? wr.get() : null; @@ -1621,8 +1656,10 @@ public final class ActivityThread { /** * Creates the top level resources for the given package. */ - Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) { - return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get()); + Resources getTopLevelResources(String resDir, Configuration overrideConfiguration, + LoadedApk pkgInfo) { + return getTopLevelResources(resDir, overrideConfiguration, + pkgInfo.mCompatibilityInfo.get()); } final Handler getHandler() { @@ -3675,18 +3712,28 @@ public final class ActivityThread { ApplicationPackageManager.configurationChanged(); //Slog.i(TAG, "Configuration changed in " + currentPackageName()); - - Iterator<WeakReference<Resources>> it = - mActiveResources.values().iterator(); - //Iterator<Map.Entry<String, WeakReference<Resources>>> it = - // mActiveResources.entrySet().iterator(); + + Configuration tmpConfig = null; + + Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it = + mActiveResources.entrySet().iterator(); while (it.hasNext()) { - WeakReference<Resources> v = it.next(); - Resources r = v.get(); + Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next(); + Resources r = entry.getValue().get(); if (r != null) { if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources " + r + " config to: " + config); - r.updateConfiguration(config, dm, compat); + Configuration override = entry.getKey().mOverrideConfiguration; + if (override != null) { + if (tmpConfig == null) { + tmpConfig = new Configuration(); + } + tmpConfig.setTo(config); + tmpConfig.updateFrom(override); + r.updateConfiguration(tmpConfig, dm, compat); + } else { + r.updateConfiguration(config, dm, compat); + } //Slog.i(TAG, "Updated app resources " + v.getKey() // + " " + r + ": " + r.getConfiguration()); } else { diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 2face4c..9b59e2c 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -713,7 +713,7 @@ final class ApplicationPackageManager extends PackageManager { } Resources r = mContext.mMainThread.getTopLevelResources( app.uid == Process.myUid() ? app.sourceDir - : app.publicSourceDir, mContext.mPackageInfo); + : app.publicSourceDir, null, mContext.mPackageInfo); if (r != null) { return r; } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 4496ce8..1ef14eb 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -37,6 +37,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.CompatibilityInfo; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; @@ -525,7 +526,7 @@ class ContextImpl extends Context { @Override public AssetManager getAssets() { - return mResources.getAssets(); + return getResources().getAssets(); } @Override @@ -1591,6 +1592,16 @@ class ContextImpl extends Context { } @Override + public Context createConfigurationContext(Configuration overrideConfiguration) { + ContextImpl c = new ContextImpl(); + c.init(mPackageInfo, null, mMainThread); + c.mResources = mMainThread.getTopLevelResources( + mPackageInfo.getResDir(), overrideConfiguration, + mResources.getCompatibilityInfo()); + return c; + } + + @Override public boolean isRestricted() { return mRestricted; } @@ -1659,12 +1670,11 @@ class ContextImpl extends Context { " compatiblity info:" + container.getDisplayMetrics()); } mResources = mainThread.getTopLevelResources( - mPackageInfo.getResDir(), container.getCompatibilityInfo()); + mPackageInfo.getResDir(), null, container.getCompatibilityInfo()); } mMainThread = mainThread; mContentResolver = new ApplicationContentResolver(this, mainThread); - - setActivityToken(activityToken); + mActivityToken = activityToken; } final void init(Resources resources, ActivityThread mainThread) { @@ -1691,10 +1701,6 @@ class ContextImpl extends Context { return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext()); } - final void setActivityToken(IBinder token) { - mActivityToken = token; - } - final void setOuterContext(Context context) { mOuterContext = context; } diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index be4b284..f4195d6 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -471,7 +471,7 @@ public final class LoadedApk { public Resources getResources(ActivityThread mainThread) { if (mResources == null) { - mResources = mainThread.getTopLevelResources(mResDir, this); + mResources = mainThread.getTopLevelResources(mResDir, null, this); } return mResources; } diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index bf60a96..a90142a 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -19,6 +19,7 @@ package android.content; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; +import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.DatabaseErrorHandler; @@ -2445,6 +2446,23 @@ public abstract class Context { int flags) throws PackageManager.NameNotFoundException; /** + * Return a new Context object for the current Context but whose resources + * are adjusted to match the given Configuration. Each call to this method + * returns a new instance of a Contex object; Context objects are not + * shared, however common state (ClassLoader, other Resources for the + * same configuration) may be so the Context itself can be fairly lightweight. + * + * @param overrideConfiguration A {@link Configuration} specifying what + * values to modify in the base Configuration of the original Context's + * resources. If the base configuration changes (such as due to an + * orientation change), the resources of this context will also change except + * for those that have been explicitly overridden with a value here. + * + * @return A Context for the application. + */ + public abstract Context createConfigurationContext(Configuration overrideConfiguration); + + /** * Indicates whether this Context is restricted. * * @return True if this Context is restricted, false otherwise. diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java index ff4c9a1..fdf60ab 100644 --- a/core/java/android/content/ContextWrapper.java +++ b/core/java/android/content/ContextWrapper.java @@ -19,6 +19,7 @@ package android.content; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; +import android.content.res.Configuration; import android.content.res.Resources; import android.database.DatabaseErrorHandler; import android.database.sqlite.SQLiteDatabase; @@ -533,6 +534,11 @@ public class ContextWrapper extends Context { } @Override + public Context createConfigurationContext(Configuration overrideConfiguration) { + return mBase.createConfigurationContext(overrideConfiguration); + } + + @Override public boolean isRestricted() { return mBase.isRestricted(); } diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index ea13a2a..52b6498 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -35,6 +35,9 @@ import java.util.Locale; * <pre>Configuration config = getResources().getConfiguration();</pre> */ public final class Configuration implements Parcelable, Comparable<Configuration> { + /** @hide */ + public static final Configuration EMPTY = new Configuration(); + /** * Current user preference for the scaling factor for fonts, relative * to the base density scaling. diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index d2af3e9..26512e2 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1435,9 +1435,12 @@ public class Resources { int configChanges = 0xfffffff; if (config != null) { mTmpConfig.setTo(config); + int density = config.densityDpi; + if (density == Configuration.DENSITY_DPI_UNDEFINED) { + density = mMetrics.noncompatDensityDpi; + } if (mCompatibilityInfo != null) { - mCompatibilityInfo.applyToConfiguration(mMetrics.noncompatDensityDpi, - mTmpConfig); + mCompatibilityInfo.applyToConfiguration(density, mTmpConfig); } if (mTmpConfig.locale == null) { mTmpConfig.locale = Locale.getDefault(); @@ -1448,6 +1451,10 @@ public class Resources { if (mConfiguration.locale == null) { mConfiguration.locale = Locale.getDefault(); } + if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) { + mMetrics.densityDpi = mConfiguration.densityDpi; + mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; + } mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale; String locale = null; diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java index 626f385..6c733f9 100644 --- a/core/java/android/view/ContextThemeWrapper.java +++ b/core/java/android/view/ContextThemeWrapper.java @@ -18,6 +18,7 @@ package android.view; import android.content.Context; import android.content.ContextWrapper; +import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; @@ -30,6 +31,8 @@ public class ContextThemeWrapper extends ContextWrapper { private int mThemeResource; private Resources.Theme mTheme; private LayoutInflater mInflater; + private Configuration mOverrideConfiguration; + private Resources mResources; public ContextThemeWrapper() { super(null); @@ -45,6 +48,41 @@ public class ContextThemeWrapper extends ContextWrapper { super.attachBaseContext(newBase); mBase = newBase; } + + /** + * Call to set an "override configuration" on this context -- this is + * a configuration that replies one or more values of the standard + * configuration that is applied to the context. See + * {@link Context#createConfigurationContext(Configuration)} for more + * information. + * + * <p>This method can only be called once, and must be called before any + * calls to {@link #getResources()} are made. + */ + public void applyOverrideConfiguration(Configuration overrideConfiguration) { + if (mResources != null) { + throw new IllegalStateException("getResources() has already been called"); + } + if (mOverrideConfiguration != null) { + throw new IllegalStateException("Override configuration has already been set"); + } + mOverrideConfiguration = new Configuration(overrideConfiguration); + } + + @Override + public Resources getResources() { + if (mResources != null) { + return mResources; + } + if (mOverrideConfiguration == null) { + mResources = super.getResources(); + return mResources; + } else { + Context resc = createConfigurationContext(mOverrideConfiguration); + mResources = resc.getResources(); + return mResources; + } + } @Override public void setTheme(int resid) { mThemeResource = resid; |