diff options
15 files changed, 86 insertions, 40 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index d30010a..063665b 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -172,6 +172,11 @@ public final class ActivityThread { // These can be accessed by multiple threads; mPackages is the lock. // XXX For now we keep around information about all packages we have // seen, not removing entries from this map. + // NOTE: The activity manager in its process needs to call in to + // ActivityThread to do things like update resource configurations, + // which means this lock gets held while the activity manager holds its + // own lock. Thus you MUST NEVER call back into the activity manager + // or anything that depends on it while holding this lock. final HashMap<String, WeakReference<LoadedApk>> mPackages = new HashMap<String, WeakReference<LoadedApk>>(); final HashMap<String, WeakReference<LoadedApk>> mResourcePackages @@ -1480,7 +1485,7 @@ public final class ActivityThread { } public Configuration getConfiguration() { - return mConfiguration; + return mResConfiguration; } public boolean isProfiling() { @@ -1525,7 +1530,7 @@ public final class ActivityThread { synchronized (this) { ContextImpl context = getSystemContext(); context.init(new LoadedApk(this, "android", context, info, - new CompatibilityInfo(info, 0, 0, false)), null, this); + CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this); } } @@ -3274,6 +3279,12 @@ public final class ActivityThread { } } + public final void applyConfigurationToResources(Configuration config) { + synchronized (mPackages) { + applyConfigurationToResourcesLocked(config, null); + } + } + final boolean applyConfigurationToResourcesLocked(Configuration config, CompatibilityInfo compat) { if (mResConfiguration == null) { @@ -3492,8 +3503,7 @@ public final class ActivityThread { * reflect configuration changes. The configuration object passed * in AppBindData can be safely assumed to be up to date */ - Resources.getSystem().updateConfiguration(mConfiguration, - Resources.getSystem().getDisplayMetrics(), data.compatInfo); + applyConfigurationToResourcesLocked(data.config, data.compatInfo); data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 5307696..6287d33 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -98,6 +98,12 @@ final class LoadedApk { return mApplication; } + /** + * Create information about a new .apk + * + * NOTE: This constructor is called with ActivityThread's lock held, + * so MUST NOT call back out to the activity manager. + */ public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo, CompatibilityInfo compatInfo, ActivityThread mainThread, ClassLoader baseLoader, diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java index e42caca..b7b6de6 100644 --- a/core/java/android/content/res/CompatibilityInfo.java +++ b/core/java/android/content/res/CompatibilityInfo.java @@ -243,11 +243,11 @@ public class CompatibilityInfo implements Parcelable { } public boolean neverSupportsScreen() { - return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0; + return (mCompatibilityFlags&ALWAYS_NEEDS_COMPAT) != 0; } public boolean alwaysSupportsScreen() { - return (mCompatibilityFlags&ALWAYS_NEEDS_COMPAT) != 0; + return (mCompatibilityFlags&NEVER_NEEDS_COMPAT) != 0; } /** @@ -406,7 +406,7 @@ public class CompatibilityInfo implements Parcelable { if (!supportsScreen()) { // This is a larger screen device and the app is not // compatible with large screens, so diddle it. - CompatibilityInfo.updateCompatibleScreenFrame(inoutDm, null, inoutDm); + CompatibilityInfo.computeCompatibleScaling(inoutDm, inoutDm); } else { inoutDm.widthPixels = inoutDm.unscaledWidthPixels; inoutDm.heightPixels = inoutDm.unscaledHeightPixels; @@ -443,8 +443,7 @@ public class CompatibilityInfo implements Parcelable { * @param outRect the output parameter which will contain the result. * @return Returns the scaling factor for the window. */ - public static float updateCompatibleScreenFrame(DisplayMetrics dm, - Rect outRect, DisplayMetrics outDm) { + public static float computeCompatibleScaling(DisplayMetrics dm, DisplayMetrics outDm) { final int width = dm.unscaledWidthPixels; final int height = dm.unscaledHeightPixels; int shortSize, longSize; @@ -477,12 +476,6 @@ public class CompatibilityInfo implements Parcelable { scale = 1; } - if (outRect != null) { - final int left = (int)((width-(newWidth*scale))/2); - final int top = (int)((height-(newHeight*scale))/2); - outRect.set(left, top, left+newWidth, top+newHeight); - } - if (outDm != null) { outDm.widthPixels = newWidth; outDm.heightPixels = newHeight; diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java index d476997..6409aac 100644 --- a/core/java/android/content/res/Configuration.java +++ b/core/java/android/content/res/Configuration.java @@ -330,17 +330,17 @@ public final class Configuration implements Parcelable, Comparable<Configuration if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp"); } else { - sb.append("?swdp"); + sb.append(" ?swdp"); } if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) { sb.append(" w"); sb.append(screenWidthDp); sb.append("dp"); } else { - sb.append("?wdp"); + sb.append(" ?wdp"); } if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) { sb.append(" h"); sb.append(screenHeightDp); sb.append("dp"); } else { - sb.append("?hdp"); + sb.append(" ?hdp"); } switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) { case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break; diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 81dc46a..70bf524 100755 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -28,14 +28,13 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable.ConstantState; import android.os.Build; import android.os.Bundle; -import android.os.SystemProperties; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; +import android.util.Slog; import android.util.SparseArray; import android.util.TypedValue; import android.util.LongSparseArray; -import android.view.Display; import java.io.IOException; import java.io.InputStream; @@ -1406,6 +1405,12 @@ public class Resources { public void updateConfiguration(Configuration config, DisplayMetrics metrics, CompatibilityInfo compat) { synchronized (mTmpValue) { + if (false) { + Slog.i(TAG, "**** Updating config of " + this + ": old config is " + + mConfiguration + " old compat is " + mCompatibilityInfo); + Slog.i(TAG, "**** Updating config of " + this + ": new config is " + + config + " new compat is " + compat); + } if (compat != null) { mCompatibilityInfo = compat; } @@ -1471,6 +1476,11 @@ public class Resources { mConfiguration.screenLayout, mConfiguration.uiMode, Build.VERSION.RESOURCES_SDK_INT); + if (false) { + Slog.i(TAG, "**** Updating config of " + this + ": final config is " + mConfiguration + + " final compat is " + mCompatibilityInfo); + } + clearDrawableCache(mDrawableCache, configChanges); clearDrawableCache(mColorDrawableCache, configChanges); diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index bdf04ab..4427eb5 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -19,6 +19,7 @@ package android.view; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethodClient; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Point; @@ -88,7 +89,7 @@ interface IWindowManager void overridePendingAppTransition(String packageName, int enterAnim, int exitAnim); void executeAppTransition(); void setAppStartingWindow(IBinder token, String pkg, int theme, - CharSequence nonLocalizedLabel, int labelRes, + in CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int windowFlags, IBinder transferFrom, boolean createIfNeeded); void setAppWillBeHidden(IBinder token); void setAppVisibility(IBinder token, boolean visible); diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java index beb23aa..4d4569c 100644 --- a/core/java/android/view/WindowManagerPolicy.java +++ b/core/java/android/view/WindowManagerPolicy.java @@ -17,6 +17,7 @@ package android.view; import android.content.Context; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Rect; import android.os.IBinder; @@ -537,7 +538,7 @@ public interface WindowManagerPolicy { * @see #removeStartingWindow */ public View addStartingWindow(IBinder appToken, String packageName, - int theme, CharSequence nonLocalizedLabel, + int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int windowFlags); /** diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 60066e0..36201ac 100755 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.database.ContentObserver; @@ -1110,9 +1111,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } /** {@inheritDoc} */ - public View addStartingWindow(IBinder appToken, String packageName, - int theme, CharSequence nonLocalizedLabel, - int labelRes, int icon, int windowFlags) { + public View addStartingWindow(IBinder appToken, String packageName, int theme, + CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, + int icon, int windowFlags) { if (!SHOW_STARTING_ANIMATIONS) { return null; } @@ -1158,8 +1159,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); + if (!compatInfo.supportsScreen()) { + win.addFlags(WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW); + } + win.setLayout(WindowManager.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.MATCH_PARENT); + WindowManager.LayoutParams.MATCH_PARENT); final WindowManager.LayoutParams params = win.getAttributes(); params.token = appToken; diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index a4a95a0..65f8b34 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -29,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; +import org.apache.commons.logging.impl.SimpleLog; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 080cbda..4cc032f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -12217,6 +12217,15 @@ public final class ActivityManagerService extends ActivityManagerNative ac.updateConfiguration(mConfiguration); } + // Make sure all resources in our process are updated + // right now, so that anyone who is going to retrieve + // resource values after we return will be sure to get + // the new ones. This is especially important during + // boot, where the first config change needs to guarantee + // all resources have that config before following boot + // code is executed. + mSystemThread.applyConfigurationToResources(newConfig); + if (Settings.System.hasInterestingConfigurationChanges(changes)) { Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG); msg.obj = new Configuration(mConfiguration); diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 65ea4f4..2706d49 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -1455,6 +1455,8 @@ public class ActivityStack { if (SHOW_APP_STARTING_PREVIEW && mMainStack) { mService.mWindowManager.setAppStartingWindow( next, next.packageName, next.theme, + mService.compatibilityInfoForPackageLocked( + next.info.applicationInfo), next.nonLocalizedLabel, next.labelRes, next.icon, next.windowFlags, null, true); @@ -1491,6 +1493,8 @@ public class ActivityStack { if (SHOW_APP_STARTING_PREVIEW) { mService.mWindowManager.setAppStartingWindow( next, next.packageName, next.theme, + mService.compatibilityInfoForPackageLocked( + next.info.applicationInfo), next.nonLocalizedLabel, next.labelRes, next.icon, next.windowFlags, null, true); @@ -1617,7 +1621,9 @@ public class ActivityStack { else if (prev.nowVisible) prev = null; } mService.mWindowManager.setAppStartingWindow( - r, r.packageName, r.theme, r.nonLocalizedLabel, + r, r.packageName, r.theme, + mService.compatibilityInfoForPackageLocked( + r.info.applicationInfo), r.nonLocalizedLabel, r.labelRes, r.icon, r.windowFlags, prev, showStartingIcon); } } else { diff --git a/services/java/com/android/server/am/CompatModePackages.java b/services/java/com/android/server/am/CompatModePackages.java index 8949f48..1334bcd 100644 --- a/services/java/com/android/server/am/CompatModePackages.java +++ b/services/java/com/android/server/am/CompatModePackages.java @@ -150,9 +150,11 @@ public class CompatModePackages { } public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) { - return new CompatibilityInfo(ai, mService.mConfiguration.screenLayout, + CompatibilityInfo ci = new CompatibilityInfo(ai, mService.mConfiguration.screenLayout, mService.mConfiguration.smallestScreenWidthDp, (getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0); + //Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci); + return ci; } public int computeCompatModeLocked(ApplicationInfo ai) { diff --git a/services/java/com/android/server/wm/StartingData.java b/services/java/com/android/server/wm/StartingData.java index 625fcfe..46bb480 100644 --- a/services/java/com/android/server/wm/StartingData.java +++ b/services/java/com/android/server/wm/StartingData.java @@ -16,18 +16,23 @@ package com.android.server.wm; +import android.content.res.CompatibilityInfo; + final class StartingData { final String pkg; final int theme; + final CompatibilityInfo compatInfo; final CharSequence nonLocalizedLabel; final int labelRes; final int icon; final int windowFlags; - StartingData(String _pkg, int _theme, CharSequence _nonLocalizedLabel, + StartingData(String _pkg, int _theme, CompatibilityInfo _compatInfo, + CharSequence _nonLocalizedLabel, int _labelRes, int _icon, int _windowFlags) { pkg = _pkg; theme = _theme; + compatInfo = _compatInfo; nonLocalizedLabel = _nonLocalizedLabel; labelRes = _labelRes; icon = _icon; diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 9c98296..7760897 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -602,8 +602,7 @@ public class WindowManagerService extends IWindowManager.Stub final Configuration mTempConfiguration = new Configuration(); - // The frame use to limit the size of the app running in compatibility mode. - Rect mCompatibleScreenFrame = new Rect(); + // The desired scaling factor for compatible apps. float mCompatibleScreenScale; public static WindowManagerService main(Context context, @@ -3526,7 +3525,8 @@ public class WindowManagerService extends IWindowManager.Stub } public void setAppStartingWindow(IBinder token, String pkg, - int theme, CharSequence nonLocalizedLabel, int labelRes, int icon, + int theme, CompatibilityInfo compatInfo, + CharSequence nonLocalizedLabel, int labelRes, int icon, int windowFlags, IBinder transferFrom, boolean createIfNeeded) { if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS, "setAppStartingIcon()")) { @@ -3676,8 +3676,7 @@ public class WindowManagerService extends IWindowManager.Stub } mStartingIconInTransition = true; - wtoken.startingData = new StartingData( - pkg, theme, nonLocalizedLabel, + wtoken.startingData = new StartingData(pkg, theme, compatInfo, nonLocalizedLabel, labelRes, icon, windowFlags); Message m = mH.obtainMessage(H.ADD_STARTING, wtoken); // Note: we really want to do sendMessageAtFrontOfQueue() because we @@ -5562,8 +5561,7 @@ public class WindowManagerService extends IWindowManager.Stub dm.heightPixels = dm.unscaledHeightPixels = mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh); - mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame( - dm, mCompatibleScreenFrame, null); + mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm, null); config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(mRotation, dw) / dm.density); config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(mRotation, dh) / dm.density); @@ -6138,9 +6136,8 @@ public class WindowManagerService extends IWindowManager.Stub View view = null; try { view = mPolicy.addStartingWindow( - wtoken.token, sd.pkg, - sd.theme, sd.nonLocalizedLabel, sd.labelRes, - sd.icon, sd.windowFlags); + wtoken.token, sd.pkg, sd.theme, sd.compatInfo, + sd.nonLocalizedLabel, sd.labelRes, sd.icon, sd.windowFlags); } catch (Exception e) { Slog.w(TAG, "Exception when adding starting window", e); } diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java index e0f0f05..f015378 100644 --- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java +++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java @@ -164,7 +164,7 @@ public class WindowManagerPermissionTests extends TestCase { } try { - mWm.setAppStartingWindow(null, "foo", 0, null, 0, 0, 0, null, false); + mWm.setAppStartingWindow(null, "foo", 0, null, null, 0, 0, 0, null, false); fail("IWindowManager.setAppStartingWindow did not throw SecurityException as" + " expected"); } catch (SecurityException e) { |