diff options
author | Dianne Hackborn <hackbod@google.com> | 2011-05-31 17:59:49 -0700 |
---|---|---|
committer | Dianne Hackborn <hackbod@google.com> | 2011-05-31 18:04:14 -0700 |
commit | 2f0b17573d4324832f7a20402a3d2b5920bc4866 (patch) | |
tree | eb85b9344237741f21f4989950677692b3bdbbda | |
parent | 8ede62745faa02265f927941d1195b6c1bf05ebb (diff) | |
download | frameworks_base-2f0b17573d4324832f7a20402a3d2b5920bc4866.zip frameworks_base-2f0b17573d4324832f7a20402a3d2b5920bc4866.tar.gz frameworks_base-2f0b17573d4324832f7a20402a3d2b5920bc4866.tar.bz2 |
Fix issue #4502672: Wrong xml resources used for homescreen widgets.
There was a race in the system process between applying the initial
configuration and executing code in higher-level system services
like the app widget service that relies on the config. For some
reason it starting showing up more after my code changes; it should
now be completely fixed.
Also fix the activity starting window to run in compatibility mode
if its application is going to be in compatibility mode.
And some various cleanup and small fixes.
Change-Id: I0566933bf1bbb4259c1d99a60c0a3c19af1542e5
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) { |