Merge "Allow camera to specify a refresh rate range" into tm-dev am: baec980e23

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17008563

Change-Id: I6ed53a1208c336c1f29a82796fc0908a61accec8
This commit is contained in:
Austin Borger
2022-03-08 18:26:52 +00:00
committed by Automerger Merge Worker
5 changed files with 115 additions and 24 deletions

View File

@@ -1068,7 +1068,9 @@ public class CameraServiceProxy extends SystemService
if (!alreadyActivePackage) { if (!alreadyActivePackage) {
WindowManagerInternal wmi = WindowManagerInternal wmi =
LocalServices.getService(WindowManagerInternal.class); LocalServices.getService(WindowManagerInternal.class);
wmi.addNonHighRefreshRatePackage(clientName); // TODO(b/209669709): populate min.max refreshRate based on
// the camera capture speed
wmi.addRefreshRateRangeForPackage(clientName, 60.0f, 60.0f);
} }
// Update activity events // Update activity events
@@ -1107,7 +1109,7 @@ public class CameraServiceProxy extends SystemService
if (!stillActivePackage) { if (!stillActivePackage) {
WindowManagerInternal wmi = WindowManagerInternal wmi =
LocalServices.getService(WindowManagerInternal.class); LocalServices.getService(WindowManagerInternal.class);
wmi.removeNonHighRefreshRatePackage(clientName); wmi.removeRefreshRateRangeForPackage(clientName);
} }
} }

View File

