summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ActivityThread.java81
-rw-r--r--core/java/android/app/ApplicationPackageManager.java2
-rw-r--r--core/java/android/app/ContextImpl.java22
-rw-r--r--core/java/android/app/LoadedApk.java2
-rw-r--r--core/java/android/content/Context.java18
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/res/Configuration.java3
-rwxr-xr-xcore/java/android/content/res/Resources.java11
-rw-r--r--core/java/android/view/ContextThemeWrapper.java38
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;