Merge "Fixed latency spike" into tm-qpr-dev

This commit is contained in:
Rupesh Bansal
2022-11-18 12:34:10 +00:00
committed by Android (Google) Code Review
2 changed files with 161 additions and 34 deletions

View File

@@ -523,8 +523,10 @@ public class DisplayModeDirector {
* changed * changed
*/ */
public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) { public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) {
mSettingsObserver.setRefreshRates(displayDeviceConfig); mSettingsObserver.setRefreshRates(displayDeviceConfig,
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig); /* attemptLoadingFromDeviceConfig= */ true);
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig,
/* attemptLoadingFromDeviceConfig= */ true);
} }
/** /**
@@ -1142,19 +1144,25 @@ public class DisplayModeDirector {
SettingsObserver(@NonNull Context context, @NonNull Handler handler) { SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
super(handler); super(handler);
mContext = context; mContext = context;
setRefreshRates(/* displayDeviceConfig= */ null); // We don't want to load from the DeviceConfig while constructing since this leads to
// a spike in the latency of DisplayManagerService startup. This happens because
// reading from the DeviceConfig is an intensive IO operation and having it in the
// startup phase where we thrive to keep the latency very low has significant impact.
setRefreshRates(/* displayDeviceConfig= */ null,
/* attemptLoadingFromDeviceConfig= */ false);
} }
/** /**
* This is used to update the refresh rate configs from the DeviceConfig, which * This is used to update the refresh rate configs from the DeviceConfig, which
* if missing from DisplayDeviceConfig, and finally fallback to config.xml. * if missing from DisplayDeviceConfig, and finally fallback to config.xml.
*/ */
public void setRefreshRates(DisplayDeviceConfig displayDeviceConfig) { public void setRefreshRates(DisplayDeviceConfig displayDeviceConfig,
setDefaultPeakRefreshRate(displayDeviceConfig); boolean attemptLoadingFromDeviceConfig) {
setDefaultPeakRefreshRate(displayDeviceConfig, attemptLoadingFromDeviceConfig);
mDefaultRefreshRate = mDefaultRefreshRate =
(displayDeviceConfig == null) ? (float) mContext.getResources().getInteger( (displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
R.integer.config_defaultRefreshRate) R.integer.config_defaultRefreshRate)
: (float) displayDeviceConfig.getDefaultRefreshRate(); : (float) displayDeviceConfig.getDefaultRefreshRate();
} }
public void observe() { public void observe() {
@@ -1215,13 +1223,27 @@ public class DisplayModeDirector {
} }
} }
private void setDefaultPeakRefreshRate(DisplayDeviceConfig displayDeviceConfig) { @VisibleForTesting
float getDefaultRefreshRate() {
return mDefaultRefreshRate;
}
@VisibleForTesting
float getDefaultPeakRefreshRate() {
return mDefaultPeakRefreshRate;
}
private void setDefaultPeakRefreshRate(DisplayDeviceConfig displayDeviceConfig,
boolean attemptLoadingFromDeviceConfig) {
Float defaultPeakRefreshRate = null; Float defaultPeakRefreshRate = null;
try {
defaultPeakRefreshRate = if (attemptLoadingFromDeviceConfig) {
try {
defaultPeakRefreshRate =
mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate(); mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
} catch (Exception exception) { } catch (Exception exception) {
// Do nothing // Do nothing
}
} }
if (defaultPeakRefreshRate == null) { if (defaultPeakRefreshRate == null) {
defaultPeakRefreshRate = defaultPeakRefreshRate =
@@ -1544,7 +1566,8 @@ public class DisplayModeDirector {
mContext = context; mContext = context;
mHandler = handler; mHandler = handler;
mInjector = injector; mInjector = injector;
updateBlockingZoneThresholds(/* displayDeviceConfig= */ null); updateBlockingZoneThresholds(/* displayDeviceConfig= */ null,
/* attemptLoadingFromDeviceConfig= */ false);
mRefreshRateInHighZone = context.getResources().getInteger( mRefreshRateInHighZone = context.getResources().getInteger(
R.integer.config_fixedRefreshRateInHighZone); R.integer.config_fixedRefreshRateInHighZone);
} }
@@ -1553,22 +1576,44 @@ public class DisplayModeDirector {
* This is used to update the blocking zone thresholds from the DeviceConfig, which * This is used to update the blocking zone thresholds from the DeviceConfig, which
* if missing from DisplayDeviceConfig, and finally fallback to config.xml. * if missing from DisplayDeviceConfig, and finally fallback to config.xml.
*/ */
public void updateBlockingZoneThresholds(DisplayDeviceConfig displayDeviceConfig) { public void updateBlockingZoneThresholds(DisplayDeviceConfig displayDeviceConfig,
loadLowBrightnessThresholds(displayDeviceConfig); boolean attemptLoadingFromDeviceConfig) {
loadHighBrightnessThresholds(displayDeviceConfig); loadLowBrightnessThresholds(displayDeviceConfig, attemptLoadingFromDeviceConfig);
loadHighBrightnessThresholds(displayDeviceConfig, attemptLoadingFromDeviceConfig);
} }
private void loadLowBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig) { @VisibleForTesting
int[] getLowDisplayBrightnessThreshold() {
return mLowDisplayBrightnessThresholds;
}
@VisibleForTesting
int[] getLowAmbientBrightnessThreshold() {
return mLowAmbientBrightnessThresholds;
}
@VisibleForTesting
int[] getHighDisplayBrightnessThreshold() {
return mHighDisplayBrightnessThresholds;
}
@VisibleForTesting
int[] getHighAmbientBrightnessThreshold() {
return mHighAmbientBrightnessThresholds;
}
private void loadLowBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig,
boolean attemptLoadingFromDeviceConfig) {
mLowDisplayBrightnessThresholds = loadBrightnessThresholds( mLowDisplayBrightnessThresholds = loadBrightnessThresholds(
() -> mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds(), () -> mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds(),
() -> displayDeviceConfig.getLowDisplayBrightnessThresholds(), () -> displayDeviceConfig.getLowDisplayBrightnessThresholds(),
R.array.config_brightnessThresholdsOfPeakRefreshRate, R.array.config_brightnessThresholdsOfPeakRefreshRate,
displayDeviceConfig); displayDeviceConfig, attemptLoadingFromDeviceConfig);
mLowAmbientBrightnessThresholds = loadBrightnessThresholds( mLowAmbientBrightnessThresholds = loadBrightnessThresholds(
() -> mDeviceConfigDisplaySettings.getLowAmbientBrightnessThresholds(), () -> mDeviceConfigDisplaySettings.getLowAmbientBrightnessThresholds(),
() -> displayDeviceConfig.getLowAmbientBrightnessThresholds(), () -> displayDeviceConfig.getLowAmbientBrightnessThresholds(),
R.array.config_ambientThresholdsOfPeakRefreshRate, R.array.config_ambientThresholdsOfPeakRefreshRate,
displayDeviceConfig); displayDeviceConfig, attemptLoadingFromDeviceConfig);
if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) { if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) {
throw new RuntimeException("display low brightness threshold array and ambient " throw new RuntimeException("display low brightness threshold array and ambient "
+ "brightness threshold array have different length: " + "brightness threshold array have different length: "
@@ -1579,17 +1624,18 @@ public class DisplayModeDirector {
} }
} }
private void loadHighBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig) { private void loadHighBrightnessThresholds(DisplayDeviceConfig displayDeviceConfig,
boolean attemptLoadingFromDeviceConfig) {
mHighDisplayBrightnessThresholds = loadBrightnessThresholds( mHighDisplayBrightnessThresholds = loadBrightnessThresholds(
() -> mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds(), () -> mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds(),
() -> displayDeviceConfig.getHighDisplayBrightnessThresholds(), () -> displayDeviceConfig.getHighDisplayBrightnessThresholds(),
R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate, R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate,
displayDeviceConfig); displayDeviceConfig, attemptLoadingFromDeviceConfig);
mHighAmbientBrightnessThresholds = loadBrightnessThresholds( mHighAmbientBrightnessThresholds = loadBrightnessThresholds(
() -> mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds(), () -> mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds(),
() -> displayDeviceConfig.getHighAmbientBrightnessThresholds(), () -> displayDeviceConfig.getHighAmbientBrightnessThresholds(),
R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate, R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate,
displayDeviceConfig); displayDeviceConfig, attemptLoadingFromDeviceConfig);
if (mHighDisplayBrightnessThresholds.length if (mHighDisplayBrightnessThresholds.length
!= mHighAmbientBrightnessThresholds.length) { != mHighAmbientBrightnessThresholds.length) {
throw new RuntimeException("display high brightness threshold array and ambient " throw new RuntimeException("display high brightness threshold array and ambient "
@@ -1605,13 +1651,16 @@ public class DisplayModeDirector {
Callable<int[]> loadFromDeviceConfigDisplaySettingsCallable, Callable<int[]> loadFromDeviceConfigDisplaySettingsCallable,
Callable<int[]> loadFromDisplayDeviceConfigCallable, Callable<int[]> loadFromDisplayDeviceConfigCallable,
int brightnessThresholdOfFixedRefreshRateKey, int brightnessThresholdOfFixedRefreshRateKey,
DisplayDeviceConfig displayDeviceConfig) { DisplayDeviceConfig displayDeviceConfig, boolean attemptLoadingFromDeviceConfig) {
int[] brightnessThresholds = null; int[] brightnessThresholds = null;
try {
brightnessThresholds = if (attemptLoadingFromDeviceConfig) {
try {
brightnessThresholds =
loadFromDeviceConfigDisplaySettingsCallable.call(); loadFromDeviceConfigDisplaySettingsCallable.call();
} catch (Exception exception) { } catch (Exception exception) {
// Do nothing // Do nothing
}
} }
if (brightnessThresholds == null) { if (brightnessThresholds == null) {
try { try {

View File

@@ -21,6 +21,7 @@ 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_PEAK_REFRESH_RATE_DEFAULT;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR; import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR;
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_SUNLIGHT;
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;
@@ -31,6 +32,8 @@ import static com.android.server.display.HighBrightnessModeController.HBM_TRANSI
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
@@ -48,6 +51,7 @@ import android.annotation.NonNull;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.ContextWrapper; import android.content.ContextWrapper;
import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.hardware.Sensor; import android.hardware.Sensor;
import android.hardware.SensorEventListener; import android.hardware.SensorEventListener;
@@ -76,6 +80,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.internal.R;
import com.android.internal.display.BrightnessSynchronizer; import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.Preconditions; import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider;
@@ -1855,16 +1860,83 @@ public class DisplayModeDirectorTest {
@Test @Test
public void testNotifyDefaultDisplayDeviceUpdated() { public void testNotifyDefaultDisplayDeviceUpdated() {
DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class); Resources resources = mock(Resources.class);
when(displayDeviceConfig.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{}); when(mContext.getResources()).thenReturn(resources);
when(displayDeviceConfig.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{}); when(resources.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate))
when(displayDeviceConfig.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{}); .thenReturn(75);
when(displayDeviceConfig.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{}); when(resources.getInteger(R.integer.config_defaultRefreshRate))
.thenReturn(45);
when(resources.getIntArray(R.array.config_brightnessThresholdsOfPeakRefreshRate))
.thenReturn(new int[]{5});
when(resources.getIntArray(R.array.config_ambientThresholdsOfPeakRefreshRate))
.thenReturn(new int[]{10});
when(
resources.getIntArray(R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate))
.thenReturn(new int[]{250});
when(
resources.getIntArray(R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate))
.thenReturn(new int[]{7000});
DisplayModeDirector director = DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0); createDirectorFromRefreshRateArray(new float[]{60.0f, 90.0f}, 0);
// We don't expect any interaction with DeviceConfig when the director is initialized
// because we explicitly avoid doing this as this can lead to a latency spike in the
// startup of DisplayManagerService
// Verify all the loaded values are from DisplayDeviceConfig
assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 45, 0.0);
assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 75,
0.0);
assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
new int[]{250});
assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
new int[]{7000});
assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThreshold(),
new int[]{5});
assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThreshold(),
new int[]{10});
// Notify that the default display is updated, such that DisplayDeviceConfig has new values
DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
when(displayDeviceConfig.getDefaultRefreshRate()).thenReturn(50);
when(displayDeviceConfig.getDefaultPeakRefreshRate()).thenReturn(55);
when(displayDeviceConfig.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25});
when(displayDeviceConfig.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30});
when(displayDeviceConfig.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210});
when(displayDeviceConfig.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{2100});
director.defaultDisplayDeviceUpdated(displayDeviceConfig); director.defaultDisplayDeviceUpdated(displayDeviceConfig);
verify(displayDeviceConfig).getDefaultRefreshRate();
verify(displayDeviceConfig).getDefaultPeakRefreshRate(); assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 50, 0.0);
assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 55,
0.0);
assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
new int[]{210});
assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
new int[]{2100});
assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThreshold(),
new int[]{25});
assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThreshold(),
new int[]{30});
// Notify that the default display is updated, such that DeviceConfig has new values
FakeDeviceConfig config = mInjector.getDeviceConfig();
config.setDefaultPeakRefreshRate(60);
config.setLowAmbientBrightnessThresholds(new int[]{20});
config.setLowDisplayBrightnessThresholds(new int[]{10});
config.setHighDisplayBrightnessThresholds(new int[]{255});
config.setHighAmbientBrightnessThresholds(new int[]{8000});
director.defaultDisplayDeviceUpdated(displayDeviceConfig);
assertEquals(director.getSettingsObserver().getDefaultRefreshRate(), 50, 0.0);
assertEquals(director.getSettingsObserver().getDefaultPeakRefreshRate(), 60,
0.0);
assertArrayEquals(director.getBrightnessObserver().getHighDisplayBrightnessThreshold(),
new int[]{255});
assertArrayEquals(director.getBrightnessObserver().getHighAmbientBrightnessThreshold(),
new int[]{8000});
assertArrayEquals(director.getBrightnessObserver().getLowDisplayBrightnessThreshold(),
new int[]{10});
assertArrayEquals(director.getBrightnessObserver().getLowAmbientBrightnessThreshold(),
new int[]{20});
} }
private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) { private Temperature getSkinTemp(@Temperature.ThrottlingStatus int status) {
@@ -1954,6 +2026,12 @@ public class DisplayModeDirectorTest {
String.valueOf(fps)); String.valueOf(fps));
} }
void setDefaultPeakRefreshRate(int fps) {
putPropertyAndNotify(
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_PEAK_REFRESH_RATE_DEFAULT,
String.valueOf(fps));
}
void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) { void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
String thresholds = toPropertyValue(brightnessThresholds); String thresholds = toPropertyValue(brightnessThresholds);