resolution support fix/improvement
* adding compatibility menu
* backup gravity
* set expanable=true if the screen size is hvga * density.
* added "supports any density" mode. I'll add sdk check later.
* disallow to catch orientation change event if the app is not expandable. This
was causing layout problem under non-expandable mode. I discussed this with Mike C
and we agreed to do this approach for now. We'll revisit if this causes problem to
a lot of applications.
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index f3dfc5a..f10dd53 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -145,6 +145,13 @@
public static final int FLAG_ALLOW_BACKUP = 1<<10;
/**
+ * Indicates that the application supports any densities;
+ * {@hide}
+ */
+ public static final int ANY_DENSITY = -1;
+ private static final int[] ANY_DENSITIES_ARRAY = { ANY_DENSITY };
+
+ /**
* Flags associated with the application. Any combination of
* {@link #FLAG_SYSTEM}, {@link #FLAG_DEBUGGABLE}, {@link #FLAG_HAS_CODE},
* {@link #FLAG_PERSISTENT}, {@link #FLAG_FACTORY_TEST}, and
@@ -369,4 +376,14 @@
}
return null;
}
+
+ /**
+ * Disable compatibility mode
+ *
+ * @hide
+ */
+ public void disableCompatibilityMode() {
+ expandable = true;
+ supportsDensities = ANY_DENSITIES_ARRAY;
+ }
}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 19379fb..836de39 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -51,10 +51,17 @@
public final float mApplicationInvertedScale;
/**
- *
* A boolean flag to indicates that the application can expand over the original size.
+ * The flag is set to true if
+ * 1) Application declares its expandable in manifest file using <expandable /> or
+ * 2) The screen size is same as (320 x 480) * density.
*/
- public final boolean mExpandable;
+ public boolean mExpandable;
+
+ /**
+ * A expandable flag in the configuration.
+ */
+ public final boolean mConfiguredExpandable;
/**
* A boolean flag to tell if the application needs scaling (when mApplicationScale != 1.0f)
@@ -62,13 +69,16 @@
public final boolean mScalingRequired;
public CompatibilityInfo(ApplicationInfo appInfo) {
- // A temp workaround to fix rotation issue.
- // mExpandable = appInfo.expandable;
- mExpandable = true;
+ mExpandable = mConfiguredExpandable = appInfo.expandable;
+
float packageDensityScale = -1.0f;
if (appInfo.supportsDensities != null) {
int minDiff = Integer.MAX_VALUE;
for (int density : appInfo.supportsDensities) {
+ if (density == ApplicationInfo.ANY_DENSITY) {
+ packageDensityScale = 1.0f;
+ break;
+ }
int tmpDiff = Math.abs(DisplayMetrics.DEVICE_DENSITY - density);
if (tmpDiff == 0) {
packageDensityScale = 1.0f;
@@ -92,7 +102,7 @@
private CompatibilityInfo() {
mApplicationScale = mApplicationInvertedScale = 1.0f;
- mExpandable = true;
+ mExpandable = mConfiguredExpandable = true;
mScalingRequired = false;
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 976b618..2f63820 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -88,7 +88,7 @@
PluralRules mPluralRule;
private final CompatibilityInfo mCompatibilityInfo;
-
+
private static final SparseArray<Object> EMPTY_ARRAY = new SparseArray<Object>() {
@Override
public void put(int k, Object o) {
@@ -1255,7 +1255,7 @@
return array;
}
-
+
/**
* Store the newly updated configuration.
*/
@@ -1268,7 +1268,7 @@
}
if (metrics != null) {
mMetrics.setTo(metrics);
- mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);
+ mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration.orientation);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 52cec22..c2da593 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1025,6 +1025,14 @@
public static final String SCREEN_OFF_TIMEOUT = "screen_off_timeout";
/**
+ * If 0, the compatibility mode is off for all applications.
+ * If 1, older applications run under compatibility mode.
+ * TODO: remove this settings before code freeze (bug/1907571)
+ * @hide
+ */
+ public static final String COMPATIBILITY_MODE = "compatibility_mode";
+
+ /**
* The screen backlight brightness between 0 and 255.
*/
public static final String SCREEN_BRIGHTNESS = "screen_brightness";
diff --git a/core/java/android/util/DisplayMetrics.java b/core/java/android/util/DisplayMetrics.java
index 987be2b..245148d 100644
--- a/core/java/android/util/DisplayMetrics.java
+++ b/core/java/android/util/DisplayMetrics.java
@@ -103,10 +103,10 @@
}
/**
- * Update the display metrics based on the compatibility info and configuration.
+ * Update the display metrics based on the compatibility info and orientation
* {@hide}
*/
- public void updateMetrics(CompatibilityInfo compatibilityInfo, Configuration configuration) {
+ public void updateMetrics(CompatibilityInfo compatibilityInfo, int orientation) {
if (compatibilityInfo.mScalingRequired) {
float invertedRatio = compatibilityInfo.mApplicationInvertedScale;
density *= invertedRatio;
@@ -116,31 +116,42 @@
widthPixels *= invertedRatio;
heightPixels *= invertedRatio;
}
- if (!compatibilityInfo.mExpandable) {
+ if (!compatibilityInfo.mConfiguredExpandable) {
// Note: this assume that configuration is updated before calling
// updateMetrics method.
int defaultWidth;
int defaultHeight;
- switch (configuration.orientation) {
+ switch (orientation) {
case Configuration.ORIENTATION_LANDSCAPE: {
defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
break;
}
- case Configuration.ORIENTATION_UNDEFINED:
case Configuration.ORIENTATION_PORTRAIT:
case Configuration.ORIENTATION_SQUARE:
default: {
defaultWidth = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_WIDTH * density);
defaultHeight = (int)(CompatibilityInfo.DEFAULT_PORTRAIT_HEIGHT * density);
+ break;
+ }
+ case Configuration.ORIENTATION_UNDEFINED: {
+ // don't change
+ return;
}
}
- // adjust the size only when the device's screen is bigger.
- if (defaultWidth < widthPixels) {
- widthPixels = defaultWidth;
- }
- if (defaultHeight < heightPixels) {
- heightPixels = defaultHeight;
+
+ if (defaultWidth == widthPixels && defaultHeight == heightPixels) {
+ // the screen size is same as expected size. make it expandable
+ compatibilityInfo.mExpandable = true;
+ } else {
+ compatibilityInfo.mExpandable = false;
+ // adjust the size only when the device's screen is bigger.
+ if (defaultWidth < widthPixels) {
+ widthPixels = defaultWidth;
+ }
+ if (defaultHeight < heightPixels) {
+ heightPixels = defaultHeight;
+ }
}
}
}
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index d8bab56..ee8229d 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -129,7 +129,6 @@
boolean mIsAnimating;
private CompatibilityInfo mCompatibilityInfo;
- private int[] mWindowLayoutParamsBackup = null;
final View.AttachInfo mAttachInfo;
@@ -388,10 +387,11 @@
if (mView == null) {
mView = view;
mWindowAttributes.copyFrom(attrs);
- mCompatibilityInfo =
- mView.getContext().getResources().getCompatibilityInfo();
- if (mCompatibilityInfo.mScalingRequired) {
- mWindowLayoutParamsBackup = new int[4];
+ mCompatibilityInfo = mView.getContext().getResources().getCompatibilityInfo();
+ boolean restore = false;
+ if (mCompatibilityInfo.mScalingRequired || !mCompatibilityInfo.mExpandable) {
+ restore = true;
+ mWindowAttributes.backup();
}
if (!mCompatibilityInfo.mExpandable) {
adjustWindowAttributesForCompatibleMode(mWindowAttributes);
@@ -420,6 +420,11 @@
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
}
+
+ if (restore) {
+ mWindowAttributes.restore();
+ }
+
if (mCompatibilityInfo.mScalingRequired) {
mAttachInfo.mContentInsets.scale(
mCompatibilityInfo.mApplicationInvertedScale);
@@ -1921,9 +1926,6 @@
} else {
didFinish = false;
}
- if (event != null && mCompatibilityInfo.mScalingRequired) {
- event.scale(mCompatibilityInfo.mApplicationInvertedScale);
- }
if (DEBUG_TRACKBALL) Log.v(TAG, "Motion event:" + event);
@@ -2355,13 +2357,15 @@
boolean restore = false;
float appScale = mCompatibilityInfo.mApplicationScale;
boolean scalingRequired = mCompatibilityInfo.mScalingRequired;
-
if (params != null && !mCompatibilityInfo.mExpandable) {
+ restore = true;
+ params.backup();
adjustWindowAttributesForCompatibleMode(params);
}
if (params != null && scalingRequired) {
+ if (!restore) params.backup();
restore = true;
- params.scale(appScale, mWindowLayoutParamsBackup);
+ params.scale(appScale);
}
int relayoutResult = sWindowSession.relayout(
mWindow, params,
@@ -2370,7 +2374,7 @@
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets, mSurface);
if (restore) {
- params.restore(mWindowLayoutParamsBackup);
+ params.restore();
}
if (scalingRequired) {
float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
@@ -2396,12 +2400,15 @@
if (attrs.width == ViewGroup.LayoutParams.FILL_PARENT) {
attrs.width = metrics.widthPixels;
attrs.gravity |= Gravity.CENTER_HORIZONTAL;
+ mWindowAttributesChanged = attrs == mWindowAttributes;
}
if (attrs.height == ViewGroup.LayoutParams.FILL_PARENT) {
attrs.height = metrics.heightPixels;
+ attrs.gravity |= Gravity.TOP;
+ mWindowAttributesChanged = attrs == mWindowAttributes;
}
if (DEBUG_LAYOUT) {
- Log.d(TAG, "Attributes fixed for compatibility : " + attrs);
+ Log.d(TAG, "Adjusted Attributes for compatibility : " + attrs);
}
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index ec2069c..e1c4687 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -818,6 +818,9 @@
public static final int SCREEN_ORIENTATION_CHANGED = 1<<10;
public static final int SCREEN_BRIGHTNESS_CHANGED = 1<<11;
+ // internal buffer to backup/restore parameters under compatibility mode.
+ private int[] mCompatibilityParamsBackup = null;
+
public final int copyFrom(LayoutParams o) {
int changes = 0;
@@ -975,37 +978,47 @@
/**
* Scale the layout params' coordinates and size.
- * Returns the original info as a backup so that the caller can
- * restore the layout params;
*/
- void scale(float scale, int[] backup) {
- if (scale != 1.0f) {
- backup[0] = x;
- backup[1] = y;
- x *= scale;
- y *= scale;
- if (width > 0) {
- backup[2] = width;
- width *= scale;
- }
- if (height > 0) {
- backup[3] = height;
- height *= scale;
- }
+ void scale(float scale) {
+ x *= scale;
+ y *= scale;
+ if (width > 0) {
+ width *= scale;
+ }
+ if (height > 0) {
+ height *= scale;
}
}
/**
- * Restore the layout params' coordinates and size.
+ * Backup the layout parameters used in compatibility mode.
+ * @see LayoutParams#restore()
*/
- void restore(int[] backup) {
- x = backup[0];
- y = backup[1];
- if (width > 0) {
- width = backup[2];
+ void backup() {
+ int[] backup = mCompatibilityParamsBackup;
+ if (backup == null) {
+ // we backup 5 elements, x, y, width, height and gravity.
+ backup = mCompatibilityParamsBackup = new int[5];
}
- if (height > 0) {
+ backup[0] = x;
+ backup[1] = y;
+ backup[2] = width;
+ backup[3] = height;
+ backup[4] = gravity;
+ }
+
+ /**
+ * Restore the layout params' coordinates, size and gravity
+ * @see LayoutParams#backup()
+ */
+ void restore() {
+ int[] backup = mCompatibilityParamsBackup;
+ if (backup != null) {
+ x = backup[0];
+ y = backup[1];
+ width = backup[2];
height = backup[3];
+ gravity = backup[4];
}
}