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:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user