@@ -19,20 +19,46 @@ package com.android.server.wm;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import android.util.ArraySet; import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.view.Display; import android.view.Display;
import android.view.Display.Mode; import android.view.Display.Mode;
import android.view.DisplayInfo; import android.view.DisplayInfo;
import java.util.HashMap;
/** /**
* Policy to select a lower refresh rate for the display if applicable. * Policy to select a lower refresh rate for the display if applicable.
*/ */
class RefreshRatePolicy { class RefreshRatePolicy {
class PackageRefreshRate {
private final HashMap<String, RefreshRateRange> mPackages = new HashMap<>();
public void add(String s, float minRefreshRate, float maxRefreshRate) {
float minSupportedRefreshRate =
Math.max(RefreshRatePolicy.this.mMinSupportedRefreshRate, minRefreshRate);
float maxSupportedRefreshRate =
Math.min(RefreshRatePolicy.this.mMaxSupportedRefreshRate, maxRefreshRate);
mPackages.put(s,
new RefreshRateRange(minSupportedRefreshRate, maxSupportedRefreshRate));
}
public RefreshRateRange get(String s) {
return mPackages.get(s);
}
public void remove(String s) {
mPackages.remove(s);
}
}
private final Mode mLowRefreshRateMode; private final Mode mLowRefreshRateMode;
private final ArraySet<String> mNonHighRefreshRatePackages = new ArraySet<>(); private final PackageRefreshRate mNonHighRefreshRatePackages = new PackageRefreshRate();
private final HighRefreshRateDenylist mHighRefreshRateDenylist; private final HighRefreshRateDenylist mHighRefreshRateDenylist;
private final WindowManagerService mWmService; private final WindowManagerService mWmService;
private float mMinSupportedRefreshRate;
private float mMaxSupportedRefreshRate;
/** /**
* The following constants represent priority of the window. SF uses this information when * The following constants represent priority of the window. SF uses this information when
@@ -70,7 +96,12 @@ class RefreshRatePolicy {
Mode mode = displayInfo.getDefaultMode(); Mode mode = displayInfo.getDefaultMode();
float[] refreshRates = displayInfo.getDefaultRefreshRates(); float[] refreshRates = displayInfo.getDefaultRefreshRates();
float bestRefreshRate = mode.getRefreshRate(); float bestRefreshRate = mode.getRefreshRate();
mMinSupportedRefreshRate = bestRefreshRate;
mMaxSupportedRefreshRate = bestRefreshRate;
for (int i = refreshRates.length - 1; i >= 0; i--) { for (int i = refreshRates.length - 1; i >= 0; i--) {
mMinSupportedRefreshRate = Math.min(mMinSupportedRefreshRate, refreshRates[i]);
mMaxSupportedRefreshRate = Math.max(mMaxSupportedRefreshRate, refreshRates[i]);
if (refreshRates[i] >= 60f && refreshRates[i] < bestRefreshRate) { if (refreshRates[i] >= 60f && refreshRates[i] < bestRefreshRate) {
bestRefreshRate = refreshRates[i]; bestRefreshRate = refreshRates[i];
} }
@@ -78,12 +109,13 @@ class RefreshRatePolicy {
return displayInfo.findDefaultModeByRefreshRate(bestRefreshRate); return displayInfo.findDefaultModeByRefreshRate(bestRefreshRate);
} }
void addNonHighRefreshRatePackage(String packageName) { void addRefreshRateRangeForPackage(String packageName,
mNonHighRefreshRatePackages.add(packageName); float minRefreshRate, float maxRefreshRate) {
mNonHighRefreshRatePackages.add(packageName, minRefreshRate, maxRefreshRate);
mWmService.requestTraversal(); mWmService.requestTraversal();
} }
void removeNonHighRefreshRatePackage(String packageName) { void removeRefreshRateRangeForPackage(String packageName) {
mNonHighRefreshRatePackages.remove(packageName); mNonHighRefreshRatePackages.remove(packageName);
mWmService.requestTraversal(); mWmService.requestTraversal();
} }
@@ -172,8 +204,9 @@ class RefreshRatePolicy {
// If app is using Camera, we set both the min and max refresh rate to the camera's // If app is using Camera, we set both the min and max refresh rate to the camera's
// preferred refresh rate to make sure we don't end up with a refresh rate lower // preferred refresh rate to make sure we don't end up with a refresh rate lower
// than the camera capture rate, which will lead to dropping camera frames. // than the camera capture rate, which will lead to dropping camera frames.
if (mNonHighRefreshRatePackages.contains(packageName)) { RefreshRateRange range = mNonHighRefreshRatePackages.get(packageName);
return mLowRefreshRateMode.getRefreshRate(); if (range != null) {
return range.min;
} }
return 0; return 0;
@@ -192,8 +225,9 @@ class RefreshRatePolicy {
final String packageName = w.getOwningPackage(); final String packageName = w.getOwningPackage();
// If app is using Camera, force it to default (lower) refresh rate. // If app is using Camera, force it to default (lower) refresh rate.
if (mNonHighRefreshRatePackages.contains(packageName)) { RefreshRateRange range = mNonHighRefreshRatePackages.get(packageName);
return mLowRefreshRateMode.getRefreshRate(); if (range != null) {
return range.max;
} }
return 0; return 0;

View File

@@ -725,17 +725,18 @@ public abstract class WindowManagerInternal {
public abstract void hideIme(IBinder imeTargetWindowToken, int displayId); public abstract void hideIme(IBinder imeTargetWindowToken, int displayId);
/** /**
* Tell window manager about a package that should not be running with high refresh rate * Tell window manager about a package that should be running with a restricted range of
* setting until removeNonHighRefreshRatePackage is called for the same package. * refresh rate setting until removeRefreshRateRangeForPackage is called for the same package.
* *
* This must not be called again for the same package. * This must not be called again for the same package.
*/ */
public abstract void addNonHighRefreshRatePackage(@NonNull String packageName); public abstract void addRefreshRateRangeForPackage(@NonNull String packageName,
float minRefreshRate, float maxRefreshRate);
/** /**
* Tell window manager to stop constraining refresh rate for the given package. * Tell window manager to stop constraining refresh rate for the given package.
*/ */
public abstract void removeNonHighRefreshRatePackage(@NonNull String packageName); public abstract void removeRefreshRateRangeForPackage(@NonNull String packageName);
/** /**
* Checks if the device supports touch or faketouch. * Checks if the device supports touch or faketouch.

View File

@@ -7969,18 +7969,20 @@ public class WindowManagerService extends IWindowManager.Stub
} }
@Override @Override
public void addNonHighRefreshRatePackage(@NonNull String packageName) { public void addRefreshRateRangeForPackage(@NonNull String packageName,
float minRefreshRate, float maxRefreshRate) {
synchronized (mGlobalLock) { synchronized (mGlobalLock) {
mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy() mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
.addNonHighRefreshRatePackage(packageName)); .addRefreshRateRangeForPackage(
packageName, minRefreshRate, maxRefreshRate));
} }
} }
@Override @Override
public void removeNonHighRefreshRatePackage(@NonNull String packageName) { public void removeRefreshRateRangeForPackage(@NonNull String packageName) {
synchronized (mGlobalLock) { synchronized (mGlobalLock) {
mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy() mRoot.forAllDisplays(dc -> dc.getDisplayPolicy().getRefreshRatePolicy()
.removeNonHighRefreshRatePackage(packageName)); .removeRefreshRateRangeForPackage(packageName));
} }
} }

View File

@@ -101,14 +101,63 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.addNonHighRefreshRatePackage("com.android.test"); mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE, LOW_REFRESH_RATE);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(LOW_REFRESH_RATE, assertEquals(LOW_REFRESH_RATE,
mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(LOW_REFRESH_RATE, assertEquals(LOW_REFRESH_RATE,
mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.removeNonHighRefreshRatePackage("com.android.test"); mPolicy.removeRefreshRateRangeForPackage("com.android.test");
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
}
@Test
public void testCameraRange() {
final WindowState cameraUsingWindow = createWindow("cameraUsingWindow");
cameraUsingWindow.mAttrs.packageName = "com.android.test";
parcelLayoutParams(cameraUsingWindow);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE, MID_REFRESH_RATE);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(LOW_REFRESH_RATE,
mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(MID_REFRESH_RATE,
mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.removeRefreshRateRangeForPackage("com.android.test");
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
}
@Test
public void testCameraRange_OutOfRange() {
final WindowState cameraUsingWindow = createWindow("cameraUsingWindow");
cameraUsingWindow.mAttrs.packageName = "com.android.test";
parcelLayoutParams(cameraUsingWindow);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE - 10, HI_REFRESH_RATE + 10);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(LOW_REFRESH_RATE,
mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(HI_REFRESH_RATE,
mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.removeRefreshRateRangeForPackage("com.android.test");
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMinRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
@@ -162,7 +211,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
overrideWindow.mAttrs.packageName = "com.android.test"; overrideWindow.mAttrs.packageName = "com.android.test";
overrideWindow.mAttrs.preferredDisplayModeId = HI_MODE_ID; overrideWindow.mAttrs.preferredDisplayModeId = HI_MODE_ID;
parcelLayoutParams(overrideWindow); parcelLayoutParams(overrideWindow);
mPolicy.addNonHighRefreshRatePackage("com.android.test"); mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE, LOW_REFRESH_RATE);
assertEquals(HI_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); assertEquals(HI_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
assertEquals(HI_REFRESH_RATE, assertEquals(HI_REFRESH_RATE,
mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE);
@@ -178,7 +228,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
overrideWindow.mAttrs.packageName = "com.android.test"; overrideWindow.mAttrs.packageName = "com.android.test";
overrideWindow.mAttrs.preferredRefreshRate = HI_REFRESH_RATE; overrideWindow.mAttrs.preferredRefreshRate = HI_REFRESH_RATE;
parcelLayoutParams(overrideWindow); parcelLayoutParams(overrideWindow);
mPolicy.addNonHighRefreshRatePackage("com.android.test"); mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE, LOW_REFRESH_RATE);
assertEquals(0, mPolicy.getPreferredModeId(overrideWindow)); assertEquals(0, mPolicy.getPreferredModeId(overrideWindow));
assertEquals(HI_REFRESH_RATE, assertEquals(HI_REFRESH_RATE,
mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE);
@@ -257,7 +308,8 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
cameraUsingWindow.mAttrs.packageName = "com.android.test"; cameraUsingWindow.mAttrs.packageName = "com.android.test";
parcelLayoutParams(cameraUsingWindow); parcelLayoutParams(cameraUsingWindow);
mPolicy.addNonHighRefreshRatePackage("com.android.test"); mPolicy.addRefreshRateRangeForPackage("com.android.test",
LOW_REFRESH_RATE, LOW_REFRESH_RATE);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow)); assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(LOW_REFRESH_RATE, assertEquals(LOW_REFRESH_RATE,