Merge "Unregister gralloc buffer immediately Bug #9406765"
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 4568525..f1b5d46 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,8 +16,6 @@
package android.app;
-import static android.view.DisplayAdjustments.DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN;
-
import android.app.backup.BackupAgent;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
@@ -77,7 +75,6 @@
import android.util.LogPrinter;
import android.util.PrintWriterPrinter;
import android.util.Slog;
-import android.view.DisplayAdjustments;
import android.view.Display;
import android.view.HardwareRenderer;
import android.view.View;
@@ -150,7 +147,7 @@
public static final boolean DEBUG_BROADCAST = false;
private static final boolean DEBUG_RESULTS = false;
private static final boolean DEBUG_BACKUP = false;
- private static final boolean DEBUG_CONFIGURATION = false;
+ public static final boolean DEBUG_CONFIGURATION = false;
private static final boolean DEBUG_SERVICE = false;
private static final boolean DEBUG_MEMORY_TRIM = false;
private static final boolean DEBUG_PROVIDER = false;
@@ -182,8 +179,6 @@
boolean mDensityCompatMode;
Configuration mConfiguration;
Configuration mCompatConfiguration;
- Configuration mResConfiguration;
- CompatibilityInfo mResCompatibilityInfo;
Application mInitialApplication;
final ArrayList<Application> mAllApplications
= new ArrayList<Application>();
@@ -212,14 +207,12 @@
= new HashMap<String, WeakReference<LoadedApk>>();
final HashMap<String, WeakReference<LoadedApk>> mResourcePackages
= new HashMap<String, WeakReference<LoadedApk>>();
- final HashMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
- = new HashMap<DisplayAdjustments, DisplayMetrics>();
- final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
- = new HashMap<ResourcesKey, WeakReference<Resources> >();
final ArrayList<ActivityClientRecord> mRelaunchingActivities
= new ArrayList<ActivityClientRecord>();
Configuration mPendingConfiguration = null;
+ private final ResourcesManager mResourcesManager;
+
private static final class ProviderKey {
final String authority;
final int userId;
@@ -555,7 +548,7 @@
private static final int ACTIVITY_THREAD_CHECKIN_VERSION = 3;
private void updatePendingConfiguration(Configuration config) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(config)) {
mPendingConfiguration = config;
@@ -1608,72 +1601,6 @@
}
}
- private static class ResourcesKey {
- final private String mResDir;
- final private int mDisplayId;
- final private Configuration mOverrideConfiguration;
- final private float mScale;
- final private int mHash;
- final private IBinder mToken;
-
- ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
- float scale, IBinder token) {
- mResDir = resDir;
- mDisplayId = displayId;
- if (overrideConfiguration != null) {
- if (Configuration.EMPTY.equals(overrideConfiguration)) {
- overrideConfiguration = null;
- }
- }
- mOverrideConfiguration = overrideConfiguration;
- mScale = scale;
- int hash = 17;
- hash = 31 * hash + mResDir.hashCode();
- hash = 31 * hash + mDisplayId;
- hash = 31 * hash + (mOverrideConfiguration != null
- ? mOverrideConfiguration.hashCode() : 0);
- hash = 31 * hash + Float.floatToIntBits(mScale);
- if (DEVELOPMENT_RESOURCES_DEPEND_ON_ACTIVITY_TOKEN) {
- mToken = token;
- hash = 31 * hash + (mToken == null ? 0 : mToken.hashCode());
- } else {
- mToken = null;
- }
- mHash = hash;
- }
-
- @Override
- public int hashCode() {
- return mHash;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof ResourcesKey)) {
- return false;
- }
- ResourcesKey peer = (ResourcesKey) obj;
- if (!mResDir.equals(peer.mResDir)) {
- return false;
- }
- if (mDisplayId != peer.mDisplayId) {
- 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;
- }
- }
-
public static ActivityThread currentActivityThread() {
return sCurrentActivityThread;
}
@@ -1707,49 +1634,6 @@
return sPackageManager;
}
- private void flushDisplayMetricsLocked() {
- mDefaultDisplayMetrics.clear();
- }
-
- DisplayMetrics getDisplayMetricsLocked(int displayId) {
- return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
- }
-
- DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
- if (dm != null) {
- return dm;
- }
- dm = new DisplayMetrics();
-
- DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
- if (displayManager == null) {
- // may be null early in system startup
- dm.setToDefaults();
- return dm;
- }
-
- if (isDefaultDisplay) {
- mDefaultDisplayMetrics.put(daj, dm);
- }
-
- Display d = displayManager.getCompatibleDisplay(displayId, daj);
- if (d != null) {
- d.getMetrics(dm);
- } else {
- // Display no longer exists
- // FIXME: This would not be a problem if we kept the Display object around
- // instead of using the raw display id everywhere. The Display object caches
- // its information even after the display has been removed.
- dm.setToDefaults();
- }
- //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
- // + metrics.heightPixels + " den=" + metrics.density
- // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
- return dm;
- }
-
private Configuration mMainThreadConfig = new Configuration();
Configuration applyConfigCompatMainThread(int displayDensity, Configuration config,
CompatibilityInfo compat) {
@@ -1765,90 +1649,12 @@
}
/**
- * Creates the top level Resources for applications with the given compatibility info.
- *
- * @param resDir the resource directory.
- * @param compatInfo the compability info. Must not be null.
- * @param token the application token for determining stack bounds.
- */
- Resources getTopLevelResources(String resDir, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
- final float scale = compatInfo.applicationScale;
- ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
- token);
- Resources r;
- synchronized (mPackages) {
- // Resources is app scale dependent.
- if (false) {
- Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
- }
- WeakReference<Resources> wr = mActiveResources.get(key);
- r = wr != null ? wr.get() : null;
- //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
- if (r != null && r.getAssets().isUpToDate()) {
- if (false) {
- Slog.w(TAG, "Returning cached resources " + r + " " + resDir
- + ": appScale=" + r.getCompatibilityInfo().applicationScale);
- }
- return r;
- }
- }
-
- //if (r != null) {
- // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
- // + r + " " + resDir);
- //}
-
- AssetManager assets = new AssetManager();
- if (assets.addAssetPath(resDir) == 0) {
- return null;
- }
-
- //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
- DisplayMetrics dm = getDisplayMetricsLocked(displayId);
- Configuration config;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- if (!isDefaultDisplay || key.mOverrideConfiguration != null) {
- config = new Configuration(getConfiguration());
- if (!isDefaultDisplay) {
- applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
- }
- if (key.mOverrideConfiguration != null) {
- config.updateFrom(key.mOverrideConfiguration);
- }
- } else {
- config = getConfiguration();
- }
- r = new Resources(assets, dm, config, compatInfo, token);
- 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;
- if (existing != null && existing.getAssets().isUpToDate()) {
- // Someone else already created the resources while we were
- // unlocked; go ahead and use theirs.
- r.getAssets().close();
- return existing;
- }
-
- // XXX need to remove entries when weak references go away
- mActiveResources.put(key, new WeakReference<Resources>(r));
- return r;
- }
- }
-
- /**
* Creates the top level resources for the given package.
*/
Resources getTopLevelResources(String resDir,
int displayId, Configuration overrideConfiguration,
LoadedApk pkgInfo) {
- return getTopLevelResources(resDir, displayId, overrideConfiguration,
+ return mResourcesManager.getTopLevelResources(resDir, displayId, overrideConfiguration,
pkgInfo.getCompatibilityInfo(), null);
}
@@ -1863,7 +1669,7 @@
public final LoadedApk getPackageInfo(String packageName, CompatibilityInfo compatInfo,
int flags, int userId) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if ((flags&Context.CONTEXT_INCLUDE_CODE) != 0) {
ref = mPackages.get(packageName);
@@ -1933,7 +1739,7 @@
}
public final LoadedApk peekPackageInfo(String packageName, boolean includeCode) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(packageName);
@@ -1946,7 +1752,7 @@
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(aInfo.packageName);
@@ -1978,6 +1784,7 @@
}
ActivityThread() {
+ mResourcesManager = ResourcesManager.getInstance();
}
public ApplicationThread getApplicationThread()
@@ -1990,10 +1797,6 @@
return mInstrumentation;
}
- public Configuration getConfiguration() {
- return mResConfiguration;
- }
-
public boolean isProfiling() {
return mProfiler != null && mProfiler.profileFile != null
&& mProfiler.profileFd == null;
@@ -2023,8 +1826,8 @@
LoadedApk info = new LoadedApk(this, "android", context, null,
CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
context.init(info, null, this);
- context.getResources().updateConfiguration(getConfiguration(),
- getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
+ context.getResources().updateConfiguration(mResourcesManager.getConfiguration(),
+ mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
mSystemContext = context;
//Slog.i(TAG, "Created system resources " + context.getResources()
// + ": " + context.getResources().getConfiguration());
@@ -3419,7 +3222,7 @@
}
private void handleSetCoreSettings(Bundle coreSettings) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
mCoreSettings = coreSettings;
}
}
@@ -3509,7 +3312,7 @@
private ActivityClientRecord performDestroyActivity(IBinder token, boolean finishing,
int configChanges, boolean getNonConfigInstance) {
ActivityClientRecord r = mActivities.get(token);
- Class activityClass = null;
+ Class<? extends Activity> activityClass = null;
if (localLOGV) Slog.v(TAG, "Performing finish of " + r);
if (r != null) {
activityClass = r.activity.getClass();
@@ -3664,7 +3467,7 @@
boolean fromServer) {
ActivityClientRecord target = null;
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
for (int i=0; i<mRelaunchingActivities.size(); i++) {
ActivityClientRecord r = mRelaunchingActivities.get(i);
if (r.token == token) {
@@ -3725,7 +3528,7 @@
// First: make sure we have the most recent configuration and most
// recent version of the activity, or skip it if some previous call
// had taken a more recent version.
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
int N = mRelaunchingActivities.size();
IBinder token = tmp.token;
tmp = null;
@@ -3854,7 +3657,7 @@
ArrayList<ComponentCallbacks2> callbacks
= new ArrayList<ComponentCallbacks2>();
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
final int N = mAllApplications.size();
for (int i=0; i<N; i++) {
callbacks.add(mAllApplications.get(i));
@@ -3948,114 +3751,18 @@
}
public final void applyConfigurationToResources(Configuration config) {
- synchronized (mPackages) {
- applyConfigurationToResourcesLocked(config, null);
+ synchronized (mResourcesManager) {
+ mResourcesManager.applyConfigurationToResourcesLocked(config, null);
}
}
- final boolean applyConfigurationToResourcesLocked(Configuration config,
- CompatibilityInfo compat) {
- if (mResConfiguration == null) {
- mResConfiguration = new Configuration();
- }
- if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
- if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
- + mResConfiguration.seq + ", newSeq=" + config.seq);
- return false;
- }
- int changes = mResConfiguration.updateFrom(config);
- flushDisplayMetricsLocked();
- DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
-
- if (compat != null && (mResCompatibilityInfo == null ||
- !mResCompatibilityInfo.equals(compat))) {
- mResCompatibilityInfo = compat;
- changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
- | ActivityInfo.CONFIG_SCREEN_SIZE
- | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
- }
-
- // set it for java, this also affects newly created Resources
- if (config.locale != null) {
- Locale.setDefault(config.locale);
- }
-
- Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
-
- ApplicationPackageManager.configurationChanged();
- //Slog.i(TAG, "Configuration changed in " + currentPackageName());
-
- Configuration tmpConfig = null;
-
- Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
- mActiveResources.entrySet().iterator();
- while (it.hasNext()) {
- 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);
- int displayId = entry.getKey().mDisplayId;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- DisplayMetrics dm = defaultDisplayMetrics;
- Configuration overrideConfig = entry.getKey().mOverrideConfiguration;
- if (!isDefaultDisplay || overrideConfig != null) {
- if (tmpConfig == null) {
- tmpConfig = new Configuration();
- }
- tmpConfig.setTo(config);
- if (!isDefaultDisplay) {
- dm = getDisplayMetricsLocked(displayId);
- applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
- }
- if (overrideConfig != null) {
- tmpConfig.updateFrom(overrideConfig);
- }
- r.updateConfiguration(tmpConfig, dm, compat);
- } else {
- r.updateConfiguration(config, dm, compat);
- }
- //Slog.i(TAG, "Updated app resources " + v.getKey()
- // + " " + r + ": " + r.getConfiguration());
- } else {
- //Slog.i(TAG, "Removing old resources " + v.getKey());
- it.remove();
- }
- }
-
- return changes != 0;
- }
-
- final void applyNonDefaultDisplayMetricsToConfigurationLocked(
- DisplayMetrics dm, Configuration config) {
- config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
- config.densityDpi = dm.densityDpi;
- config.screenWidthDp = (int)(dm.widthPixels / dm.density);
- config.screenHeightDp = (int)(dm.heightPixels / dm.density);
- int sl = Configuration.resetScreenLayout(config.screenLayout);
- if (dm.widthPixels > dm.heightPixels) {
- config.orientation = Configuration.ORIENTATION_LANDSCAPE;
- config.screenLayout = Configuration.reduceScreenLayout(sl,
- config.screenWidthDp, config.screenHeightDp);
- } else {
- config.orientation = Configuration.ORIENTATION_PORTRAIT;
- config.screenLayout = Configuration.reduceScreenLayout(sl,
- config.screenHeightDp, config.screenWidthDp);
- }
- config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
- config.compatScreenWidthDp = config.screenWidthDp;
- config.compatScreenHeightDp = config.screenHeightDp;
- config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
- }
-
final Configuration applyCompatConfiguration(int displayDensity) {
Configuration config = mConfiguration;
if (mCompatConfiguration == null) {
mCompatConfiguration = new Configuration();
}
mCompatConfiguration.setTo(mConfiguration);
- if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
- mResCompatibilityInfo.applyToConfiguration(displayDensity, mCompatConfiguration);
+ if (mResourcesManager.applyCompatConfiguration(displayDensity, mCompatConfiguration)) {
config = mCompatConfiguration;
}
return config;
@@ -4065,7 +3772,7 @@
int configDiff = 0;
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
if (mPendingConfiguration != null) {
if (!mPendingConfiguration.isOtherSeqNewer(config)) {
config = mPendingConfiguration;
@@ -4081,9 +3788,9 @@
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Handle configuration changed: "
+ config);
-
- applyConfigurationToResourcesLocked(config, compat);
-
+
+ mResourcesManager.applyConfigurationToResourcesLocked(config, compat);
+
if (mConfiguration == null) {
mConfiguration = new Configuration();
}
@@ -4333,7 +4040,7 @@
* reflect configuration changes. The configuration object passed
* in AppBindData can be safely assumed to be up to date
*/
- applyConfigurationToResourcesLocked(data.config, data.compatInfo);
+ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
@@ -5045,6 +4752,7 @@
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
+ @Override
public void run() {
ensureJitEnabled();
}
@@ -5081,12 +4789,13 @@
DropBox.setReporter(new DropBoxReporter());
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
+ @Override
public void onConfigurationChanged(Configuration newConfig) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
// We need to apply this change to the resources
// immediately, because upon returning the view
// hierarchy will be informed about it.
- if (applyConfigurationToResourcesLocked(newConfig, null)) {
+ if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
@@ -5098,8 +4807,10 @@
}
}
}
+ @Override
public void onLowMemory() {
}
+ @Override
public void onTrimMemory(int level) {
}
});
@@ -5119,12 +4830,11 @@
}
public int getIntCoreSetting(String key, int defaultValue) {
- synchronized (mPackages) {
+ synchronized (mResourcesManager) {
if (mCoreSettings != null) {
return mCoreSettings.getInt(key, defaultValue);
- } else {
- return defaultValue;
}
+ return defaultValue;
}
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index a5106e4..6a0fbd5 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -192,6 +192,7 @@
private Context mReceiverRestrictedContext = null;
private boolean mRestricted;
private UserHandle mUser;
+ private ResourcesManager mResourcesManager;
private final Object mSync = new Object();
@@ -1832,8 +1833,9 @@
ContextImpl c = new ContextImpl();
c.init(mPackageInfo, null, mMainThread);
- c.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), getDisplayId(),
- overrideConfiguration, mResources.getCompatibilityInfo(), mActivityToken);
+ c.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
+ getDisplayId(), overrideConfiguration, mResources.getCompatibilityInfo(),
+ mActivityToken);
return c;
}
@@ -1849,8 +1851,8 @@
context.init(mPackageInfo, null, mMainThread);
context.mDisplay = display;
DisplayAdjustments daj = getDisplayAdjustments(displayId);
- context.mResources = mMainThread.getTopLevelResources(mPackageInfo.getResDir(), displayId,
- null, daj.getCompatibilityInfo(), null);
+ context.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
+ displayId, null, daj.getCompatibilityInfo(), null);
return context;
}
@@ -1929,6 +1931,7 @@
mPackageInfo = packageInfo;
mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
mResources = mPackageInfo.getResources(mainThread);
+ mResourcesManager = ResourcesManager.getInstance();
CompatibilityInfo compatInfo =
container == null ? null : container.getCompatibilityInfo();
@@ -1945,7 +1948,7 @@
}
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
mDisplayAdjustments.setActivityToken(activityToken);
- mResources = mainThread.getTopLevelResources(mPackageInfo.getResDir(),
+ mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
} else {
mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 573a6aa..05d3a47 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -138,11 +138,11 @@
if (ActivityThread.mSystemContext == null) {
ActivityThread.mSystemContext =
ContextImpl.createSystemContext(mainThread);
+ ResourcesManager resourcesManager = ResourcesManager.getInstance();
ActivityThread.mSystemContext.getResources().updateConfiguration(
- mainThread.getConfiguration(),
- mainThread.getDisplayMetricsLocked(
- Display.DEFAULT_DISPLAY, mDisplayAdjustments),
- compatInfo);
+ resourcesManager.getConfiguration(),
+ resourcesManager.getDisplayMetricsLocked(
+ Display.DEFAULT_DISPLAY, mDisplayAdjustments), compatInfo);
//Slog.i(TAG, "Created system resources "
// + mSystemContext.getResources() + ": "
// + mSystemContext.getResources().getConfiguration());
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
new file mode 100644
index 0000000..e9693dd
--- /dev/null
+++ b/core/java/android/app/ResourcesManager.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static android.app.ActivityThread.DEBUG_CONFIGURATION;
+
+import android.app.ApplicationPackageManager;
+import android.content.pm.ActivityInfo;
+import android.content.res.AssetManager;
+import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.ResourcesKey;
+import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
+import android.util.ArrayMap;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayAdjustments;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+
+/** @hide */
+public class ResourcesManager {
+ static final String TAG = "ResourcesManager";
+ static final boolean DEBUG_CACHE = false;
+ static final boolean DEBUG_STATS = true;
+
+ private static ResourcesManager sResourcesManager;
+ final HashMap<ResourcesKey, WeakReference<Resources> > mActiveResources
+ = new HashMap<ResourcesKey, WeakReference<Resources> >();
+
+ final ArrayMap<DisplayAdjustments, DisplayMetrics> mDefaultDisplayMetrics
+ = new ArrayMap<DisplayAdjustments, DisplayMetrics>();
+
+ CompatibilityInfo mResCompatibilityInfo;
+
+ Configuration mResConfiguration;
+ final Configuration mTmpConfig = new Configuration();
+
+ public static ResourcesManager getInstance() {
+ synchronized (ResourcesManager.class) {
+ if (sResourcesManager == null) {
+ sResourcesManager = new ResourcesManager();
+ }
+ return sResourcesManager;
+ }
+ }
+
+ public Configuration getConfiguration() {
+ return mResConfiguration;
+ }
+
+ public void flushDisplayMetricsLocked() {
+ mDefaultDisplayMetrics.clear();
+ }
+
+ public DisplayMetrics getDisplayMetricsLocked(int displayId) {
+ return getDisplayMetricsLocked(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+ }
+
+ public DisplayMetrics getDisplayMetricsLocked(int displayId, DisplayAdjustments daj) {
+ boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ DisplayMetrics dm = isDefaultDisplay ? mDefaultDisplayMetrics.get(daj) : null;
+ if (dm != null) {
+ return dm;
+ }
+ dm = new DisplayMetrics();
+
+ DisplayManagerGlobal displayManager = DisplayManagerGlobal.getInstance();
+ if (displayManager == null) {
+ // may be null early in system startup
+ dm.setToDefaults();
+ return dm;
+ }
+
+ if (isDefaultDisplay) {
+ mDefaultDisplayMetrics.put(daj, dm);
+ }
+
+ Display d = displayManager.getCompatibleDisplay(displayId, daj);
+ if (d != null) {
+ d.getMetrics(dm);
+ } else {
+ // Display no longer exists
+ // FIXME: This would not be a problem if we kept the Display object around
+ // instead of using the raw display id everywhere. The Display object caches
+ // its information even after the display has been removed.
+ dm.setToDefaults();
+ }
+ //Slog.i("foo", "New metrics: w=" + metrics.widthPixels + " h="
+ // + metrics.heightPixels + " den=" + metrics.density
+ // + " xdpi=" + metrics.xdpi + " ydpi=" + metrics.ydpi);
+ return dm;
+ }
+
+ final void applyNonDefaultDisplayMetricsToConfigurationLocked(
+ DisplayMetrics dm, Configuration config) {
+ config.touchscreen = Configuration.TOUCHSCREEN_NOTOUCH;
+ config.densityDpi = dm.densityDpi;
+ config.screenWidthDp = (int)(dm.widthPixels / dm.density);
+ config.screenHeightDp = (int)(dm.heightPixels / dm.density);
+ int sl = Configuration.resetScreenLayout(config.screenLayout);
+ if (dm.widthPixels > dm.heightPixels) {
+ config.orientation = Configuration.ORIENTATION_LANDSCAPE;
+ config.screenLayout = Configuration.reduceScreenLayout(sl,
+ config.screenWidthDp, config.screenHeightDp);
+ } else {
+ config.orientation = Configuration.ORIENTATION_PORTRAIT;
+ config.screenLayout = Configuration.reduceScreenLayout(sl,
+ config.screenHeightDp, config.screenWidthDp);
+ }
+ config.smallestScreenWidthDp = config.screenWidthDp; // assume screen does not rotate
+ config.compatScreenWidthDp = config.screenWidthDp;
+ config.compatScreenHeightDp = config.screenHeightDp;
+ config.compatSmallestScreenWidthDp = config.smallestScreenWidthDp;
+ }
+
+ public boolean applyCompatConfiguration(int displayDensity,
+ Configuration compatConfiguration) {
+ if (mResCompatibilityInfo != null && !mResCompatibilityInfo.supportsScreen()) {
+ mResCompatibilityInfo.applyToConfiguration(displayDensity, compatConfiguration);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Creates the top level Resources for applications with the given compatibility info.
+ *
+ * @param resDir the resource directory.
+ * @param compatInfo the compability info. Must not be null.
+ * @param token the application token for determining stack bounds.
+ */
+ public Resources getTopLevelResources(String resDir, int displayId,
+ Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
+ final float scale = compatInfo.applicationScale;
+ ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
+ token);
+ Resources r;
+ synchronized (this) {
+ // Resources is app scale dependent.
+ if (false) {
+ Slog.w(TAG, "getTopLevelResources: " + resDir + " / " + scale);
+ }
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ r = wr != null ? wr.get() : null;
+ //if (r != null) Slog.i(TAG, "isUpToDate " + resDir + ": " + r.getAssets().isUpToDate());
+ if (r != null && r.getAssets().isUpToDate()) {
+ if (false) {
+ Slog.w(TAG, "Returning cached resources " + r + " " + resDir
+ + ": appScale=" + r.getCompatibilityInfo().applicationScale);
+ }
+ return r;
+ }
+ }
+
+ //if (r != null) {
+ // Slog.w(TAG, "Throwing away out-of-date resources!!!! "
+ // + r + " " + resDir);
+ //}
+
+ AssetManager assets = new AssetManager();
+ if (assets.addAssetPath(resDir) == 0) {
+ return null;
+ }
+
+ //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
+ DisplayMetrics dm = getDisplayMetricsLocked(displayId);
+ Configuration config;
+ boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ final boolean hasOverrideConfig = key.hasOverrideConfiguration();
+ if (!isDefaultDisplay || hasOverrideConfig) {
+ config = new Configuration(getConfiguration());
+ if (!isDefaultDisplay) {
+ applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
+ }
+ if (hasOverrideConfig) {
+ config.updateFrom(key.mOverrideConfiguration);
+ }
+ } else {
+ config = getConfiguration();
+ }
+ r = new Resources(assets, dm, config, compatInfo, token);
+ if (false) {
+ Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ + r.getConfiguration() + " appScale="
+ + r.getCompatibilityInfo().applicationScale);
+ }
+
+ synchronized (this) {
+ WeakReference<Resources> wr = mActiveResources.get(key);
+ Resources existing = wr != null ? wr.get() : null;
+ if (existing != null && existing.getAssets().isUpToDate()) {
+ // Someone else already created the resources while we were
+ // unlocked; go ahead and use theirs.
+ r.getAssets().close();
+ return existing;
+ }
+
+ // XXX need to remove entries when weak references go away
+ mActiveResources.put(key, new WeakReference<Resources>(r));
+ return r;
+ }
+ }
+
+ public final boolean applyConfigurationToResourcesLocked(Configuration config,
+ CompatibilityInfo compat) {
+ if (mResConfiguration == null) {
+ mResConfiguration = new Configuration();
+ }
+ if (!mResConfiguration.isOtherSeqNewer(config) && compat == null) {
+ if (DEBUG_CONFIGURATION) Slog.v(TAG, "Skipping new config: curSeq="
+ + mResConfiguration.seq + ", newSeq=" + config.seq);
+ return false;
+ }
+ int changes = mResConfiguration.updateFrom(config);
+ flushDisplayMetricsLocked();
+ DisplayMetrics defaultDisplayMetrics = getDisplayMetricsLocked(Display.DEFAULT_DISPLAY);
+
+ if (compat != null && (mResCompatibilityInfo == null ||
+ !mResCompatibilityInfo.equals(compat))) {
+ mResCompatibilityInfo = compat;
+ changes |= ActivityInfo.CONFIG_SCREEN_LAYOUT
+ | ActivityInfo.CONFIG_SCREEN_SIZE
+ | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+ }
+
+ // set it for java, this also affects newly created Resources
+ if (config.locale != null) {
+ Locale.setDefault(config.locale);
+ }
+
+ Resources.updateSystemConfiguration(config, defaultDisplayMetrics, compat);
+
+ ApplicationPackageManager.configurationChanged();
+ //Slog.i(TAG, "Configuration changed in " + currentPackageName());
+
+ Configuration tmpConfig = null;
+
+ Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
+ mActiveResources.entrySet().iterator();
+ while (it.hasNext()) {
+ 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);
+ int displayId = entry.getKey().mDisplayId;
+ boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
+ DisplayMetrics dm = defaultDisplayMetrics;
+ ResourcesKey resourcesKey = entry.getKey();
+ final boolean hasOverrideConfiguration = resourcesKey.hasOverrideConfiguration();
+ if (!isDefaultDisplay || hasOverrideConfiguration) {
+ if (tmpConfig == null) {
+ tmpConfig = new Configuration();
+ }
+ tmpConfig.setTo(config);
+ if (!isDefaultDisplay) {
+ dm = getDisplayMetricsLocked(displayId);
+ applyNonDefaultDisplayMetricsToConfigurationLocked(dm, tmpConfig);
+ }
+ if (hasOverrideConfiguration) {
+ tmpConfig.updateFrom(resourcesKey.mOverrideConfiguration);
+ }
+ r.updateConfiguration(tmpConfig, dm, compat);
+ } else {
+ r.updateConfiguration(config, dm, compat);
+ }
+ //Slog.i(TAG, "Updated app resources " + v.getKey()
+ // + " " + r + ": " + r.getConfiguration());
+ } else {
+ //Slog.i(TAG, "Removing old resources " + v.getKey());
+ it.remove();
+ }
+ }
+
+ return changes != 0;
+ }
+
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index c24e0ee..6483cd9 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1668,13 +1668,6 @@
}
/**
- * @hide
- */
- public static void updateSystemConfiguration(Configuration config, DisplayMetrics metrics) {
- updateSystemConfiguration(config, metrics, null);
- }
-
- /**
* Return the current display metrics that are in effect for this resource
* object. The returned object should be treated as read-only.
*
diff --git a/core/java/android/content/res/ResourcesKey.java b/core/java/android/content/res/ResourcesKey.java
new file mode 100644
index 0000000..53e0f2c
--- /dev/null
+++ b/core/java/android/content/res/ResourcesKey.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.res;
+
+import android.os.IBinder;
+
+/** @hide */
+public final class ResourcesKey {
+ final String mResDir;
+ final float mScale;
+ private final int mHash;
+ private final IBinder mToken;
+
+ public final int mDisplayId;
+ public final Configuration mOverrideConfiguration = new Configuration();
+
+ public ResourcesKey(String resDir, int displayId, Configuration overrideConfiguration,
+ float scale, IBinder token) {
+ mResDir = resDir;
+ mDisplayId = displayId;
+ if (overrideConfiguration != null) {
+ mOverrideConfiguration.setTo(overrideConfiguration);
+ }
+ mScale = scale;
+ mToken = token;
+
+ int hash = 17;
+ hash = 31 * hash + (mResDir == null ? 0 : mResDir.hashCode());
+ hash = 31 * hash + mDisplayId;
+ hash = 31 * hash + (mOverrideConfiguration != null
+ ? mOverrideConfiguration.hashCode() : 0);
+ hash = 31 * hash + Float.floatToIntBits(mScale);
+ mHash = hash;
+ }
+
+ public boolean hasOverrideConfiguration() {
+ return !Configuration.EMPTY.equals(mOverrideConfiguration);
+ }
+
+ @Override
+ public int hashCode() {
+ return mHash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ResourcesKey)) {
+ return false;
+ }
+ ResourcesKey peer = (ResourcesKey) obj;
+ if (!mResDir.equals(peer.mResDir)) {
+ return false;
+ }
+ if (mDisplayId != peer.mDisplayId) {
+ 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;
+ }
+
+ @Override
+ public String toString() {
+ return Integer.toHexString(mHash);
+ }
+}
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index d86f2c7..2901212 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -822,6 +822,11 @@
pinState.failedAttempts = failedAttempts;
pinState.lastAttemptTime = lastAttemptTime;
}
+ // If this is not a restricted profile and there is no restrictions pin, clean up
+ // any restrictions files that might have been left behind.
+ if (!userInfo.isRestricted() && salt == 0) {
+ cleanAppRestrictions(id);
+ }
return userInfo;
} catch (IOException ioe) {
@@ -873,6 +878,26 @@
}
}
+ /**
+ * Removes all the restrictions files (res_<packagename>) for a given user.
+ * Does not do any permissions checking.
+ */
+ private void cleanAppRestrictions(int userId) {
+ synchronized (mPackagesLock) {
+ File dir = Environment.getUserSystemDirectory(userId);
+ String[] files = dir.list();
+ if (files == null) return;
+ for (String fileName : files) {
+ if (fileName.startsWith(RESTRICTIONS_FILE_PREFIX)) {
+ File resFile = new File(dir, fileName);
+ if (resFile.exists()) {
+ resFile.delete();
+ }
+ }
+ }
+ }
+ }
+
@Override
public UserInfo createUser(String name, int flags) {
checkManageUsersPermission("Only the system can create users");
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 375a160..ae41c9a 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -388,6 +388,10 @@
return doStringCommand("PKTCNT_POLL");
}
+ public void bssFlush() {
+ doBooleanCommand("BSS_FLUSH");
+ }
+
public boolean startWpsPbc(String bssid) {
if (TextUtils.isEmpty(bssid)) {
return doBooleanCommand("WPS_PBC");
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 1f51b2a..d509b37 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -2497,6 +2497,8 @@
if (DBG) log("set frequency band " + band);
if (mWifiNative.setBand(band)) {
mFrequencyBand.set(band);
+ // flush old data - like scan results
+ mWifiNative.bssFlush();
//Fetch the latest scan results when frequency band is set
startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
} else {