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.
This commit is contained in:
Mitsuru Oshima
2009-06-09 21:16:08 -07:00
parent ca436e24de
commit e5fb328825
8 changed files with 166 additions and 60 deletions

View File

@@ -144,6 +144,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
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},
@@ -369,4 +376,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
}
return null;
}
/**
* Disable compatibility mode
*
* @hide
*/
public void disableCompatibilityMode() {
expandable = true;
supportsDensities = ANY_DENSITIES_ARRAY;
}
}

View File

@@ -51,10 +51,17 @@ public class CompatibilityInfo {
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 class CompatibilityInfo {
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 @@ public class CompatibilityInfo {
private CompatibilityInfo() {
mApplicationScale = mApplicationInvertedScale = 1.0f;
mExpandable = true;
mExpandable = mConfiguredExpandable = true;
mScalingRequired = false;
}

View File

@@ -88,7 +88,7 @@ public class Resources {
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 @@ public class Resources {
return array;
}
/**
* Store the newly updated configuration.
*/
@@ -1268,7 +1268,7 @@ public class Resources {
}
if (metrics != null) {
mMetrics.setTo(metrics);
mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration);
mMetrics.updateMetrics(mCompatibilityInfo, mConfiguration.orientation);
}
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;

View File

@@ -1024,6 +1024,14 @@ public final class Settings {
*/
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.
*/

View File

@@ -103,10 +103,10 @@ public class DisplayMetrics {
}
/**
* 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 @@ public class DisplayMetrics {
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;
}
}
}
}

View File

@@ -129,7 +129,6 @@ public final class ViewRoot extends Handler implements ViewParent,
boolean mIsAnimating;
private CompatibilityInfo mCompatibilityInfo;
private int[] mWindowLayoutParamsBackup = null;
final View.AttachInfo mAttachInfo;
@@ -388,10 +387,11 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
unscheduleTraversals();
throw new RuntimeException("Adding window failed", e);
}
if (restore) {
mWindowAttributes.restore();
}
if (mCompatibilityInfo.mScalingRequired) {
mAttachInfo.mContentInsets.scale(
mCompatibilityInfo.mApplicationInvertedScale);
@@ -1921,9 +1926,6 @@ public final class ViewRoot extends Handler implements ViewParent,
} 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 @@ public final class ViewRoot extends Handler implements ViewParent,
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 @@ public final class ViewRoot extends Handler implements ViewParent,
viewVisibility, insetsPending, mWinFrame,
mPendingContentInsets, mPendingVisibleInsets, mSurface);
if (restore) {
params.restore(mWindowLayoutParamsBackup);
params.restore();
}
if (scalingRequired) {
float invertedScale = mCompatibilityInfo.mApplicationInvertedScale;
@@ -2396,12 +2400,15 @@ public final class ViewRoot extends Handler implements ViewParent,
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);
}
}
}

View File

@@ -818,6 +818,9 @@ public interface WindowManager extends ViewManager {
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 @@ public interface WindowManager extends ViewManager {
/**
* 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];
}
}

View File

@@ -58,6 +58,8 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.Signature;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Binder;
import android.os.Build;
@@ -259,6 +261,7 @@ class PackageManagerService extends IPackageManager.Stub {
final ResolveInfo mResolveInfo = new ResolveInfo();
ComponentName mResolveComponentName;
PackageParser.Package mPlatformPackage;
private boolean mCompatibilityModeEnabled = true;
public static final IPackageManager main(Context context, boolean factoryTest) {
PackageManagerService m = new PackageManagerService(context, factoryTest);
@@ -509,7 +512,7 @@ class PackageManagerService extends IPackageManager.Stub {
} // synchronized (mPackages)
} // synchronized (mInstallLock)
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
@@ -885,7 +888,11 @@ class PackageManagerService extends IPackageManager.Stub {
+ ": " + p);
if (p != null) {
// Note: isEnabledLP() does not apply here - always return info
return PackageParser.generateApplicationInfo(p, flags);
ApplicationInfo appInfo = PackageParser.generateApplicationInfo(p, flags);
if (!mCompatibilityModeEnabled) {
appInfo.disableCompatibilityMode();
}
return appInfo;
}
if ("android".equals(packageName)||"system".equals(packageName)) {
return mAndroidApplication;
@@ -952,10 +959,35 @@ class PackageManagerService extends IPackageManager.Stub {
public ActivityInfo getActivityInfo(ComponentName component, int flags) {
synchronized (mPackages) {
PackageParser.Activity a = mActivities.mActivities.get(component);
if (Config.LOGV) Log.v(
TAG, "getActivityInfo " + component + ": " + a);
if (Config.LOGV) Log.v(TAG, "getActivityInfo " + component + ": " + a);
if (a != null && mSettings.isEnabledLP(a.info, flags)) {
return PackageParser.generateActivityInfo(a, flags);
ActivityInfo ainfo = PackageParser.generateActivityInfo(a, flags);
if (ainfo != null && (flags & PackageManager.GET_EXPANDABLE) != 0) {
ApplicationInfo appInfo = getApplicationInfo(component.getPackageName(),
PackageManager.GET_EXPANDABLE | PackageManager.GET_SUPPORTS_DENSITIES);
if (appInfo != null && !appInfo.expandable) {
// Check if the screen size is same as what the application expect.
CompatibilityInfo info = new CompatibilityInfo(appInfo);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setTo(mMetrics);
int orientation = mMetrics.widthPixels > mMetrics.heightPixels ?
Configuration.ORIENTATION_LANDSCAPE :
Configuration.ORIENTATION_PORTRAIT;
metrics.updateMetrics(info, orientation);
if (!info.mExpandable) {
// Don't allow an app that cannot expand to handle rotation.
ainfo.configChanges &= ~ ActivityInfo.CONFIG_ORIENTATION;
} else {
appInfo.expandable = true;
}
if (DEBUG_SETTINGS) {
Log.d(TAG, "component=" + component +
", expandable:" + appInfo.expandable);
}
}
}
return ainfo;
}
if (mResolveComponentName.equals(component)) {
return mResolveActivity;
@@ -4709,6 +4741,14 @@ class PackageManagerService extends IPackageManager.Stub {
public void systemReady() {
mSystemReady = true;
// Read the compatibilty setting when the system is ready.
mCompatibilityModeEnabled = android.provider.Settings.System.getInt(
mContext.getContentResolver(),
android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1;
if (DEBUG_SETTINGS) {
Log.d(TAG, "compatibility mode:" + mCompatibilityModeEnabled);
}
}
public boolean isSafeMode() {