Merge changes from topic "revert_high_zone" into rvc-qpr-dev
* changes: DO NOT MERGE Revert "Set fixed fps when ambient or display brightness is high" DO NOT MERGE Revert "Allow DeviceConfig to change display settings for high zone" DO NOT MERGE Revert "Fix the ambient lux which did not update for blocking zone"
This commit is contained in:
committed by
Android (Google) Code Review
commit
4d0d51d7f5
@@ -875,52 +875,12 @@ public final class DisplayManager {
|
||||
public interface DeviceConfig {
|
||||
|
||||
/**
|
||||
* Key for refresh rate in the low zone defined by thresholds.
|
||||
* Key for refresh rate in the zone defined by thresholds.
|
||||
*
|
||||
* Note that the name and value don't match because they were added before we had a high
|
||||
* zone to consider.
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.integer#config_defaultZoneBehavior
|
||||
*/
|
||||
String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone";
|
||||
|
||||
/**
|
||||
* Key for accessing the low display brightness thresholds for the configured refresh
|
||||
* rate zone.
|
||||
* The value will be a pair of comma separated integers representing the minimum and maximum
|
||||
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
|
||||
*
|
||||
* Note that the name and value don't match because they were added before we had a high
|
||||
* zone to consider.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
|
||||
* @hide
|
||||
*/
|
||||
String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
||||
"peak_refresh_rate_brightness_thresholds";
|
||||
|
||||
/**
|
||||
* Key for accessing the low ambient brightness thresholds for the configured refresh
|
||||
* rate zone. The value will be a pair of comma separated integers representing the minimum
|
||||
* and maximum thresholds of the zone, respectively, in lux.
|
||||
*
|
||||
* Note that the name and value don't match because they were added before we had a high
|
||||
* zone to consider.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
|
||||
* @hide
|
||||
*/
|
||||
String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||
"peak_refresh_rate_ambient_thresholds";
|
||||
/**
|
||||
* Key for refresh rate in the high zone defined by thresholds.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.integer#config_fixedRefreshRateInHighZone
|
||||
*/
|
||||
String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone";
|
||||
String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
|
||||
|
||||
/**
|
||||
* Key for accessing the display brightness thresholds for the configured refresh rate zone.
|
||||
@@ -928,11 +888,11 @@ public final class DisplayManager {
|
||||
* thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate
|
||||
* @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
|
||||
* @hide
|
||||
*/
|
||||
String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
||||
"fixed_refresh_rate_high_display_brightness_thresholds";
|
||||
String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
|
||||
"peak_refresh_rate_brightness_thresholds";
|
||||
|
||||
/**
|
||||
* Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
|
||||
@@ -940,11 +900,12 @@ public final class DisplayManager {
|
||||
* thresholds of the zone, respectively, in lux.
|
||||
*
|
||||
* @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
|
||||
* @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate
|
||||
* @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
|
||||
* @hide
|
||||
*/
|
||||
String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||
"fixed_refresh_rate_high_ambient_brightness_thresholds";
|
||||
String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
|
||||
"peak_refresh_rate_ambient_thresholds";
|
||||
|
||||
/**
|
||||
* Key for default peak refresh rate
|
||||
*
|
||||
|
||||
@@ -4138,35 +4138,6 @@
|
||||
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||
<integer name="config_defaultRefreshRateInZone">0</integer>
|
||||
|
||||
<!-- The display uses different gamma curves for different refresh rates. It's hard for panel
|
||||
vendor to tune the curves to have exact same brightness for different refresh rate. So
|
||||
flicker could be observed at switch time. The issue can be observed on the screen with
|
||||
even full white content at the high brightness. To prevent flickering, we support fixed
|
||||
refresh rates if the display and ambient brightness are equal to or above the provided
|
||||
thresholds. You can define multiple threshold levels as higher brightness environments
|
||||
may have lower display brightness requirements for the flickering is visible. And the
|
||||
high brightness environment could have higher threshold.
|
||||
For example, fixed refresh rate if
|
||||
display brightness >= disp0 && ambient brightness >= amb0
|
||||
|| display brightness >= disp1 && ambient brightness >= amb1 -->
|
||||
<integer-array translatable="false" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate">
|
||||
<!--
|
||||
<item>disp0</item>
|
||||
<item>disp1</item>
|
||||
-->
|
||||
</integer-array>
|
||||
|
||||
<integer-array translatable="false" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate">
|
||||
<!--
|
||||
<item>amb0</item>
|
||||
<item>amb1</item>
|
||||
-->
|
||||
</integer-array>
|
||||
|
||||
<!-- Default refresh rate in the high zone defined by brightness and ambient thresholds.
|
||||
If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
|
||||
<integer name="config_fixedRefreshRateInHighZone">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" />
|
||||
|
||||
@@ -3783,11 +3783,6 @@
|
||||
<java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
|
||||
<java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
|
||||
|
||||
<!-- For fixed refresh rate displays in high brightness-->
|
||||
<java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
|
||||
<java-symbol type="array" name="config_highDisplayBrightnessThresholdsOfFixedRefreshRate" />
|
||||
<java-symbol type="array" name="config_highAmbientBrightnessThresholdsOfFixedRefreshRate" />
|
||||
|
||||
<!-- For Auto-Brightness -->
|
||||
<java-symbol type="string" name="config_displayLightSensorType" />
|
||||
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
filegroup {
|
||||
name: "services.core-sources-deviceconfig-interface",
|
||||
srcs: [
|
||||
"java/com/android/server/utils/DeviceConfigInterface.java"
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "services.core-sources",
|
||||
srcs: ["java/**/*.java"],
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,7 @@ import android.util.ArraySet;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.os.BackgroundThread;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import android.provider.AndroidDeviceConfig;
|
||||
import android.provider.DeviceConfig;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -282,8 +282,8 @@ import com.android.server.policy.WindowManagerPolicy.ScreenOffListener;
|
||||
import com.android.server.power.ShutdownThread;
|
||||
import com.android.server.protolog.ProtoLogImpl;
|
||||
import com.android.server.protolog.common.ProtoLog;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
import com.android.server.utils.PriorityDump;
|
||||
import com.android.server.wm.utils.DeviceConfigInterface;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.DataInputStream;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.utils;
|
||||
package com.android.server.wm.utils;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -53,11 +53,6 @@ public interface DeviceConfigInterface {
|
||||
*/
|
||||
boolean getBoolean(@NonNull String namespace, @NonNull String name, boolean defaultValue);
|
||||
|
||||
/**
|
||||
* @see DeviceConfig#getFloat
|
||||
*/
|
||||
float getFloat(@NonNull String namespace, @NonNull String name, float defaultValue);
|
||||
|
||||
/**
|
||||
* @see DeviceConfig#addOnPropertiesChangedListener
|
||||
*/
|
||||
@@ -100,12 +95,6 @@ public interface DeviceConfigInterface {
|
||||
return DeviceConfig.getBoolean(namespace, name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(@NonNull String namespace, @NonNull String name,
|
||||
float defaultValue) {
|
||||
return DeviceConfig.getFloat(namespace, name, defaultValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnPropertiesChangedListener(String namespace, Executor executor,
|
||||
DeviceConfig.OnPropertiesChangedListener listener) {
|
||||
@@ -48,6 +48,7 @@ android_test {
|
||||
// TODO: remove once Android migrates to JUnit 4.12,
|
||||
// which provides assertThrows
|
||||
"testng",
|
||||
|
||||
],
|
||||
|
||||
aidl: {
|
||||
@@ -109,7 +110,6 @@ java_library {
|
||||
"utils/**/*.java",
|
||||
"utils/**/*.kt",
|
||||
"utils-mockito/**/*.kt",
|
||||
":services.core-sources-deviceconfig-interface",
|
||||
],
|
||||
static_libs: [
|
||||
"junit",
|
||||
@@ -126,7 +126,6 @@ java_library {
|
||||
"utils/**/*.java",
|
||||
"utils/**/*.kt",
|
||||
"utils-mockito/**/*.kt",
|
||||
":services.core-sources-deviceconfig-interface",
|
||||
],
|
||||
static_libs: [
|
||||
"junit",
|
||||
|
||||
@@ -16,100 +16,49 @@
|
||||
|
||||
package com.android.server.display;
|
||||
|
||||
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_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_DISPLAY_BRIGHTNESS_THRESHOLDS;
|
||||
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 com.android.server.display.DisplayModeDirector.Vote.PRIORITY_FLICKER;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.any;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.mockito.internal.verification.VerificationModeFactory.times;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.test.mock.MockContentResolver;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.internal.util.test.FakeSettingsProvider;
|
||||
import com.android.internal.util.test.FakeSettingsProviderRule;
|
||||
import com.android.server.display.DisplayModeDirector.BrightnessObserver;
|
||||
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
|
||||
import com.android.server.display.DisplayModeDirector.Vote;
|
||||
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||
|
||||
import com.google.common.truth.Truth;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DisplayModeDirectorTest {
|
||||
// The tolerance within which we consider something approximately equals.
|
||||
private static final String TAG = "DisplayModeDirectorTest";
|
||||
private static final boolean DEBUG = false;
|
||||
private static final float FLOAT_TOLERANCE = 0.01f;
|
||||
|
||||
private Context mContext;
|
||||
private FakesInjector mInjector;
|
||||
private Handler mHandler;
|
||||
@Rule
|
||||
public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
|
||||
final MockContentResolver resolver = mSettingsProviderRule.mockContentResolver(mContext);
|
||||
when(mContext.getContentResolver()).thenReturn(resolver);
|
||||
mInjector = new FakesInjector();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
mContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
}
|
||||
|
||||
private DisplayModeDirector createDirectorFromRefreshRateArray(
|
||||
float[] refreshRates, int baseModeId) {
|
||||
DisplayModeDirector director =
|
||||
new DisplayModeDirector(mContext, mHandler, mInjector);
|
||||
new DisplayModeDirector(mContext, new Handler(Looper.getMainLooper()));
|
||||
int displayId = 0;
|
||||
Display.Mode[] modes = new Display.Mode[refreshRates.length];
|
||||
for (int i = 0; i < refreshRates.length; i++) {
|
||||
@@ -210,9 +159,9 @@ public class DisplayModeDirectorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFlickerHasLowerPriorityThanUser() {
|
||||
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
|
||||
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_SIZE);
|
||||
public void testBrightnessHasLowerPriorityThanUser() {
|
||||
assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
|
||||
assertTrue(Vote.PRIORITY_LOW_BRIGHTNESS < Vote.PRIORITY_APP_REQUEST_SIZE);
|
||||
|
||||
int displayId = 0;
|
||||
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
|
||||
@@ -220,7 +169,7 @@ public class DisplayModeDirectorTest {
|
||||
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
||||
votesByDisplay.put(displayId, votes);
|
||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
||||
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
||||
director.injectVotesByDisplay(votesByDisplay);
|
||||
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||
@@ -228,7 +177,7 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
votes.clear();
|
||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
|
||||
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
|
||||
director.injectVotesByDisplay(votesByDisplay);
|
||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
||||
@@ -236,7 +185,7 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
votes.clear();
|
||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
|
||||
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
||||
director.injectVotesByDisplay(votesByDisplay);
|
||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
|
||||
@@ -244,7 +193,7 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
votes.clear();
|
||||
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
|
||||
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
|
||||
director.injectVotesByDisplay(votesByDisplay);
|
||||
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||
@@ -253,10 +202,10 @@ public class DisplayModeDirectorTest {
|
||||
|
||||
@Test
|
||||
public void testAppRequestRefreshRateRange() {
|
||||
// Confirm that the app request range doesn't include flicker or min refresh rate settings,
|
||||
// but does include everything else.
|
||||
// Confirm that the app request range doesn't include low brightness or min refresh rate
|
||||
// settings, but does include everything else.
|
||||
assertTrue(
|
||||
PRIORITY_FLICKER < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
||||
Vote.PRIORITY_LOW_BRIGHTNESS < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
||||
assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
|
||||
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
|
||||
assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
|
||||
@@ -267,7 +216,7 @@ public class DisplayModeDirectorTest {
|
||||
SparseArray<Vote> votes = new SparseArray<>();
|
||||
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
||||
votesByDisplay.put(displayId, votes);
|
||||
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
|
||||
director.injectVotesByDisplay(votesByDisplay);
|
||||
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
|
||||
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
|
||||
@@ -353,380 +302,4 @@ public class DisplayModeDirectorTest {
|
||||
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
|
||||
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBrightnessObserverGetsUpdatedRefreshRatesForZone() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||
SensorManager sensorManager = createMockSensorManager(createLightSensor());
|
||||
|
||||
final int initialRefreshRate = 60;
|
||||
mInjector.getDeviceConfig().setRefreshRateInLowZone(initialRefreshRate);
|
||||
director.start(sensorManager);
|
||||
assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
|
||||
.isEqualTo(initialRefreshRate);
|
||||
|
||||
final int updatedRefreshRate = 90;
|
||||
mInjector.getDeviceConfig().setRefreshRateInLowZone(updatedRefreshRate);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getBrightnessObserver().getRefreshRateInLowZone())
|
||||
.isEqualTo(updatedRefreshRate);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBrightnessObserverThresholdsInZone() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, /* baseModeId= */ 0);
|
||||
SensorManager sensorManager = createMockSensorManager(createLightSensor());
|
||||
|
||||
final int[] initialDisplayThresholds = { 10 };
|
||||
final int[] initialAmbientThresholds = { 20 };
|
||||
|
||||
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||
config.setLowDisplayBrightnessThresholds(initialDisplayThresholds);
|
||||
config.setLowAmbientBrightnessThresholds(initialAmbientThresholds);
|
||||
director.start(sensorManager);
|
||||
|
||||
assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
|
||||
.isEqualTo(initialDisplayThresholds);
|
||||
assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
|
||||
.isEqualTo(initialAmbientThresholds);
|
||||
|
||||
final int[] updatedDisplayThresholds = { 9, 14 };
|
||||
final int[] updatedAmbientThresholds = { -1, 19 };
|
||||
config.setLowDisplayBrightnessThresholds(updatedDisplayThresholds);
|
||||
config.setLowAmbientBrightnessThresholds(updatedAmbientThresholds);
|
||||
// Need to wait for the property change to propagate to the main thread.
|
||||
waitForIdleSync();
|
||||
assertThat(director.getBrightnessObserver().getLowDisplayBrightnessThresholds())
|
||||
.isEqualTo(updatedDisplayThresholds);
|
||||
assertThat(director.getBrightnessObserver().getLowAmbientBrightnessThresholds())
|
||||
.isEqualTo(updatedAmbientThresholds);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockFpsForLowZone() throws Exception {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||
setPeakRefreshRate(90);
|
||||
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
|
||||
|
||||
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||
config.setRefreshRateInLowZone(90);
|
||||
config.setLowDisplayBrightnessThresholds(new int[] { 10 });
|
||||
config.setLowAmbientBrightnessThresholds(new int[] { 20 });
|
||||
|
||||
Sensor lightSensor = createLightSensor();
|
||||
SensorManager sensorManager = createMockSensorManager(lightSensor);
|
||||
|
||||
director.start(sensorManager);
|
||||
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||
.registerListener(
|
||||
listenerCaptor.capture(),
|
||||
eq(lightSensor),
|
||||
anyInt(),
|
||||
any(Handler.class));
|
||||
SensorEventListener listener = listenerCaptor.getValue();
|
||||
|
||||
setBrightness(10);
|
||||
// Sensor reads 20 lux,
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
|
||||
|
||||
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||
assertVoteForRefreshRateLocked(vote, 90 /*fps*/);
|
||||
|
||||
setBrightness(125);
|
||||
// Sensor reads 1000 lux,
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
|
||||
|
||||
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||
assertThat(vote).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockFpsForHighZone() throws Exception {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||
setPeakRefreshRate(90 /*fps*/);
|
||||
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
|
||||
|
||||
final FakeDeviceConfig config = mInjector.getDeviceConfig();
|
||||
config.setRefreshRateInHighZone(60);
|
||||
config.setHighDisplayBrightnessThresholds(new int[] { 255 });
|
||||
config.setHighAmbientBrightnessThresholds(new int[] { 8000 });
|
||||
|
||||
Sensor lightSensor = createLightSensor();
|
||||
SensorManager sensorManager = createMockSensorManager(lightSensor);
|
||||
|
||||
director.start(sensorManager);
|
||||
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||
.registerListener(
|
||||
listenerCaptor.capture(),
|
||||
eq(lightSensor),
|
||||
anyInt(),
|
||||
any(Handler.class));
|
||||
SensorEventListener listener = listenerCaptor.getValue();
|
||||
|
||||
setBrightness(100);
|
||||
// Sensor reads 2000 lux,
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
|
||||
|
||||
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||
assertThat(vote).isNull();
|
||||
|
||||
setBrightness(255);
|
||||
// Sensor reads 9000 lux,
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
|
||||
|
||||
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
|
||||
assertVoteForRefreshRateLocked(vote, 60 /*fps*/);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSensorRegistration() {
|
||||
DisplayModeDirector director =
|
||||
createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
|
||||
setPeakRefreshRate(90 /*fps*/);
|
||||
director.getSettingsObserver().setDefaultRefreshRate(90);
|
||||
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
|
||||
|
||||
Sensor lightSensor = createLightSensor();
|
||||
SensorManager sensorManager = createMockSensorManager(lightSensor);
|
||||
|
||||
director.start(sensorManager);
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
|
||||
.registerListener(
|
||||
listenerCaptor.capture(),
|
||||
eq(lightSensor),
|
||||
anyInt(),
|
||||
any(Handler.class));
|
||||
|
||||
// Dispaly state changed from On to Doze
|
||||
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_DOZE);
|
||||
Mockito.verify(sensorManager)
|
||||
.unregisterListener(listenerCaptor.capture());
|
||||
|
||||
// Dispaly state changed from Doze to On
|
||||
director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);
|
||||
Mockito.verify(sensorManager, times(2))
|
||||
.registerListener(
|
||||
listenerCaptor.capture(),
|
||||
eq(lightSensor),
|
||||
anyInt(),
|
||||
any(Handler.class));
|
||||
|
||||
}
|
||||
|
||||
private void assertVoteForRefreshRateLocked(Vote vote, float refreshRate) {
|
||||
assertThat(vote).isNotNull();
|
||||
final DisplayModeDirector.RefreshRateRange expectedRange =
|
||||
new DisplayModeDirector.RefreshRateRange(refreshRate, refreshRate);
|
||||
assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
|
||||
}
|
||||
|
||||
private static class FakeDeviceConfig extends FakeDeviceConfigInterface {
|
||||
@Override
|
||||
public String getProperty(String namespace, String name) {
|
||||
Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
|
||||
return super.getProperty(namespace, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addOnPropertiesChangedListener(
|
||||
String namespace,
|
||||
Executor executor,
|
||||
DeviceConfig.OnPropertiesChangedListener listener) {
|
||||
Preconditions.checkArgument(DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace));
|
||||
super.addOnPropertiesChangedListener(namespace, executor, listener);
|
||||
}
|
||||
|
||||
void setRefreshRateInLowZone(int fps) {
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_LOW_ZONE,
|
||||
String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||
String thresholds = toPropertyValue(brightnessThresholds);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.e(TAG, "Brightness Thresholds = " + thresholds);
|
||||
}
|
||||
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS,
|
||||
thresholds);
|
||||
}
|
||||
|
||||
void setLowAmbientBrightnessThresholds(int[] ambientThresholds) {
|
||||
String thresholds = toPropertyValue(ambientThresholds);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.e(TAG, "Ambient Thresholds = " + thresholds);
|
||||
}
|
||||
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS,
|
||||
thresholds);
|
||||
}
|
||||
|
||||
void setRefreshRateInHighZone(int fps) {
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER, KEY_REFRESH_RATE_IN_HIGH_ZONE,
|
||||
String.valueOf(fps));
|
||||
}
|
||||
|
||||
void setHighDisplayBrightnessThresholds(int[] brightnessThresholds) {
|
||||
String thresholds = toPropertyValue(brightnessThresholds);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.e(TAG, "Brightness Thresholds = " + thresholds);
|
||||
}
|
||||
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS,
|
||||
thresholds);
|
||||
}
|
||||
|
||||
void setHighAmbientBrightnessThresholds(int[] ambientThresholds) {
|
||||
String thresholds = toPropertyValue(ambientThresholds);
|
||||
|
||||
if (DEBUG) {
|
||||
Slog.e(TAG, "Ambient Thresholds = " + thresholds);
|
||||
}
|
||||
|
||||
putPropertyAndNotify(
|
||||
DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
|
||||
KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS,
|
||||
thresholds);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static String toPropertyValue(@NonNull int[] intArray) {
|
||||
return Arrays.stream(intArray)
|
||||
.mapToObj(Integer::toString)
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
}
|
||||
|
||||
private void setBrightness(int brightness) {
|
||||
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,
|
||||
brightness);
|
||||
mInjector.notifyBrightnessChanged();
|
||||
waitForIdleSync();
|
||||
}
|
||||
|
||||
private void setPeakRefreshRate(float fps) {
|
||||
Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
|
||||
fps);
|
||||
mInjector.notifyPeakRefreshRateChanged();
|
||||
waitForIdleSync();
|
||||
}
|
||||
|
||||
private static SensorManager createMockSensorManager(Sensor... sensors) {
|
||||
SensorManager sensorManager = Mockito.mock(SensorManager.class);
|
||||
when(sensorManager.getSensorList(anyInt())).then((invocation) -> {
|
||||
List<Sensor> requestedSensors = new ArrayList<>();
|
||||
int type = invocation.getArgument(0);
|
||||
for (Sensor sensor : sensors) {
|
||||
if (sensor.getType() == type || type == Sensor.TYPE_ALL) {
|
||||
requestedSensors.add(sensor);
|
||||
}
|
||||
}
|
||||
return requestedSensors;
|
||||
});
|
||||
|
||||
when(sensorManager.getDefaultSensor(anyInt())).then((invocation) -> {
|
||||
int type = invocation.getArgument(0);
|
||||
for (Sensor sensor : sensors) {
|
||||
if (sensor.getType() == type) {
|
||||
return sensor;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
});
|
||||
return sensorManager;
|
||||
}
|
||||
|
||||
private static Sensor createLightSensor() {
|
||||
try {
|
||||
return TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
|
||||
} catch (Exception e) {
|
||||
// There's nothing we can do if this fails, just throw a RuntimeException so that we
|
||||
// don't have to mark every function that might call this as throwing Exception
|
||||
throw new RuntimeException("Failed to create a light sensor", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void waitForIdleSync() {
|
||||
mHandler.runWithScissors(() -> { }, 500 /*timeout*/);
|
||||
}
|
||||
|
||||
static class FakesInjector implements DisplayModeDirector.Injector {
|
||||
private final FakeDeviceConfig mDeviceConfig;
|
||||
private ContentObserver mBrightnessObserver;
|
||||
private ContentObserver mPeakRefreshRateObserver;
|
||||
|
||||
FakesInjector() {
|
||||
mDeviceConfig = new FakeDeviceConfig();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public FakeDeviceConfig getDeviceConfig() {
|
||||
return mDeviceConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBrightnessObserver(@NonNull ContentResolver cr,
|
||||
@NonNull ContentObserver observer) {
|
||||
if (mBrightnessObserver != null) {
|
||||
throw new IllegalStateException("Tried to register a second brightness observer");
|
||||
}
|
||||
mBrightnessObserver = observer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
|
||||
@NonNull ContentObserver observer) {
|
||||
mBrightnessObserver = null;
|
||||
}
|
||||
|
||||
void notifyBrightnessChanged() {
|
||||
if (mBrightnessObserver != null) {
|
||||
mBrightnessObserver.dispatchChange(false /*selfChange*/, DISPLAY_BRIGHTNESS_URI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
|
||||
@NonNull ContentObserver observer) {
|
||||
mPeakRefreshRateObserver = observer;
|
||||
}
|
||||
|
||||
void notifyPeakRefreshRateChanged() {
|
||||
if (mPeakRefreshRateObserver != null) {
|
||||
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,
|
||||
PEAK_REFRESH_RATE_URI);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeviceInteractive(@NonNull Context context) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||
import com.android.server.wm.utils.FakeDeviceConfigInterface;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -32,7 +32,7 @@ import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.server.testutils.FakeDeviceConfigInterface;
|
||||
import com.android.server.wm.utils.FakeDeviceConfigInterface;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.testutils;
|
||||
package com.android.server.wm.utils;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.provider.DeviceConfig;
|
||||
@@ -22,7 +22,6 @@ import android.util.ArrayMap;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.server.utils.DeviceConfigInterface;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.HashMap;
|
||||
@@ -122,19 +121,6 @@ public class FakeDeviceConfigInterface implements DeviceConfigInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(String namespace, String name, float defaultValue) {
|
||||
String value = getProperty(namespace, name);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Float.parseFloat(value);
|
||||
} catch (NumberFormatException e) {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(String namespace, String name, boolean defaultValue) {
|
||||
String value = getProperty(namespace, name);
|
||||
Reference in New Issue
Block a user