Merge "Implement per-app window resizing override." into sc-dev

This commit is contained in:
Peiyong Lin
2021-02-02 16:30:40 +00:00
committed by Android (Google) Code Review
3 changed files with 132 additions and 8 deletions

View File

@@ -88,6 +88,11 @@ public class CompatibilityInfo implements Parcelable {
*/
private static final int NEEDS_COMPAT_RES = 16;
/**
* Set if the application needs to be forcibly downscaled
*/
private static final int HAS_OVERRIDE_SCALING = 32;
/**
* The effective screen density we have selected for this application.
*/
@@ -107,6 +112,11 @@ public class CompatibilityInfo implements Parcelable {
@UnsupportedAppUsage
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
boolean forceCompat) {
this(appInfo, screenLayout, sw, forceCompat, 1f);
}
public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
boolean forceCompat, float overrideScale) {
int compatFlags = 0;
if (appInfo.targetSdkVersion < VERSION_CODES.O) {
@@ -241,7 +251,12 @@ public class CompatibilityInfo implements Parcelable {
compatFlags |= NEVER_NEEDS_COMPAT;
}
if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
if (overrideScale != 1.0f) {
applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
applicationScale = overrideScale;
applicationInvertedScale = 1.0f / overrideScale;
compatFlags |= HAS_OVERRIDE_SCALING;
} else if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
applicationDensity = DisplayMetrics.DENSITY_DEVICE;
applicationScale = 1.0f;
applicationInvertedScale = 1.0f;
@@ -277,7 +292,7 @@ public class CompatibilityInfo implements Parcelable {
*/
@UnsupportedAppUsage
public boolean isScalingRequired() {
return (mCompatibilityFlags&SCALING_REQUIRED) != 0;
return (mCompatibilityFlags & (SCALING_REQUIRED | HAS_OVERRIDE_SCALING)) != 0;
}
@UnsupportedAppUsage
@@ -303,7 +318,7 @@ public class CompatibilityInfo implements Parcelable {
*/
@UnsupportedAppUsage
public Translator getTranslator() {
return isScalingRequired() ? new Translator() : null;
return (mCompatibilityFlags & SCALING_REQUIRED) != 0 ? new Translator() : null;
}
/**
@@ -504,6 +519,16 @@ public class CompatibilityInfo implements Parcelable {
if (isScalingRequired()) {
float invertedRatio = applicationInvertedScale;
inoutConfig.densityDpi = (int)((inoutConfig.densityDpi * invertedRatio) + .5f);
inoutConfig.screenWidthDp = (int) ((inoutConfig.screenWidthDp * invertedRatio) + .5f);
inoutConfig.screenHeightDp = (int) ((inoutConfig.screenHeightDp * invertedRatio) + .5f);
inoutConfig.smallestScreenWidthDp =
(int) ((inoutConfig.smallestScreenWidthDp * invertedRatio) + .5f);
inoutConfig.windowConfiguration.getMaxBounds().scale(invertedRatio);
inoutConfig.windowConfiguration.getBounds().scale(invertedRatio);
final Rect appBounds = inoutConfig.windowConfiguration.getAppBounds();
if (appBounds != null) {
appBounds.scale(invertedRatio);
}
}
}

View File

@@ -24,6 +24,9 @@ import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import android.app.ActivityManager;
import android.app.AppGlobals;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.Disabled;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.res.CompatibilityInfo;
@@ -32,6 +35,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.util.AtomicFile;
import android.util.Slog;
import android.util.SparseArray;
@@ -63,6 +67,58 @@ public final class CompatModePackages {
// Compatibility state: compatibility mode is enabled.
private static final int COMPAT_FLAG_ENABLED = 1<<1;
/**
* CompatModePackages#DOWNSCALED is the gatekeeper of all per-app buffer downscaling
* changes. Disabling this change will prevent the following scaling factors from working:
* CompatModePackages#DOWNSCALE_87_5
* CompatModePackages#DOWNSCALE_75
* CompatModePackages#DOWNSCALE_62_5
* CompatModePackages#DOWNSCALE_50
*
* If CompatModePackages#DOWNSCALED is enabled for an app package, then the app will be forcibly
* resized to the highest enabled scaling factor e.g. 87.5% if both 87.5% and 75% were
* enabled.
*/
@ChangeId
@Disabled
private static final long DOWNSCALED = 168419799L;
/**
* With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id
* CompatModePackages#DOWNSCALE_87_5 for a package will force the app to assume it's
* running on a display with 87.5% the vertical and horizontal resolution of the real display.
*/
@ChangeId
@Disabled
private static final long DOWNSCALE_87_5 = 176926753L;
/**
* With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id
* CompatModePackages#DOWNSCALE_75 for a package will force the app to assume it's
* running on a display with 75% the vertical and horizontal resolution of the real display.
*/
@ChangeId
@Disabled
private static final long DOWNSCALE_75 = 176926829L;
/**
* With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id
* CompatModePackages#DOWNSCALE_62_5 for a package will force the app to assume it's
* running on a display with 62.5% the vertical and horizontal resolution of the real display.
*/
@ChangeId
@Disabled
private static final long DOWNSCALE_62_5 = 176926771L;
/**
* With CompatModePackages#DOWNSCALED enabled, subsequently enabling change-id
* CompatModePackages#DOWNSCALE_50 for a package will force the app to assume it's
* running on a display with 50% vertical and horizontal resolution of the real display.
*/
@ChangeId
@Disabled
private static final long DOWNSCALE_50 = 176926741L;
private final HashMap<String, Integer> mPackages = new HashMap<String, Integer>();
private static final int MSG_WRITE = 300;
@@ -191,11 +247,39 @@ public final class CompatModePackages {
mHandler.sendMessageDelayed(msg, 10000);
}
float getCompatScale(String packageName, int uid) {
if (!CompatChanges.isChangeEnabled(
DOWNSCALED, packageName, UserHandle.getUserHandleForUid(uid))) {
return 1f;
}
if (CompatChanges.isChangeEnabled(
DOWNSCALE_87_5, packageName, UserHandle.getUserHandleForUid(uid))) {
// 8/7 == (1 / 0.875) ~= 1.14285714286
return 8f / 7f;
}
if (CompatChanges.isChangeEnabled(
DOWNSCALE_75, packageName, UserHandle.getUserHandleForUid(uid))) {
// 4/3 == (1 / 0.75) ~= 1.333333333
return 4f / 3f;
}
if (CompatChanges.isChangeEnabled(
DOWNSCALE_62_5, packageName, UserHandle.getUserHandleForUid(uid))) {
// (1 / 0.625) == 1.6
return 1.6f;
}
if (CompatChanges.isChangeEnabled(
DOWNSCALE_50, packageName, UserHandle.getUserHandleForUid(uid))) {
return 2f;
}
return 1f;
}
public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
final Configuration globalConfig = mService.getGlobalConfiguration();
final float requestedScale = getCompatScale(ai.packageName, ai.uid);
CompatibilityInfo ci = new CompatibilityInfo(ai, globalConfig.screenLayout,
globalConfig.smallestScreenWidthDp,
(getPackageFlags(ai.packageName)&COMPAT_FLAG_ENABLED) != 0);
(getPackageFlags(ai.packageName) & COMPAT_FLAG_ENABLED) != 0, requestedScale);
//Slog.i(TAG, "*********** COMPAT FOR PKG " + ai.packageName + ": " + ci);
return ci;
}

View File

@@ -441,6 +441,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
float mGlobalScale=1;
float mLastGlobalScale=1;
float mInvGlobalScale=1;
float mOverrideScale = 1;
float mHScale=1, mVScale=1;
float mLastHScale=1, mLastVScale=1;
final Matrix mTmpMatrix = new Matrix();
@@ -1014,6 +1015,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mLastRequestedWidth = 0;
mLastRequestedHeight = 0;
mLayer = 0;
mOverrideScale = mWmService.mAtmService.mCompatModePackages.getCompatScale(
mAttrs.packageName, s.mUid);
// Make sure we initial all fields before adding to parentWindow, to prevent exception
// during onDisplayChanged.
@@ -1046,8 +1049,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mSession.windowAddedLocked(mAttrs.packageName);
}
/**
* @return {@code true} if the application runs in size compatibility mode or has an app level
* scaling override set.
* @see CompatModePackages#getCompatScale
* @see android.content.res.CompatibilityInfo#supportsScreen
* @see ActivityRecord#inSizeCompatMode()
*/
boolean inSizeCompatMode() {
return inSizeCompatMode(mAttrs, mActivityRecord);
return mOverrideScale != 1f || inSizeCompatMode(mAttrs, mActivityRecord);
}
/**
@@ -1682,7 +1692,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
void prelayout() {
if (inSizeCompatMode()) {
mGlobalScale = mToken.getSizeCompatScale();
if (mOverrideScale != 1f) {
mGlobalScale = mToken.hasSizeCompatBounds()
? mToken.getSizeCompatScale() * mOverrideScale
: mOverrideScale;
} else {
mGlobalScale = mToken.getSizeCompatScale();
}
mInvGlobalScale = 1 / mGlobalScale;
} else {
mGlobalScale = mInvGlobalScale = 1;
@@ -2640,8 +2656,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// scaling but the existing logic doesn't expect that. The result is that the already-
// scaled region ends up getting sent to surfaceflinger which then applies the scale
// (again). Until this is resolved, apply an inverse-scale here.
if (mActivityRecord != null && mActivityRecord.hasSizeCompatBounds()
&& mGlobalScale != 1.f) {
if (mInvGlobalScale != 1.f) {
region.scale(mInvGlobalScale);
}