Apply override scale from entry points on client

This provides a sandbox-like scaled environment on client side.

- This prevents the metrics and config from being scaled multiple
  times because the entry points are only called from server side,
  there won't have reentrancy for applying the scale.
- App's configuration callback method can get scaled config.
- If override scale is enabled, the legacy compat mode will be
  skipped. That avoids mixing different approaches of scaling.
  - Legacy compat mode is to simulate a 320dp x 480dp screen
    size with density 160 (the surface scale and config scale
    are different).
  - Override scale is to downscale the app for better performance
    (the surface scale and config scale are the same).

Bug: 238416387
Bug: 240335717
Test: atest ActivityThreadTest#testOverrideScale
Test: atest CtsWindowManagerDeviceTestCases:CompatScaleTests
Test: am compat enable DOWNSCALED $pkg
      am compat enable DOWNSCALE_50 $pkg
Change-Id: I0ddf333996f229063511273f8aeb3867c9ba8bda
This commit is contained in:
Riddle Hsu
2022-08-29 18:33:29 -06:00
committed by Xiang Wang
parent 56fe9580ff
commit a0530caa33
13 changed files with 222 additions and 36 deletions

View File

@@ -1177,9 +1177,16 @@ public final class ActivityThread extends ClientTransactionHandler
data.mSerializedSystemFontMap = serializedSystemFontMap;
data.startRequestedElapsedTime = startRequestedElapsedTime;
data.startRequestedUptime = startRequestedUptime;
updateCompatOverrideScale(compatInfo);
CompatibilityInfo.applyOverrideScaleIfNeeded(config);
sendMessage(H.BIND_APPLICATION, data);
}
private void updateCompatOverrideScale(CompatibilityInfo info) {
CompatibilityInfo.setOverrideInvertedScale(
info.hasOverrideScaling() ? info.applicationInvertedScale : 1f);
}
public final void runIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = entryPoint;
@@ -1756,6 +1763,7 @@ public final class ActivityThread extends ClientTransactionHandler
UpdateCompatibilityData ucd = new UpdateCompatibilityData();
ucd.pkg = pkg;
ucd.info = info;
updateCompatOverrideScale(info);
sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
}

View File

@@ -462,13 +462,30 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
/** @hide */
public void scale(float scale) {
mBounds.scale(scale);
mMaxBounds.scale(scale);
scaleBounds(scale, mBounds);
scaleBounds(scale, mMaxBounds);
if (mAppBounds != null) {
mAppBounds.scale(scale);
scaleBounds(scale, mAppBounds);
}
}
/**
* Size based scaling. This avoid inconsistent length when rounding 4 sides.
* E.g. left=12, right=18, scale=0.8. The scaled width can be:
* int((right - left) * scale + 0.5) = int(4.8 + 0.5) = 5
* But with rounding both left and right, the width will be inconsistent:
* int(right * scale + 0.5) - int(left * scale + 0.5) = int(14.9) - int(10.1) = 4
* @hide
*/
private static void scaleBounds(float scale, Rect bounds) {
final int w = bounds.width();
final int h = bounds.height();
bounds.left = (int) (bounds.left * scale + .5f);
bounds.top = (int) (bounds.top * scale + .5f);
bounds.right = bounds.left + (int) (w * scale + .5f);
bounds.bottom = bounds.top + (int) (h * scale + .5f);
}
/**
* Copies the fields from delta into this Configuration object, keeping
* track of which ones have changed. Any undefined fields in {@code delta}

View File

@@ -23,6 +23,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.Parcel;
@@ -40,6 +41,7 @@ public class ActivityConfigurationChangeItem extends ActivityTransactionItem {
@Override
public void preExecute(android.app.ClientTransactionHandler client, IBinder token) {
CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration);
// Notify the client of an upcoming change in the token configuration. This ensures that
// batches of config change items only process the newest configuration.
client.updatePendingActivityConfiguration(token, mConfiguration);

View File

@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.app.ResultInfo;
import android.content.res.CompatibilityInfo;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Trace;
@@ -56,6 +57,7 @@ public class ActivityRelaunchItem extends ActivityTransactionItem {
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
CompatibilityInfo.applyOverrideScaleIfNeeded(mConfig);
mActivityClientRecord = client.prepareRelaunchActivity(token, mPendingResults,
mPendingNewIntents, mConfigChanges, mConfig, mPreserveWindow);
}

View File

@@ -18,6 +18,7 @@ package android.app.servertransaction;
import android.annotation.Nullable;
import android.app.ClientTransactionHandler;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.Parcel;
@@ -34,6 +35,7 @@ public class ConfigurationChangeItem extends ClientTransactionItem {
@Override
public void preExecute(android.app.ClientTransactionHandler client, IBinder token) {
CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration);
client.updatePendingConfiguration(mConfiguration);
}

View File

@@ -30,6 +30,7 @@ import android.app.ResultInfo;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.BaseBundle;
import android.os.Bundle;
@@ -81,6 +82,8 @@ public class LaunchActivityItem extends ClientTransactionItem {
public void preExecute(ClientTransactionHandler client, IBinder token) {
client.countLaunchingActivities(1);
client.updateProcessState(mProcState, false);
CompatibilityInfo.applyOverrideScaleIfNeeded(mCurConfig);
CompatibilityInfo.applyOverrideScaleIfNeeded(mOverrideConfig);
client.updatePendingConfiguration(mCurConfig);
if (mActivityClientController != null) {
ActivityClient.setActivityClientController(mActivityClientController);

View File

@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityThread.ActivityClientRecord;
import android.app.ClientTransactionHandler;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.os.IBinder;
import android.os.Parcel;
@@ -40,6 +41,7 @@ public class MoveToDisplayItem extends ActivityTransactionItem {
@Override
public void preExecute(ClientTransactionHandler client, IBinder token) {
CompatibilityInfo.applyOverrideScaleIfNeeded(mConfiguration);
// Notify the client of an upcoming change in the token configuration. This ensures that
// batches of config change items only process the newest configuration.
client.updatePendingActivityConfiguration(token, mConfiguration);