Fixed latency spike
A spike in the startup time of DisplayManagerService was observeed because of a recent change where we are attempting read values from DeviceConfig, which if missing fallsback to DisplayDeviceConfig. This extra read attempt is unneeded because once the DisplayManagerService is setup, we explicitly make a start call to DisplayModeDirector which takes care of reloading values from DeviceConfig if present. Bug: 254354520 Test: Manual Change-Id: Iae7066b8c732d9b39e3fb76200ff24cb5aeb3d73
This commit is contained in:
@@ -523,8 +523,10 @@ public class DisplayModeDirector {
|
||||
* changed
|
||||
*/
|
||||
public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) {
|
||||
mSettingsObserver.setRefreshRates(displayDeviceConfig);
|
||||
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig);
|
||||
mSettingsObserver.setRefreshRates(displayDeviceConfig,
|
||||
/* attemptLoadingFromDeviceConfig= */ true);
|
||||
mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig,
|
||||
/* attemptLoadingFromDeviceConfig= */ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1142,19 +1144,25 @@ public class DisplayModeDirector {
|
||||
SettingsObserver(@NonNull Context context, @NonNull Handler handler) {
|
||||
super(handler);
|
||||
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
|
||||
* if missing from DisplayDeviceConfig, and finally fallback to config.xml.
|
||||
*/
|
||||
public void setRefreshRates(DisplayDeviceConfig displayDeviceConfig) {
|
||||
setDefaultPeakRefreshRate(displayDeviceConfig);
|
||||
public void setRefreshRates(DisplayDeviceConfig displayDeviceConfig,
|
||||
boolean attemptLoadingFromDeviceConfig) {
|
||||
setDefaultPeakRefreshRate(displayDeviceConfig, attemptLoadingFromDeviceConfig);
|
||||
mDefaultRefreshRate =
|
||||
(displayDeviceConfig == null) ? (float) mContext.getResources().getInteger(
|
||||
R.integer.config_defaultRefreshRate)
|
||||
: (float) displayDeviceConfig.getDefaultRefreshRate();
|
||||
R.integer.config_defaultRefreshRate)
|
||||
: (float) displayDeviceConfig.getDefaultRefreshRate();
|
||||
}
|
||||
|
||||
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;
|
||||
try {
|
||||
defaultPeakRefreshRate =
|
||||
|
||||
if (attemptLoadingFromDeviceConfig) {
|
||||
try {
|
||||
defaultPeakRefreshRate =
|
||||
mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
|
||||
} catch (Exception exception) {
|
||||
// Do nothing
|
||||
} catch (Exception exception) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
if (defaultPeakRefreshRate == null) {
|
||||
defaultPeakRefreshRate =
|
||||
@@ -1544,7 +1566,8 @@ public class DisplayModeDirector {
|
||||
mContext = context;
|
||||
mHandler = handler;
|
||||
mInjector = injector;
|
||||
updateBlockingZoneThresholds(/* displayDeviceConfig= */ null);
|
||||
updateBlockingZoneThresholds(/* displayDeviceConfig= */ null,
|
||||
/* attemptLoadingFromDeviceConfig= */ false);
|
||||
mRefreshRateInHighZone = context.getResources().getInteger(
|
||||
R.integer.config_fixedRefreshRateInHighZone);
|
||||
}
|
||||
@@ -1553,22 +1576,44 @@ public class DisplayModeDirector {
|
||||
* This is used to update the blocking zone thresholds from the DeviceConfig, which
|
||||
* if missing from DisplayDeviceConfig, and finally fallback to config.xml.
|
||||
*/
|
||||
public void updateBlockingZoneThresholds(DisplayDeviceConfig displayDeviceConfig) {
|
||||
loadLowBrightnessThresholds(displayDeviceConfig);
|
||||
loadHighBrightnessThresholds(displayDeviceConfig);
|
||||
public void updateBlockingZoneThresholds(DisplayDeviceConfig displayDeviceConfig,
|
||||
boolean attemptLoadingFromDeviceConfig) {
|
||||
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(
|
||||
() -> mDeviceConfigDisplaySettings.getLowDisplayBrightnessThresholds(),
|
||||
() -> displayDeviceConfig.getLowDisplayBrightnessThresholds(),
|
||||
R.array.config_brightnessThresholdsOfPeakRefreshRate,
|
||||
displayDeviceConfig);
|
||||
displayDeviceConfig, attemptLoadingFromDeviceConfig);
|
||||
mLowAmbientBrightnessThresholds = loadBrightnessThresholds(
|
||||
() -> mDeviceConfigDisplaySettings.getLowAmbientBrightnessThresholds(),
|
||||
() -> displayDeviceConfig.getLowAmbientBrightnessThresholds(),
|
||||
R.array.config_ambientThresholdsOfPeakRefreshRate,
|
||||
displayDeviceConfig);
|
||||
displayDeviceConfig, attemptLoadingFromDeviceConfig);
|
||||
if (mLowDisplayBrightnessThresholds.length != mLowAmbientBrightnessThresholds.length) {
|
||||
throw new RuntimeException("display low brightness threshold array and ambient "
|
||||
+ "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(
|
||||
() -> mDeviceConfigDisplaySettings.getHighDisplayBrightnessThresholds(),
|
||||
() -> displayDeviceConfig.getHighDisplayBrightnessThresholds(),
|
||||
R.array.config_highDisplayBrightnessThresholdsOfFixedRefreshRate,
|
||||
displayDeviceConfig);
|
||||
displayDeviceConfig, attemptLoadingFromDeviceConfig);
|
||||
mHighAmbientBrightnessThresholds = loadBrightnessThresholds(
|
||||
() -> mDeviceConfigDisplaySettings.getHighAmbientBrightnessThresholds(),
|
||||
() -> displayDeviceConfig.getHighAmbientBrightnessThresholds(),
|
||||
R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate,
|
||||
displayDeviceConfig);
|
||||
displayDeviceConfig, attemptLoadingFromDeviceConfig);
|
||||
if (mHighDisplayBrightnessThresholds.length
|
||||
!= mHighAmbientBrightnessThresholds.length) {
|
||||
throw new RuntimeException("display high brightness threshold array and ambient "
|
||||
@@ -1605,13 +1651,16 @@ public class DisplayModeDirector {
|
||||
Callable<int[]> loadFromDeviceConfigDisplaySettingsCallable,
|
||||
Callable<int[]> loadFromDisplayDeviceConfigCallable,
|
||||
int brightnessThresholdOfFixedRefreshRateKey,
|
||||
DisplayDeviceConfig displayDeviceConfig) {
|
||||
DisplayDeviceConfig displayDeviceConfig, boolean attemptLoadingFromDeviceConfig) {
|
||||
int[] brightnessThresholds = null;
|
||||
try {
|
||||
brightnessThresholds =
|
||||
|
||||
if (attemptLoadingFromDeviceConfig) {
|
||||
try {
|
||||
brightnessThresholds =
|
||||
loadFromDeviceConfigDisplaySettingsCallable.call();
|
||||
} catch (Exception exception) {
|
||||
// Do nothing
|
||||
} catch (Exception exception) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
if (brightnessThresholds == null) {
|
||||
try {
|
||||
|
||||
@@ -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_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_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_SUNLIGHT;
|
||||
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 org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -48,6 +51,7 @@ import android.annotation.NonNull;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.content.res.Resources;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
@@ -76,6 +80,7 @@ import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.display.BrightnessSynchronizer;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
@@ -1855,16 +1860,83 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
@Test
|
||||
public void testNotifyDefaultDisplayDeviceUpdated() {
|
||||
DisplayDeviceConfig displayDeviceConfig = mock(DisplayDeviceConfig.class);
|
||||
when(displayDeviceConfig.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{});
|
||||
when(displayDeviceConfig.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{});
|
||||
when(displayDeviceConfig.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{});
|
||||
when(displayDeviceConfig.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{});
|
||||
Resources resources = mock(Resources.class);
|
||||
when(mContext.getResources()).thenReturn(resources);
|
||||
when(resources.getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate))
|
||||
.thenReturn(75);
|
||||
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 =
|
||||
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);
|
||||
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) {
|
||||
@@ -1954,6 +2026,12 @@ public class DisplayModeDirectorTest {
|
||||
String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setDefaultPeakRefreshRate(int fps) {
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_PEAK_REFRESH_RATE_DEFAULT,
|
||||
String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||
String thresholds = toPropertyValue(brightnessThresholds);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user