Loading core/java/android/hardware/display/DisplayManager.java +17 −0 Original line number Diff line number Diff line Loading @@ -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 * Loading core/res/res/values/config.xml +7 −0 Original line number Diff line number Diff line Loading @@ -4506,6 +4506,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" /> Loading core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -3954,6 +3954,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" /> Loading services/core/java/com/android/server/display/DisplayModeDirector.java +151 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -723,6 +726,11 @@ public class DisplayModeDirector { return mUdfpsObserver; } @VisibleForTesting HbmObserver getHbmObserver() { return mHbmObserver; } @VisibleForTesting DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings( float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) { Loading Loading @@ -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; } } } } Loading Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading @@ -2294,15 +2360,33 @@ 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) { 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++) { Loading @@ -2313,12 +2397,19 @@ public class DisplayModeDirector { } } } } 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); } } Loading Loading @@ -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 */ Loading Loading @@ -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) { Loading services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +149 −3 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/hardware/display/DisplayManager.java +17 −0 Original line number Diff line number Diff line Loading @@ -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 * Loading
core/res/res/values/config.xml +7 −0 Original line number Diff line number Diff line Loading @@ -4506,6 +4506,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" /> Loading
core/res/res/values/symbols.xml +2 −0 Original line number Diff line number Diff line Loading @@ -3954,6 +3954,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" /> Loading
services/core/java/com/android/server/display/DisplayModeDirector.java +151 −28 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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. Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -723,6 +726,11 @@ public class DisplayModeDirector { return mUdfpsObserver; } @VisibleForTesting HbmObserver getHbmObserver() { return mHbmObserver; } @VisibleForTesting DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings( float minRefreshRate, float peakRefreshRate, float defaultRefreshRate) { Loading Loading @@ -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; } } } } Loading Loading @@ -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. Loading @@ -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. Loading Loading @@ -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 Loading @@ -2294,15 +2360,33 @@ 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) { 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++) { Loading @@ -2313,12 +2397,19 @@ public class DisplayModeDirector { } } } } 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); } } Loading Loading @@ -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 */ Loading Loading @@ -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) { Loading
services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +149 −3 File changed.Preview size limit exceeded, changes collapsed. Show changes