Merge changes from topic "b196691596" into sc-dev
* changes: Separate refresh rate restrictions for different High Brightness Modes Limit refresh rates if skin temperature is high
This commit is contained in:
committed by
Android (Google) Code Review
commit
7b3e40dd63
@@ -1257,6 +1257,23 @@ public final class DisplayManager {
|
|||||||
*/
|
*/
|
||||||
String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||||
"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
|
* Key for default peak refresh rate
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -4492,6 +4492,13 @@
|
|||||||
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||||
<integer name="config_fixedRefreshRateInHighZone">0</integer>
|
<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
|
<!-- 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. -->
|
auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
|
||||||
<string name="config_displayLightSensorType" translatable="false" />
|
<string name="config_displayLightSensorType" translatable="false" />
|
||||||
|
|||||||
@@ -3948,6 +3948,8 @@
|
|||||||
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
|
<java-symbol type="integer" name="config_defaultRefreshRateInZone" />
|
||||||
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
||||||
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
|
<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-->
|
<!-- For fixed refresh rate displays in high brightness-->
|
||||||
<java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
|
<java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
|
||||||
|
|||||||
@@ -36,9 +36,14 @@ import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
|
|||||||
import android.hardware.fingerprint.IUdfpsHbmListener;
|
import android.hardware.fingerprint.IUdfpsHbmListener;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IThermalEventListener;
|
||||||
|
import android.os.IThermalService;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.os.Temperature;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
@@ -48,6 +53,7 @@ import android.util.Pair;
|
|||||||
import android.util.Slog;
|
import android.util.Slog;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.util.SparseBooleanArray;
|
import android.util.SparseBooleanArray;
|
||||||
|
import android.util.SparseIntArray;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
import android.view.DisplayInfo;
|
import android.view.DisplayInfo;
|
||||||
|
|
||||||
@@ -72,7 +78,6 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The DisplayModeDirector is responsible for determining what modes are allowed to be automatically
|
* 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.
|
* picked by the system based on system-wide and display-specific configuration.
|
||||||
@@ -87,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_LOW_ZONE_CHANGED = 4;
|
||||||
private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
|
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_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
|
// Special ID used to indicate that given vote is to be applied globally, rather than to a
|
||||||
// specific display.
|
// specific display.
|
||||||
@@ -108,6 +115,7 @@ public class DisplayModeDirector {
|
|||||||
private final UdfpsObserver mUdfpsObserver;
|
private final UdfpsObserver mUdfpsObserver;
|
||||||
private final SensorObserver mSensorObserver;
|
private final SensorObserver mSensorObserver;
|
||||||
private final HbmObserver mHbmObserver;
|
private final HbmObserver mHbmObserver;
|
||||||
|
private final SkinThermalStatusObserver mSkinThermalStatusObserver;
|
||||||
private final DeviceConfigInterface mDeviceConfig;
|
private final DeviceConfigInterface mDeviceConfig;
|
||||||
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
||||||
|
|
||||||
@@ -155,8 +163,10 @@ public class DisplayModeDirector {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
mSensorObserver = new SensorObserver(context, ballotBox, injector);
|
mSensorObserver = new SensorObserver(context, ballotBox, injector);
|
||||||
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
|
mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
|
||||||
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
||||||
|
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
|
||||||
|
mDeviceConfigDisplaySettings);
|
||||||
mDeviceConfig = injector.getDeviceConfig();
|
mDeviceConfig = injector.getDeviceConfig();
|
||||||
mAlwaysRespectAppRequest = false;
|
mAlwaysRespectAppRequest = false;
|
||||||
}
|
}
|
||||||
@@ -174,6 +184,7 @@ public class DisplayModeDirector {
|
|||||||
mBrightnessObserver.observe(sensorManager);
|
mBrightnessObserver.observe(sensorManager);
|
||||||
mSensorObserver.observe();
|
mSensorObserver.observe();
|
||||||
mHbmObserver.observe();
|
mHbmObserver.observe();
|
||||||
|
mSkinThermalStatusObserver.observe();
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
// We may have a listener already registered before the call to start, so go ahead and
|
// We may have a listener already registered before the call to start, so go ahead and
|
||||||
// notify them to pick up our newly initialized state.
|
// notify them to pick up our newly initialized state.
|
||||||
@@ -606,6 +617,7 @@ public class DisplayModeDirector {
|
|||||||
mUdfpsObserver.dumpLocked(pw);
|
mUdfpsObserver.dumpLocked(pw);
|
||||||
mSensorObserver.dumpLocked(pw);
|
mSensorObserver.dumpLocked(pw);
|
||||||
mHbmObserver.dumpLocked(pw);
|
mHbmObserver.dumpLocked(pw);
|
||||||
|
mSkinThermalStatusObserver.dumpLocked(pw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,6 +726,10 @@ public class DisplayModeDirector {
|
|||||||
return mUdfpsObserver;
|
return mUdfpsObserver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
HbmObserver getHbmObserver() {
|
||||||
|
return mHbmObserver;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
|
DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
|
||||||
@@ -784,6 +800,19 @@ public class DisplayModeDirector {
|
|||||||
(DesiredDisplayModeSpecsListener) msg.obj;
|
(DesiredDisplayModeSpecsListener) msg.obj;
|
||||||
desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
|
desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
|
||||||
break;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -910,16 +939,19 @@ public class DisplayModeDirector {
|
|||||||
// result is a range.
|
// result is a range.
|
||||||
public static final int PRIORITY_FLICKER_REFRESH_RATE = 1;
|
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.
|
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
|
||||||
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
|
// 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
|
// APP_REQUEST_REFRESH_RATE_RANGE is used to for internal apps to limit the refresh
|
||||||
// rate in certain cases, mostly to preserve power.
|
// rate in certain cases, mostly to preserve power.
|
||||||
// @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
|
// @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
|
||||||
// @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
|
// @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
|
||||||
// It votes to [preferredMinRefreshRate, 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
|
// We split the app request into different priorities in case we can satisfy one desire
|
||||||
// without the other.
|
// without the other.
|
||||||
@@ -934,32 +966,32 @@ public class DisplayModeDirector {
|
|||||||
// The preferred refresh rate is set on the main surface of the app outside of
|
// The preferred refresh rate is set on the main surface of the app outside of
|
||||||
// DisplayModeDirector.
|
// DisplayModeDirector.
|
||||||
// @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
|
// @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_BASE_MODE_REFRESH_RATE = 5;
|
||||||
public static final int PRIORITY_APP_REQUEST_SIZE = 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
|
// 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)]
|
// 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.
|
// 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
|
// 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.
|
// 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
|
// 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.
|
// 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;
|
||||||
|
|
||||||
// High-brightness-mode may need a specific range of refresh-rates to function properly.
|
// Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
|
||||||
public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 9;
|
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
|
// The proximity sensor needs the refresh rate to be locked in order to function, so this is
|
||||||
// set to a high priority.
|
// set to a high priority.
|
||||||
public static final int PRIORITY_PROXIMITY = 10;
|
public static final int PRIORITY_PROXIMITY = 11;
|
||||||
|
|
||||||
// The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
|
// The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
|
||||||
// to function, so this needs to be the highest priority of all votes.
|
// to function, so this needs to be the highest priority of all votes.
|
||||||
public static final int PRIORITY_UDFPS = 11;
|
public static final int PRIORITY_UDFPS = 12;
|
||||||
|
|
||||||
// Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
|
// Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
|
||||||
// APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
|
// APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
|
||||||
@@ -1054,6 +1086,8 @@ public class DisplayModeDirector {
|
|||||||
return "PRIORITY_PROXIMITY";
|
return "PRIORITY_PROXIMITY";
|
||||||
case PRIORITY_LOW_POWER_MODE:
|
case PRIORITY_LOW_POWER_MODE:
|
||||||
return "PRIORITY_LOW_POWER_MODE";
|
return "PRIORITY_LOW_POWER_MODE";
|
||||||
|
case PRIORITY_SKIN_TEMPERATURE:
|
||||||
|
return "PRIORITY_SKIN_TEMPERATURE";
|
||||||
case PRIORITY_UDFPS:
|
case PRIORITY_UDFPS:
|
||||||
return "PRIORITY_UDFPS";
|
return "PRIORITY_UDFPS";
|
||||||
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
|
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
|
||||||
@@ -2245,33 +2279,78 @@ public class DisplayModeDirector {
|
|||||||
* HBM that are associated with that display. Restrictions are retrieved from
|
* HBM that are associated with that display. Restrictions are retrieved from
|
||||||
* DisplayManagerInternal but originate in the display-device-config file.
|
* 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 BallotBox mBallotBox;
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final SparseBooleanArray mHbmEnabled = new SparseBooleanArray();
|
private final SparseIntArray mHbmMode = new SparseIntArray();
|
||||||
private final Injector mInjector;
|
private final Injector mInjector;
|
||||||
|
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
||||||
|
private int mRefreshRateInHbmSunlight;
|
||||||
|
private int mRefreshRateInHbmHdr;
|
||||||
|
|
||||||
private DisplayManagerInternal mDisplayManagerInternal;
|
private DisplayManagerInternal mDisplayManagerInternal;
|
||||||
|
|
||||||
HbmObserver(Injector injector, BallotBox ballotBox, Handler handler) {
|
HbmObserver(Injector injector, BallotBox ballotBox, Handler handler,
|
||||||
|
DeviceConfigDisplaySettings displaySettings) {
|
||||||
mInjector = injector;
|
mInjector = injector;
|
||||||
mBallotBox = ballotBox;
|
mBallotBox = ballotBox;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
|
mDeviceConfigDisplaySettings = displaySettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void observe() {
|
public void observe() {
|
||||||
|
mRefreshRateInHbmSunlight = mDeviceConfigDisplaySettings.getRefreshRateInHbmSunlight();
|
||||||
|
mRefreshRateInHbmHdr = mDeviceConfigDisplaySettings.getRefreshRateInHbmHdr();
|
||||||
|
|
||||||
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
|
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
|
||||||
mInjector.registerDisplayListener(this, mHandler,
|
mInjector.registerDisplayListener(this, mHandler,
|
||||||
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
|
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
|
||||||
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
|
| 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
|
@Override
|
||||||
public void onDisplayAdded(int displayId) {}
|
public void onDisplayAdded(int displayId) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisplayRemoved(int displayId) {
|
public void onDisplayRemoved(int displayId) {
|
||||||
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
|
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
|
||||||
|
mHbmMode.delete(displayId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -2281,31 +2360,102 @@ public class DisplayModeDirector {
|
|||||||
// Display no longer there. Assume we'll get an onDisplayRemoved very soon.
|
// Display no longer there. Assume we'll get an onDisplayRemoved very soon.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final boolean isHbmEnabled =
|
final int hbmMode = info.highBrightnessMode;
|
||||||
info.highBrightnessMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
|
if (hbmMode == mHbmMode.get(displayId)) {
|
||||||
if (isHbmEnabled == mHbmEnabled.get(displayId)) {
|
|
||||||
// no change, ignore.
|
// no change, ignore.
|
||||||
return;
|
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;
|
Vote vote = null;
|
||||||
mHbmEnabled.put(displayId, isHbmEnabled);
|
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
|
||||||
if (isHbmEnabled) {
|
// Device resource properties take priority over DisplayDeviceConfig
|
||||||
final List<RefreshRateLimitation> limits =
|
if (mRefreshRateInHbmSunlight > 0) {
|
||||||
|
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
|
||||||
|
mRefreshRateInHbmSunlight);
|
||||||
|
} else {
|
||||||
|
final List<RefreshRateLimitation> limits =
|
||||||
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
|
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
|
||||||
for (int i = 0; limits != null && i < limits.size(); i++) {
|
for (int i = 0; limits != null && i < limits.size(); i++) {
|
||||||
final RefreshRateLimitation limitation = limits.get(i);
|
final RefreshRateLimitation limitation = limits.get(i);
|
||||||
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
|
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
|
||||||
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
|
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
|
||||||
|
&& mRefreshRateInHbmHdr > 0) {
|
||||||
|
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
|
||||||
|
}
|
||||||
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
|
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dumpLocked(PrintWriter pw) {
|
void dumpLocked(PrintWriter pw) {
|
||||||
pw.println(" HbmObserver");
|
pw.println(" HbmObserver");
|
||||||
pw.println(" mHbmEnabled: " + mHbmEnabled);
|
pw.println(" mHbmMode: " + mHbmMode);
|
||||||
|
pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight);
|
||||||
|
pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
|
||||||
|
private final BallotBox mBallotBox;
|
||||||
|
private final Injector mInjector;
|
||||||
|
|
||||||
|
private @Temperature.ThrottlingStatus int mStatus = -1;
|
||||||
|
|
||||||
|
SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
|
||||||
|
mInjector = injector;
|
||||||
|
mBallotBox = ballotBox;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void notifyThrottling(Temperature temp) {
|
||||||
|
mStatus = temp.getStatus();
|
||||||
|
if (mLoggingEnabled) {
|
||||||
|
Slog.d(TAG, "New thermal throttling status "
|
||||||
|
+ ", current thermal status = " + mStatus);
|
||||||
|
}
|
||||||
|
final Vote vote;
|
||||||
|
if (mStatus >= Temperature.THROTTLING_CRITICAL) {
|
||||||
|
vote = Vote.forRefreshRates(0f, 60f);
|
||||||
|
} else {
|
||||||
|
vote = null;
|
||||||
|
}
|
||||||
|
mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void observe() {
|
||||||
|
IThermalService thermalService = mInjector.getThermalService();
|
||||||
|
if (thermalService == null) {
|
||||||
|
Slog.w(TAG, "Could not observe thermal status. Service not available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Slog.e(TAG, "Failed to register thermal status listener", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dumpLocked(PrintWriter writer) {
|
||||||
|
writer.println(" SkinThermalStatusObserver:");
|
||||||
|
writer.println(" mStatus: " + mStatus);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2378,6 +2528,29 @@ public class DisplayModeDirector {
|
|||||||
return refreshRate;
|
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
|
* Return null if no such property
|
||||||
*/
|
*/
|
||||||
@@ -2417,6 +2590,15 @@ public class DisplayModeDirector {
|
|||||||
.sendToTarget();
|
.sendToTarget();
|
||||||
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
|
mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
|
||||||
.sendToTarget();
|
.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) {
|
private int[] getIntArrayProperty(String prop) {
|
||||||
@@ -2470,6 +2652,8 @@ public class DisplayModeDirector {
|
|||||||
BrightnessInfo getBrightnessInfo(int displayId);
|
BrightnessInfo getBrightnessInfo(int displayId);
|
||||||
|
|
||||||
boolean isDozeState(Display d);
|
boolean isDozeState(Display d);
|
||||||
|
|
||||||
|
IThermalService getThermalService();
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -2530,6 +2714,12 @@ public class DisplayModeDirector {
|
|||||||
return Display.isDozeState(d.getState());
|
return Display.isDozeState(d.getState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IThermalService getThermalService() {
|
||||||
|
return IThermalService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.THERMAL_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
private DisplayManager getDisplayManager() {
|
private DisplayManager getDisplayManager() {
|
||||||
if (mDisplayManager == null) {
|
if (mDisplayManager == null) {
|
||||||
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
mDisplayManager = mContext.getSystemService(DisplayManager.class);
|
||||||
|
|||||||
@@ -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_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_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_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_HIGH_ZONE;
|
||||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
|
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
|
||||||
|
|
||||||
@@ -56,7 +58,11 @@ import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
|
|||||||
import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
|
import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
|
||||||
import android.hardware.fingerprint.IUdfpsHbmListener;
|
import android.hardware.fingerprint.IUdfpsHbmListener;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.IThermalEventListener;
|
||||||
|
import android.os.IThermalService;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.Temperature;
|
||||||
import android.provider.DeviceConfig;
|
import android.provider.DeviceConfig;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.test.mock.MockContentResolver;
|
import android.test.mock.MockContentResolver;
|
||||||
@@ -116,6 +122,8 @@ public class DisplayModeDirectorTest {
|
|||||||
public SensorManagerInternal mSensorManagerInternalMock;
|
public SensorManagerInternal mSensorManagerInternalMock;
|
||||||
@Mock
|
@Mock
|
||||||
public DisplayManagerInternal mDisplayManagerInternalMock;
|
public DisplayManagerInternal mDisplayManagerInternalMock;
|
||||||
|
@Mock
|
||||||
|
public IThermalService mThermalServiceMock;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -124,6 +132,7 @@ public class DisplayModeDirectorTest {
|
|||||||
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
|
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
|
||||||
when(mContext.getContentResolver()).thenReturn(resolver);
|
when(mContext.getContentResolver()).thenReturn(resolver);
|
||||||
mInjector = spy(new FakesInjector());
|
mInjector = spy(new FakesInjector());
|
||||||
|
when(mInjector.getThermalService()).thenReturn(mThermalServiceMock);
|
||||||
mHandler = new Handler(Looper.getMainLooper());
|
mHandler = new Handler(Looper.getMainLooper());
|
||||||
|
|
||||||
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
|
LocalServices.removeServiceForTest(StatusBarManagerInternal.class);
|
||||||
@@ -1401,6 +1410,12 @@ public class DisplayModeDirectorTest {
|
|||||||
public void testHbmVoting_forHdr() {
|
public void testHbmVoting_forHdr() {
|
||||||
DisplayModeDirector director =
|
DisplayModeDirector director =
|
||||||
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
|
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());
|
director.start(createMockSensorManager());
|
||||||
|
|
||||||
ArgumentCaptor<DisplayListener> captor =
|
ArgumentCaptor<DisplayListener> captor =
|
||||||
@@ -1425,7 +1440,7 @@ public class DisplayModeDirectorTest {
|
|||||||
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR));
|
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR));
|
||||||
listener.onDisplayChanged(DISPLAY_ID);
|
listener.onDisplayChanged(DISPLAY_ID);
|
||||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||||
assertVoteForRefreshRate(vote, 60.f);
|
assertVoteForRefreshRate(vote, hbmRefreshRate);
|
||||||
|
|
||||||
// Turn off HBM
|
// Turn off HBM
|
||||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||||
@@ -1435,6 +1450,44 @@ public class DisplayModeDirectorTest {
|
|||||||
assertNull(vote);
|
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
|
@Test
|
||||||
public void testHbmVoting_forSunlight() {
|
public void testHbmVoting_forSunlight() {
|
||||||
DisplayModeDirector director =
|
DisplayModeDirector director =
|
||||||
@@ -1448,11 +1501,12 @@ public class DisplayModeDirectorTest {
|
|||||||
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
|
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
|
||||||
DisplayListener listener = captor.getValue();
|
DisplayListener listener = captor.getValue();
|
||||||
|
|
||||||
|
final int initialRefreshRate = 60;
|
||||||
// Specify Limitation
|
// Specify Limitation
|
||||||
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn(
|
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn(
|
||||||
List.of(new RefreshRateLimitation(
|
List.of(new RefreshRateLimitation(
|
||||||
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE,
|
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE,
|
||||||
60.f, 60.f)));
|
initialRefreshRate, initialRefreshRate)));
|
||||||
|
|
||||||
// Verify that there is no HBM vote initially
|
// Verify that there is no HBM vote initially
|
||||||
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
||||||
@@ -1463,7 +1517,39 @@ public class DisplayModeDirectorTest {
|
|||||||
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
|
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
|
||||||
listener.onDisplayChanged(DISPLAY_ID);
|
listener.onDisplayChanged(DISPLAY_ID);
|
||||||
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
|
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
|
// Turn off HBM
|
||||||
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
|
||||||
@@ -1511,6 +1597,63 @@ public class DisplayModeDirectorTest {
|
|||||||
assertNull(vote);
|
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
|
@Test
|
||||||
public void testHbmVoting_RemovedDisplay() {
|
public void testHbmVoting_RemovedDisplay() {
|
||||||
DisplayModeDirector director =
|
DisplayModeDirector director =
|
||||||
@@ -1547,12 +1690,52 @@ public class DisplayModeDirectorTest {
|
|||||||
assertNull(vote);
|
assertNull(vote);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSkinTemperature() throws RemoteException {
|
||||||
|
DisplayModeDirector director =
|
||||||
|
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
|
||||||
|
director.start(createMockSensorManager());
|
||||||
|
|
||||||
|
ArgumentCaptor<IThermalEventListener> thermalEventListener =
|
||||||
|
ArgumentCaptor.forClass(IThermalEventListener.class);
|
||||||
|
|
||||||
|
verify(mThermalServiceMock).registerThermalEventListenerWithType(
|
||||||
|
thermalEventListener.capture(), eq(Temperature.TYPE_SKIN));
|
||||||
|
final IThermalEventListener listener = thermalEventListener.getValue();
|
||||||
|
|
||||||
|
// Verify that there is no skin temperature vote initially.
|
||||||
|
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
|
||||||
|
assertNull(vote);
|
||||||
|
|
||||||
|
// Set the skin temperature to critical and verify that we added a vote.
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
|
||||||
|
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
|
||||||
|
assertVoteForRefreshRateRange(vote, 0f, 60.f);
|
||||||
|
|
||||||
|
// Set the skin temperature to severe and verify that the vote is gone.
|
||||||
|
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
|
||||||
|
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
|
||||||
|
assertNull(vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
|
||||||
|
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
|
||||||
|
}
|
||||||
|
|
||||||
private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
|
private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
|
||||||
assertThat(vote).isNotNull();
|
assertThat(vote).isNotNull();
|
||||||
final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate);
|
final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate);
|
||||||
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
|
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertVoteForRefreshRateRange(
|
||||||
|
Vote vote, float refreshRateLow, float refreshRateHigh) {
|
||||||
|
assertThat(vote).isNotNull();
|
||||||
|
final RefreshRateRange expectedRange =
|
||||||
|
new RefreshRateRange(refreshRateLow, refreshRateHigh);
|
||||||
|
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
|
||||||
|
}
|
||||||
|
|
||||||
public static class FakeDeviceConfig extends FakeDeviceConfigInterface {
|
public static class FakeDeviceConfig extends FakeDeviceConfigInterface {
|
||||||
@Override
|
@Override
|
||||||
public String getProperty(String namespace, String name) {
|
public String getProperty(String namespace, String name) {
|
||||||
@@ -1575,6 +1758,16 @@ public class DisplayModeDirectorTest {
|
|||||||
String.valueOf(fps));
|
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) {
|
void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||||
String thresholds = toPropertyValue(brightnessThresholds);
|
String thresholds = toPropertyValue(brightnessThresholds);
|
||||||
|
|
||||||
@@ -1748,6 +1941,11 @@ public class DisplayModeDirectorTest {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IThermalService getThermalService() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
void notifyPeakRefreshRateChanged() {
|
void notifyPeakRefreshRateChanged() {
|
||||||
if (mPeakRefreshRateObserver != null) {
|
if (mPeakRefreshRateObserver != null) {
|
||||||
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
|
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
|
||||||
|
|||||||
Reference in New Issue
Block a user