Separate refresh rate restrictions for different High Brightness Modes
Allow setting a different refresh rate for High Brightness Mode for HDR
and for Sunlight.
Bug: 196691596
Test: atest DisplayModeDirectorTest
Test: Manual:
1. Ensure HBM for HDR takes presedence over HBM for Sunlight
2. Ensure app refresh rate votes override bothHBM for Sunlight
Change-Id: I4a29c47f218046d0852178ad5dc7484a86ef8607
Merged-In: I4a29c47f218046d0852178ad5dc7484a86ef8607
This commit is contained in:
committed by
Yichi Chen
parent
7e783bb071
commit
46fff422b4
@@ -1257,6 +1257,23 @@ public final class DisplayManager {
|
||||
*/
|
||||
String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||
"fixed_refresh_rate_high_ambient_brightness_thresholds";
|
||||
|
||||
/**
|
||||
* Key for refresh rate when the device is in high brightness mode for sunlight visility.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.integer#config_defaultRefreshRateInHbmSunlight
|
||||
*/
|
||||
String KEY_REFRESH_RATE_IN_HBM_SUNLIGHT = "refresh_rate_in_hbm_sunlight";
|
||||
|
||||
/**
|
||||
* Key for refresh rate when the device is in high brightness mode for HDR.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.integer#config_defaultRefreshRateInHbmHdr
|
||||
*/
|
||||
String KEY_REFRESH_RATE_IN_HBM_HDR = "refresh_rate_in_hbm_hdr";
|
||||
|
||||
/**
|
||||
* Key for default peak refresh rate
|
||||
*
|
||||
|
||||
@@ -4492,6 +4492,13 @@
|
||||
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||
<integer name="config_fixedRefreshRateInHighZone">0</integer>
|
||||
|
||||
<!-- Default refresh rate while the device has high brightness mode enabled for Sunlight.
|
||||
This value overrides values from DisplayDeviceConfig -->
|
||||
<integer name="config_defaultRefreshRateInHbmSunlight">0</integer>
|
||||
|
||||
<!-- Default refresh rate while the device has high brightness mode enabled for HDR. -->
|
||||
<integer name="config_defaultRefreshRateInHbmHdr">0</integer>
|
||||
|
||||
<!-- The type of the light sensor to be used by the display framework for things like
|
||||
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
|
||||
<string name="config_displayLightSensorType" translatable="false" />
|
||||
|
||||
@@ -3948,6 +3948,8 @@
|
||||
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
|
||||
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
||||
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
|
||||
<java-symbol type="integer" name="config_defaultRefreshRateInHbmSunlight" />
|
||||
<java-symbol type="integer" name="config_defaultRefreshRateInHbmHdr" />
|
||||
|
||||
<!-- For fixed refresh rate displays in high brightness-->
|
||||
<java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
|
||||
|
||||
@@ -53,6 +53,7 @@ import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
|
||||
@@ -77,7 +78,6 @@ import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
/**
|
||||
* The DisplayModeDirector is responsible for determining what modes are allowed to be automatically
|
||||
* picked by the system based on system-wide and display-specific configuration.
|
||||
@@ -92,6 +92,8 @@ public class DisplayModeDirector {
|
||||
private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4;
|
||||
private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
|
||||
private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
|
||||
private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7;
|
||||
private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8;
|
||||
|
||||
// Special ID used to indicate that given vote is to be applied globally, rather than to a
|
||||
// specific display.
|
||||
@@ -161,9 +163,10 @@ public class DisplayModeDirector {
|
||||
}
|
||||
};
|
||||
mSensorObserver = new SensorObserver(context, ballotBox, injector);
|
||||
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
|
||||
mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
|
||||
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
||||
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
|
||||
mDeviceConfigDisplaySettings);
|
||||
mDeviceConfig = injector.getDeviceConfig();
|
||||
mAlwaysRespectAppRequest = false;
|
||||
}
|
||||
@@ -723,6 +726,11 @@ public class DisplayModeDirector {
|
||||
return mUdfpsObserver;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
HbmObserver getHbmObserver() {
|
||||
return mHbmObserver;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
|
||||
float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) {
|
||||
@@ -792,6 +800,19 @@ public class DisplayModeDirector {
|
||||
(DesiredDisplayModeSpecsListener) msg.obj;
|
||||
desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
|
||||
break;
|
||||
|
||||
case MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED: {
|
||||
int refreshRateInHbmSunlight = msg.arg1;
|
||||
mHbmObserver.onDeviceConfigRefreshRateInHbmSunlightChanged(
|
||||
refreshRateInHbmSunlight);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED: {
|
||||
int refreshRateInHbmHdr = msg.arg1;
|
||||
mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -918,16 +939,19 @@ public class DisplayModeDirector {
|
||||
// result is a range.
|
||||
public static final int PRIORITY_FLICKER_REFRESH_RATE = 1;
|
||||
|
||||
// High-brightness-mode may need a specific range of refresh-rates to function properly.
|
||||
public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2;
|
||||
|
||||
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
|
||||
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
|
||||
public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 2;
|
||||
public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 3;
|
||||
|
||||
// APP_REQUEST_REFRESH_RATE_RANGE is used to for internal apps to limit the refresh
|
||||
// rate in certain cases, mostly to preserve power.
|
||||
// @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
|
||||
// @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
|
||||
// It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
|
||||
public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 3;
|
||||
public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 4;
|
||||
|
||||
// We split the app request into different priorities in case we can satisfy one desire
|
||||
// without the other.
|
||||
@@ -942,27 +966,24 @@ public class DisplayModeDirector {
|
||||
// The preferred refresh rate is set on the main surface of the app outside of
|
||||
// DisplayModeDirector.
|
||||
// @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
|
||||
public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 4;
|
||||
public static final int PRIORITY_APP_REQUEST_SIZE = 5;
|
||||
public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 5;
|
||||
public static final int PRIORITY_APP_REQUEST_SIZE = 6;
|
||||
|
||||
// SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
|
||||
// of low priority voters. It votes [0, max(PEAK, MIN)]
|
||||
public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 6;
|
||||
public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 7;
|
||||
|
||||
// LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
|
||||
public static final int PRIORITY_LOW_POWER_MODE = 7;
|
||||
public static final int PRIORITY_LOW_POWER_MODE = 8;
|
||||
|
||||
// PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
|
||||
// higher priority voters' result is a range, it will fix the rate to a single choice.
|
||||
// It's used to avoid refresh rate switches in certain conditions which may result in the
|
||||
// user seeing the display flickering when the switches occur.
|
||||
public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8;
|
||||
public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9;
|
||||
|
||||
// Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
|
||||
public static final int PRIORITY_SKIN_TEMPERATURE = 9;
|
||||
|
||||
// High-brightness-mode may need a specific range of refresh-rates to function properly.
|
||||
public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 10;
|
||||
public static final int PRIORITY_SKIN_TEMPERATURE = 10;
|
||||
|
||||
// The proximity sensor needs the refresh rate to be locked in order to function, so this is
|
||||
// set to a high priority.
|
||||
@@ -2258,33 +2279,78 @@ public class DisplayModeDirector {
|
||||
* HBM that are associated with that display. Restrictions are retrieved from
|
||||
* DisplayManagerInternal but originate in the display-device-config file.
|
||||
*/
|
||||
private static class HbmObserver implements DisplayManager.DisplayListener {
|
||||
public static class HbmObserver implements DisplayManager.DisplayListener {
|
||||
private final BallotBox mBallotBox;
|
||||
private final Handler mHandler;
|
||||
private final SparseBooleanArray mHbmEnabled = new SparseBooleanArray();
|
||||
private final SparseIntArray mHbmMode = new SparseIntArray();
|
||||
private final Injector mInjector;
|
||||
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
||||
private int mRefreshRateInHbmSunlight;
|
||||
private int mRefreshRateInHbmHdr;
|
||||
|
||||
private DisplayManagerInternal mDisplayManagerInternal;
|
||||
|
||||
HbmObserver(Injector injector, BallotBox ballotBox, Handler handler) {
|
||||
HbmObserver(Injector injector, BallotBox ballotBox, Handler handler,
|
||||
DeviceConfigDisplaySettings displaySettings) {
|
||||
mInjector = injector;
|
||||
mBallotBox = ballotBox;
|
||||
mHandler = handler;
|
||||
mDeviceConfigDisplaySettings = displaySettings;
|
||||
}
|
||||
|
||||
public void observe() {
|
||||
mRefreshRateInHbmSunlight = mDeviceConfigDisplaySettings.getRefreshRateInHbmSunlight();
|
||||
mRefreshRateInHbmHdr = mDeviceConfigDisplaySettings.getRefreshRateInHbmHdr();
|
||||
|
||||
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
|
||||
mInjector.registerDisplayListener(this, mHandler,
|
||||
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
|
||||
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the refresh to lock to when the device is in high brightness mode for Sunlight.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
int getRefreshRateInHbmSunlight() {
|
||||
return mRefreshRateInHbmSunlight;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the refresh to lock to when the device is in high brightness mode for HDR.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
int getRefreshRateInHbmHdr() {
|
||||
return mRefreshRateInHbmHdr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the HBM vote when the device config has been changed.
|
||||
*/
|
||||
public void onDeviceConfigRefreshRateInHbmSunlightChanged(int refreshRate) {
|
||||
if (refreshRate != mRefreshRateInHbmSunlight) {
|
||||
mRefreshRateInHbmSunlight = refreshRate;
|
||||
onDeviceConfigRefreshRateInHbmChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculates the HBM vote when the device config has been changed.
|
||||
*/
|
||||
public void onDeviceConfigRefreshRateInHbmHdrChanged(int refreshRate) {
|
||||
if (refreshRate != mRefreshRateInHbmHdr) {
|
||||
mRefreshRateInHbmHdr = refreshRate;
|
||||
onDeviceConfigRefreshRateInHbmChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisplayAdded(int displayId) {}
|
||||
|
||||
@Override
|
||||
public void onDisplayRemoved(int displayId) {
|
||||
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
|
||||
mHbmMode.delete(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2294,31 +2360,56 @@ public class DisplayModeDirector {
|
||||
// Display no longer there. Assume we'll get an onDisplayRemoved very soon.
|
||||
return;
|
||||
}
|
||||
final boolean isHbmEnabled =
|
||||
info.highBrightnessMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
||||
if (isHbmEnabled == mHbmEnabled.get(displayId)) {
|
||||
final int hbmMode = info.highBrightnessMode;
|
||||
if (hbmMode == mHbmMode.get(displayId)) {
|
||||
// no change, ignore.
|
||||
return;
|
||||
}
|
||||
mHbmMode.put(displayId, hbmMode);
|
||||
recalculateVotesForDisplay(displayId);
|
||||
}
|
||||
|
||||
private void onDeviceConfigRefreshRateInHbmChanged() {
|
||||
final int[] displayIds = mHbmMode.copyKeys();
|
||||
if (displayIds != null) {
|
||||
for (int id : displayIds) {
|
||||
recalculateVotesForDisplay(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recalculateVotesForDisplay(int displayId) {
|
||||
final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
|
||||
Vote vote = null;
|
||||
mHbmEnabled.put(displayId, isHbmEnabled);
|
||||
if (isHbmEnabled) {
|
||||
final List<RefreshRateLimitation> limits =
|
||||
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
|
||||
// Device resource properties take priority over DisplayDeviceConfig
|
||||
if (mRefreshRateInHbmSunlight > 0) {
|
||||
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
|
||||
mRefreshRateInHbmSunlight);
|
||||
} else {
|
||||
final List<RefreshRateLimitation> limits =
|
||||
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
|
||||
for (int i = 0; limits != null && i < limits.size(); i++) {
|
||||
final RefreshRateLimitation limitation = limits.get(i);
|
||||
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
|
||||
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
|
||||
break;
|
||||
for (int i = 0; limits != null && i < limits.size(); i++) {
|
||||
final RefreshRateLimitation limitation = limits.get(i);
|
||||
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
|
||||
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
|
||||
&& mRefreshRateInHbmHdr > 0) {
|
||||
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
|
||||
}
|
||||
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
|
||||
}
|
||||
|
||||
void dumpLocked(PrintWriter pw) {
|
||||
pw.println(" HbmObserver");
|
||||
pw.println(" mHbmEnabled: " + mHbmEnabled);
|
||||
pw.println(" mHbmMode: " + mHbmMode);
|
||||
pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight);
|
||||
pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2437,6 +2528,29 @@ public class DisplayModeDirector {
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
public int getRefreshRateInHbmSunlight() {
|
||||
final int defaultRefreshRateInHbmSunlight =
|
||||
mContext.getResources().getInteger(
|
||||
R.integer.config_defaultRefreshRateInHbmSunlight);
|
||||
|
||||
final int refreshRate = mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT,
|
||||
defaultRefreshRateInHbmSunlight);
|
||||
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
public int getRefreshRateInHbmHdr() {
|
||||
final int defaultRefreshRateInHbmHdr =
|
||||
mContext.getResources().getInteger(R.integer.config_defaultRefreshRateInHbmHdr);
|
||||
|
||||
final int refreshRate = mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR,
|
||||
defaultRefreshRateInHbmHdr);
|
||||
|
||||
return refreshRate;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return null if no such property
|
||||
*/
|
||||
@@ -2476,6 +2590,15 @@ public class DisplayModeDirector {
|
||||
.sendToTarget();
|
||||
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
|
||||
.sendToTarget();
|
||||
|
||||
final int refreshRateInHbmSunlight = getRefreshRateInHbmSunlight();
|
||||
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED,
|
||||
refreshRateInHbmSunlight, 0)
|
||||
.sendToTarget();
|
||||
|
||||
final int refreshRateInHbmHdr = getRefreshRateInHbmHdr();
|
||||
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED, refreshRateInHbmHdr, 0)
|
||||
.sendToTarget();
|
||||
}
|
||||
|
||||
private int[] getIntArrayProperty(String prop) {
|
||||
|
||||
@@ -20,6 +20,8 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REF
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
|
||||
|
||||
@@ -1408,6 +1410,12 @@ public class DisplayModeDirectorTest {
|
||||
public void testHbmVoting_forHdr() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
|
||||
final int hbmRefreshRate = 72;
|
||||
|
||||
// Specify limitation before starting DisplayModeDirector to avoid waiting on property
|
||||
// propagation
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmHdr(hbmRefreshRate);
|
||||
|
||||
director.start(createMockSensorManager());
|
||||
|
||||
ArgumentCaptor<DisplayListener> captor =
|
||||
@@ -1432,7 +1440,7 @@ public class DisplayModeDirectorTest {
|
||||
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, 60.f);
|
||||
assertVoteForRefreshRate(vote, hbmRefreshRate);
|
||||
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
@@ -1442,6 +1450,44 @@ public class DisplayModeDirectorTest {
|
||||
assertNull(vote);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmObserverGetsUpdatedRefreshRateInHbmSunlight() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||
|
||||
final int initialRefreshRate = 60;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(initialRefreshRate);
|
||||
director.start(createMockSensorManager());
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight())
|
||||
.isEqualTo(initialRefreshRate);
|
||||
|
||||
final int updatedRefreshRate = 90;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(updatedRefreshRate);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight())
|
||||
.isEqualTo(updatedRefreshRate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmObserverGetsUpdatedRefreshRateInHbmHdr() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||
|
||||
final int initialRefreshRate = 60;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmHdr(initialRefreshRate);
|
||||
director.start(createMockSensorManager());
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmHdr())
|
||||
.isEqualTo(initialRefreshRate);
|
||||
|
||||
final int updatedRefreshRate = 90;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmHdr(updatedRefreshRate);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmHdr())
|
||||
.isEqualTo(updatedRefreshRate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmVoting_forSunlight() {
|
||||
DisplayModeDirector director =
|
||||
@@ -1455,11 +1501,12 @@ public class DisplayModeDirectorTest {
|
||||
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
|
||||
DisplayListener listener = captor.getValue();
|
||||
|
||||
final int initialRefreshRate = 60;
|
||||
// Specify Limitation
|
||||
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn(
|
||||
List.of(new RefreshRateLimitation(
|
||||
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE,
|
||||
60.f, 60.f)));
|
||||
initialRefreshRate, initialRefreshRate)));
|
||||
|
||||
// Verify that there is no HBM vote initially
|
||||
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
@@ -1470,7 +1517,39 @@ public class DisplayModeDirectorTest {
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, 60.f);
|
||||
assertVoteForRefreshRate(vote, initialRefreshRate);
|
||||
|
||||
// Change refresh rate vote value through DeviceConfig, ensure it takes precedence
|
||||
final int updatedRefreshRate = 90;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(updatedRefreshRate);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight())
|
||||
.isEqualTo(updatedRefreshRate);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, updatedRefreshRate);
|
||||
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
|
||||
// Turn HBM on again and ensure the updated vote value stuck
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, updatedRefreshRate);
|
||||
|
||||
// Reset DeviceConfig refresh rate, ensure vote falls back to the initial value
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(0);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()).isEqualTo(0);
|
||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertVoteForRefreshRate(vote, initialRefreshRate);
|
||||
|
||||
// Turn off HBM
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||
@@ -1518,6 +1597,63 @@ public class DisplayModeDirectorTest {
|
||||
assertNull(vote);
|
||||
}
|
||||
|
||||
private void setHbmAndAssertRefreshRate(
|
||||
DisplayModeDirector director, DisplayListener listener, int mode, float rr) {
|
||||
when(mInjector.getBrightnessInfo(DISPLAY_ID))
|
||||
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode));
|
||||
listener.onDisplayChanged(DISPLAY_ID);
|
||||
|
||||
final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
if (Float.isNaN(rr)) {
|
||||
assertNull(vote);
|
||||
} else {
|
||||
assertVoteForRefreshRate(vote, rr);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmVoting_forSunlightAndHdr() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
|
||||
|
||||
// Specify HDR limitation before starting DisplayModeDirector to avoid waiting on property
|
||||
// propagation
|
||||
final int hdrRr = 60;
|
||||
mInjector.getDeviceConfig().setRefreshRateInHbmHdr(hdrRr);
|
||||
director.start(createMockSensorManager());
|
||||
|
||||
ArgumentCaptor<DisplayListener> captor = ArgumentCaptor.forClass(DisplayListener.class);
|
||||
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
|
||||
eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
|
||||
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
|
||||
DisplayListener listener = captor.getValue();
|
||||
|
||||
// Specify Sunlight limitations
|
||||
final float sunlightRr = 90.0f;
|
||||
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID))
|
||||
.thenReturn(List.of(new RefreshRateLimitation(
|
||||
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE, sunlightRr,
|
||||
sunlightRr)));
|
||||
|
||||
// Verify that there is no HBM vote initially
|
||||
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||
assertNull(vote);
|
||||
|
||||
// Verify all state transitions
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, sunlightRr);
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, hdrRr);
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, Float.NaN);
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, hdrRr);
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT, sunlightRr);
|
||||
setHbmAndAssertRefreshRate(
|
||||
director, listener, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, Float.NaN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHbmVoting_RemovedDisplay() {
|
||||
DisplayModeDirector director =
|
||||
@@ -1622,6 +1758,16 @@ public class DisplayModeDirectorTest {
|
||||
String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setRefreshRateInHbmSunlight(int fps) {
|
||||
putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_REFRESH_RATE_IN_HBM_SUNLIGHT, String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setRefreshRateInHbmHdr(int fps) {
|
||||
putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||
String thresholds = toPropertyValue(brightnessThresholds);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user