Use a brightness sensor to determine the screen's initial brightness
- Create a controller to listen to a brightness sensor when the screen is off - Estimate the ambient lux based on the sensor reading - Determine the brightness using the ambient lux estimate - Specify the sensor and the sensor value to lux mapping in the config Bug: 193224604 Test: Use the device in a bright room, turn the screen off, go to a dark room, turn the screen on, see that the screen doesn't start as too bright. Test: atest ScreenOffBrightnessSensorControllerTest Test: atest DisplayDeviceConfigTest Change-Id: Ib4c4d9e0d6b385b0d309be6b8c27b71af72d4ecc Merged-In: Ib4c4d9e0d6b385b0d309be6b8c27b71af72d4ecc
This commit is contained in:
@@ -46,6 +46,7 @@ import com.android.server.display.config.DisplayConfiguration;
|
||||
import com.android.server.display.config.DisplayQuirks;
|
||||
import com.android.server.display.config.HbmTiming;
|
||||
import com.android.server.display.config.HighBrightnessMode;
|
||||
import com.android.server.display.config.IntegerArray;
|
||||
import com.android.server.display.config.NitsMap;
|
||||
import com.android.server.display.config.Point;
|
||||
import com.android.server.display.config.RefreshRateConfigs;
|
||||
@@ -213,6 +214,10 @@ import javax.xml.datatype.DatatypeConfigurationException;
|
||||
* <type>android.sensor.light</type>
|
||||
* <name>1234 Ambient Light Sensor</name>
|
||||
* </lightSensor>
|
||||
* <screenOffBrightnessSensor>
|
||||
* <type>com.google.sensor.binned_brightness</type>
|
||||
* <name>Binned Brightness 0 (wake-up)</name>
|
||||
* </screenOffBrightnessSensor>
|
||||
* <proxSensor>
|
||||
* <type>android.sensor.proximity</type>
|
||||
* <name>1234 Proximity Sensor</name>
|
||||
@@ -368,6 +373,13 @@ import javax.xml.datatype.DatatypeConfigurationException;
|
||||
* </brightnessThresholdPoints>
|
||||
* </darkeningThresholds>
|
||||
* </displayBrightnessChangeThresholdsIdle>
|
||||
* <screenOffBrightnessSensorValueToLux>
|
||||
* <item>-1</item>
|
||||
* <item>0</item>
|
||||
* <item>5</item>
|
||||
* <item>80</item>
|
||||
* <item>1500</item>
|
||||
* </screenOffBrightnessSensorValueToLux>
|
||||
* </displayConfiguration>
|
||||
* }
|
||||
* </pre>
|
||||
@@ -428,6 +440,9 @@ public class DisplayDeviceConfig {
|
||||
// The details of the ambient light sensor associated with this display.
|
||||
private final SensorData mAmbientLightSensor = new SensorData();
|
||||
|
||||
// The details of the doze brightness sensor associated with this display.
|
||||
private final SensorData mScreenOffBrightnessSensor = new SensorData();
|
||||
|
||||
// The details of the proximity sensor associated with this display.
|
||||
private final SensorData mProximitySensor = new SensorData();
|
||||
|
||||
@@ -523,6 +538,9 @@ public class DisplayDeviceConfig {
|
||||
private float[] mAmbientDarkeningLevelsIdle = DEFAULT_AMBIENT_THRESHOLD_LEVELS;
|
||||
private float[] mAmbientDarkeningPercentagesIdle = DEFAULT_AMBIENT_DARKENING_THRESHOLDS;
|
||||
|
||||
// A mapping between screen off sensor values and lux values
|
||||
private int[] mScreenOffBrightnessSensorValueToLux;
|
||||
|
||||
private Spline mBrightnessToBacklightSpline;
|
||||
private Spline mBacklightToBrightnessSpline;
|
||||
private Spline mBacklightToNitsSpline;
|
||||
@@ -1198,6 +1216,10 @@ public class DisplayDeviceConfig {
|
||||
return mAmbientLightSensor;
|
||||
}
|
||||
|
||||
SensorData getScreenOffBrightnessSensor() {
|
||||
return mScreenOffBrightnessSensor;
|
||||
}
|
||||
|
||||
SensorData getProximitySensor() {
|
||||
return mProximitySensor;
|
||||
}
|
||||
@@ -1321,6 +1343,14 @@ public class DisplayDeviceConfig {
|
||||
return mHighAmbientBrightnessThresholds;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A mapping from screen off brightness sensor readings to lux values. This estimates
|
||||
* the ambient lux when the screen is off to determine the initial brightness
|
||||
*/
|
||||
public int[] getScreenOffBrightnessSensorValueToLux() {
|
||||
return mScreenOffBrightnessSensorValueToLux;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisplayDeviceConfig{"
|
||||
@@ -1399,6 +1429,7 @@ public class DisplayDeviceConfig {
|
||||
mScreenDarkeningPercentagesIdle)
|
||||
+ "\n"
|
||||
+ ", mAmbientLightSensor=" + mAmbientLightSensor
|
||||
+ ", mScreenOffBrightnessSensor=" + mScreenOffBrightnessSensor
|
||||
+ ", mProximitySensor=" + mProximitySensor
|
||||
+ ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray())
|
||||
+ ", mDensityMapping= " + mDensityMapping
|
||||
@@ -1421,6 +1452,9 @@ public class DisplayDeviceConfig {
|
||||
+ Arrays.toString(mHighDisplayBrightnessThresholds)
|
||||
+ ", mHighAmbientBrightnessThresholds= "
|
||||
+ Arrays.toString(mHighAmbientBrightnessThresholds)
|
||||
+ "\n"
|
||||
+ ", mScreenOffBrightnessSensorValueToLux=" + Arrays.toString(
|
||||
mScreenOffBrightnessSensorValueToLux)
|
||||
+ "}";
|
||||
}
|
||||
|
||||
@@ -1474,11 +1508,13 @@ public class DisplayDeviceConfig {
|
||||
loadQuirks(config);
|
||||
loadBrightnessRamps(config);
|
||||
loadAmbientLightSensorFromDdc(config);
|
||||
loadScreenOffBrightnessSensorFromDdc(config);
|
||||
loadProxSensorFromDdc(config);
|
||||
loadAmbientHorizonFromDdc(config);
|
||||
loadBrightnessChangeThresholds(config);
|
||||
loadAutoBrightnessConfigValues(config);
|
||||
loadRefreshRateSetting(config);
|
||||
loadScreenOffBrightnessSensorValueToLuxFromDdc(config);
|
||||
} else {
|
||||
Slog.w(TAG, "DisplayDeviceConfig file is null");
|
||||
}
|
||||
@@ -2175,6 +2211,14 @@ public class DisplayDeviceConfig {
|
||||
mProximitySensor.type = "";
|
||||
}
|
||||
|
||||
private void loadScreenOffBrightnessSensorFromDdc(DisplayConfiguration config) {
|
||||
final SensorDetails sensorDetails = config.getScreenOffBrightnessSensor();
|
||||
if (sensorDetails != null) {
|
||||
mScreenOffBrightnessSensor.type = sensorDetails.getType();
|
||||
mScreenOffBrightnessSensor.name = sensorDetails.getName();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadProxSensorFromDdc(DisplayConfiguration config) {
|
||||
SensorDetails sensorDetails = config.getProxSensor();
|
||||
if (sensorDetails != null) {
|
||||
@@ -2587,6 +2631,19 @@ public class DisplayDeviceConfig {
|
||||
&& mDdcAutoBrightnessAvailable;
|
||||
}
|
||||
|
||||
private void loadScreenOffBrightnessSensorValueToLuxFromDdc(DisplayConfiguration config) {
|
||||
IntegerArray sensorValueToLux = config.getScreenOffBrightnessSensorValueToLux();
|
||||
if (sensorValueToLux == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<BigInteger> items = sensorValueToLux.getItem();
|
||||
mScreenOffBrightnessSensorValueToLux = new int[items.size()];
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
mScreenOffBrightnessSensorValueToLux[i] = items.get(i).intValue();
|
||||
}
|
||||
}
|
||||
|
||||
static class SensorData {
|
||||
public String type;
|
||||
public String name;
|
||||
|
||||
@@ -411,7 +411,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
@Nullable
|
||||
private AutomaticBrightnessController mAutomaticBrightnessController;
|
||||
|
||||
// The controller for the sensor used to estimate ambient lux while the display is off.
|
||||
@Nullable
|
||||
private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
|
||||
|
||||
private Sensor mLightSensor;
|
||||
private Sensor mScreenOffBrightnessSensor;
|
||||
|
||||
// The mappers between ambient lux, display backlight values, and display brightness.
|
||||
// We will switch between the idle mapper and active mapper in AutomaticBrightnessController.
|
||||
@@ -1088,6 +1093,19 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
|
||||
mBrightnessEventRingBuffer =
|
||||
new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
|
||||
|
||||
loadScreenOffBrightnessSensor();
|
||||
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
|
||||
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
|
||||
mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
|
||||
mSensorManager,
|
||||
mScreenOffBrightnessSensor,
|
||||
mHandler,
|
||||
SystemClock::uptimeMillis,
|
||||
sensorValueToLux,
|
||||
mInteractiveModeBrightnessMapper
|
||||
);
|
||||
}
|
||||
} else {
|
||||
mUseSoftwareAutoBrightnessConfig = false;
|
||||
}
|
||||
@@ -1265,6 +1283,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
}
|
||||
assert(state != Display.STATE_UNKNOWN);
|
||||
|
||||
if (mScreenOffBrightnessSensorController != null) {
|
||||
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
|
||||
&& (state == Display.STATE_OFF || (state == Display.STATE_DOZE
|
||||
&& !mAllowAutoBrightnessWhileDozingConfig)));
|
||||
}
|
||||
|
||||
boolean skipRampBecauseOfProximityChangeToNegative = false;
|
||||
// Apply the proximity sensor.
|
||||
if (mProximitySensor != null) {
|
||||
@@ -1442,6 +1466,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
updateScreenBrightnessSetting = mCurrentScreenBrightnessSetting != brightnessState;
|
||||
mAppliedAutoBrightness = true;
|
||||
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
|
||||
if (mScreenOffBrightnessSensorController != null) {
|
||||
mScreenOffBrightnessSensorController.setLightSensorEnabled(false);
|
||||
}
|
||||
} else {
|
||||
mAppliedAutoBrightness = false;
|
||||
}
|
||||
@@ -1469,6 +1496,19 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
|
||||
}
|
||||
|
||||
// The ALS is not available yet - use the screen off sensor to determine the initial
|
||||
// brightness
|
||||
if (Float.isNaN(brightnessState) && autoBrightnessEnabled
|
||||
&& mScreenOffBrightnessSensorController != null) {
|
||||
brightnessState = mScreenOffBrightnessSensorController.getAutomaticScreenBrightness();
|
||||
if (isValidBrightnessValue(brightnessState)) {
|
||||
brightnessState = clampScreenBrightness(brightnessState);
|
||||
updateScreenBrightnessSetting = mCurrentScreenBrightnessSetting != brightnessState;
|
||||
mBrightnessReasonTemp.setReason(
|
||||
BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply manual brightness.
|
||||
if (Float.isNaN(brightnessState)) {
|
||||
brightnessState = clampScreenBrightness(mCurrentScreenBrightnessSetting);
|
||||
@@ -2038,6 +2078,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
fallbackType);
|
||||
}
|
||||
|
||||
private void loadScreenOffBrightnessSensor() {
|
||||
DisplayDeviceConfig.SensorData screenOffBrightnessSensor =
|
||||
mDisplayDeviceConfig.getScreenOffBrightnessSensor();
|
||||
mScreenOffBrightnessSensor = SensorUtils.findSensor(mSensorManager,
|
||||
screenOffBrightnessSensor.type, screenOffBrightnessSensor.name,
|
||||
SensorUtils.NO_FALLBACK);
|
||||
}
|
||||
|
||||
private void loadProximitySensor() {
|
||||
if (DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
|
||||
return;
|
||||
@@ -3186,7 +3234,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
static final int REASON_OVERRIDE = 7;
|
||||
static final int REASON_TEMPORARY = 8;
|
||||
static final int REASON_BOOST = 9;
|
||||
static final int REASON_MAX = REASON_BOOST;
|
||||
static final int REASON_SCREEN_OFF_BRIGHTNESS_SENSOR = 10;
|
||||
static final int REASON_MAX = REASON_SCREEN_OFF_BRIGHTNESS_SENSOR;
|
||||
|
||||
static final int MODIFIER_DIMMED = 0x1;
|
||||
static final int MODIFIER_LOW_POWER = 0x2;
|
||||
@@ -3296,6 +3345,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
|
||||
case REASON_OVERRIDE: return "override";
|
||||
case REASON_TEMPORARY: return "temporary";
|
||||
case REASON_BOOST: return "boost";
|
||||
case REASON_SCREEN_OFF_BRIGHTNESS_SENSOR: return "screen_off_brightness_sensor";
|
||||
default: return Integer.toString(reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.display;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.util.IndentingPrintWriter;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Controls the light sensor when the screen is off. The sensor used here does not report lux values
|
||||
* but an index that needs to be mapped to a lux value.
|
||||
*/
|
||||
public class ScreenOffBrightnessSensorController implements SensorEventListener {
|
||||
private static final String TAG = "ScreenOffBrightnessSensorController";
|
||||
|
||||
private static final int SENSOR_INVALID_VALUE = -1;
|
||||
private static final long SENSOR_VALUE_VALID_TIME_MILLIS = 1500;
|
||||
|
||||
private final Handler mHandler;
|
||||
private final Clock mClock;
|
||||
private final SensorManager mSensorManager;
|
||||
private final Sensor mLightSensor;
|
||||
private final int[] mSensorValueToLux;
|
||||
|
||||
private boolean mRegistered;
|
||||
private int mLastSensorValue = SENSOR_INVALID_VALUE;
|
||||
private long mSensorDisableTime = -1;
|
||||
|
||||
// The mapper to translate ambient lux to screen brightness in the range [0, 1.0].
|
||||
@Nullable
|
||||
private final BrightnessMappingStrategy mBrightnessMapper;
|
||||
|
||||
public ScreenOffBrightnessSensorController(
|
||||
SensorManager sensorManager,
|
||||
Sensor lightSensor,
|
||||
Handler handler,
|
||||
Clock clock,
|
||||
int[] sensorValueToLux,
|
||||
BrightnessMappingStrategy brightnessMapper) {
|
||||
mSensorManager = sensorManager;
|
||||
mLightSensor = lightSensor;
|
||||
mHandler = handler;
|
||||
mClock = clock;
|
||||
mSensorValueToLux = sensorValueToLux;
|
||||
mBrightnessMapper = brightnessMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (mRegistered) {
|
||||
mLastSensorValue = (int) event.values[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
||||
void setLightSensorEnabled(boolean enabled) {
|
||||
if (enabled && !mRegistered) {
|
||||
// Wait until we get an event from the sensor indicating ready.
|
||||
mRegistered = mSensorManager.registerListener(this, mLightSensor,
|
||||
SensorManager.SENSOR_DELAY_NORMAL, mHandler);
|
||||
mLastSensorValue = SENSOR_INVALID_VALUE;
|
||||
} else if (!enabled && mRegistered) {
|
||||
mSensorManager.unregisterListener(this);
|
||||
mRegistered = false;
|
||||
mSensorDisableTime = mClock.uptimeMillis();
|
||||
}
|
||||
}
|
||||
|
||||
float getAutomaticScreenBrightness() {
|
||||
if (mLastSensorValue < 0 || mLastSensorValue >= mSensorValueToLux.length
|
||||
|| (!mRegistered
|
||||
&& mClock.uptimeMillis() - mSensorDisableTime > SENSOR_VALUE_VALID_TIME_MILLIS)) {
|
||||
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
}
|
||||
|
||||
int lux = mSensorValueToLux[mLastSensorValue];
|
||||
if (lux < 0) {
|
||||
return PowerManager.BRIGHTNESS_INVALID_FLOAT;
|
||||
}
|
||||
|
||||
return mBrightnessMapper.getBrightness(lux);
|
||||
}
|
||||
|
||||
/** Dump current state */
|
||||
public void dump(PrintWriter pw) {
|
||||
pw.println("ScreenOffBrightnessSensorController:");
|
||||
IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
|
||||
idpw.increaseIndent();
|
||||
idpw.println("registered=" + mRegistered);
|
||||
idpw.println("lastSensorValue=" + mLastSensorValue);
|
||||
}
|
||||
|
||||
/** Functional interface for providing time. */
|
||||
@VisibleForTesting
|
||||
interface Clock {
|
||||
/**
|
||||
* Returns current time in milliseconds since boot, not counting time spent in deep sleep.
|
||||
*/
|
||||
long uptimeMillis();
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,9 @@
|
||||
<xs:element type="sensorDetails" name="lightSensor">
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<xs:element type="sensorDetails" name="screenOffBrightnessSensor">
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<xs:element type="sensorDetails" name="proxSensor">
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
@@ -109,6 +112,11 @@
|
||||
<xs:element type="thresholds" name="ambientBrightnessChangeThresholdsIdle" minOccurs="0" maxOccurs="1">
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
<!-- Table that translates sensor values from the screenOffBrightnessSensor
|
||||
to lux values; -1 means the lux reading is not available. -->
|
||||
<xs:element type="integer-array" name="screenOffBrightnessSensorValueToLux">
|
||||
<xs:annotation name="final"/>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
@@ -485,4 +493,10 @@
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="integer-array">
|
||||
<xs:sequence>
|
||||
<xs:element name="item" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:schema>
|
||||
|
||||
@@ -98,6 +98,8 @@ package com.android.server.display.config {
|
||||
method public final java.math.BigInteger getScreenBrightnessRampIncreaseMaxMillis();
|
||||
method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
|
||||
method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
|
||||
method public final com.android.server.display.config.SensorDetails getScreenOffBrightnessSensor();
|
||||
method public final com.android.server.display.config.IntegerArray getScreenOffBrightnessSensorValueToLux();
|
||||
method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling();
|
||||
method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds);
|
||||
method public final void setAmbientBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds);
|
||||
@@ -120,6 +122,8 @@ package com.android.server.display.config {
|
||||
method public final void setScreenBrightnessRampIncreaseMaxMillis(java.math.BigInteger);
|
||||
method public final void setScreenBrightnessRampSlowDecrease(java.math.BigDecimal);
|
||||
method public final void setScreenBrightnessRampSlowIncrease(java.math.BigDecimal);
|
||||
method public final void setScreenOffBrightnessSensor(com.android.server.display.config.SensorDetails);
|
||||
method public final void setScreenOffBrightnessSensorValueToLux(com.android.server.display.config.IntegerArray);
|
||||
method public final void setThermalThrottling(@NonNull com.android.server.display.config.ThermalThrottling);
|
||||
}
|
||||
|
||||
@@ -160,6 +164,11 @@ package com.android.server.display.config {
|
||||
method public final void setTransitionPoint_all(@NonNull java.math.BigDecimal);
|
||||
}
|
||||
|
||||
public class IntegerArray {
|
||||
ctor public IntegerArray();
|
||||
method public java.util.List<java.math.BigInteger> getItem();
|
||||
}
|
||||
|
||||
public class NitsMap {
|
||||
ctor public NitsMap();
|
||||
method public String getInterpolation();
|
||||
|
||||
@@ -161,6 +161,14 @@ public final class DisplayDeviceConfigTest {
|
||||
assertArrayEquals(new int[]{70, 80},
|
||||
mDisplayDeviceConfig.getHighAmbientBrightnessThresholds());
|
||||
|
||||
assertEquals("sensor_12345",
|
||||
mDisplayDeviceConfig.getScreenOffBrightnessSensor().type);
|
||||
assertEquals("Sensor 12345",
|
||||
mDisplayDeviceConfig.getScreenOffBrightnessSensor().name);
|
||||
|
||||
assertArrayEquals(new int[]{-1, 10, 20, 30, 40},
|
||||
mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux());
|
||||
|
||||
// Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping,
|
||||
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
|
||||
}
|
||||
@@ -232,6 +240,7 @@ public final class DisplayDeviceConfigTest {
|
||||
HIGH_BRIGHTNESS_THRESHOLD_OF_PEAK_REFRESH_RATE);
|
||||
assertArrayEquals(mDisplayDeviceConfig.getHighAmbientBrightnessThresholds(),
|
||||
HIGH_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE);
|
||||
|
||||
// Todo(brup): Add asserts for BrightnessThrottlingData, DensityMapping,
|
||||
// HighBrightnessModeData AmbientLightSensor, RefreshRateLimitations and ProximitySensor.
|
||||
}
|
||||
@@ -283,6 +292,10 @@ public final class DisplayDeviceConfigTest {
|
||||
+ "<thermalStatusLimit>light</thermalStatusLimit>\n"
|
||||
+ "<allowInLowPowerMode>false</allowInLowPowerMode>\n"
|
||||
+ "</highBrightnessMode>\n"
|
||||
+ "<screenOffBrightnessSensor>\n"
|
||||
+ "<type>sensor_12345</type>\n"
|
||||
+ "<name>Sensor 12345</name>\n"
|
||||
+ "</screenOffBrightnessSensor>\n"
|
||||
+ "<ambientBrightnessChangeThresholds>\n"
|
||||
+ "<brighteningThresholds>\n"
|
||||
+ "<minimum>10</minimum>\n"
|
||||
@@ -467,6 +480,13 @@ public final class DisplayDeviceConfigTest {
|
||||
+ "</blockingZoneThreshold>\n"
|
||||
+ "</higherBlockingZoneConfigs>\n"
|
||||
+ "</refreshRate>\n"
|
||||
+ "<screenOffBrightnessSensorValueToLux>\n"
|
||||
+ "<item>-1</item>\n"
|
||||
+ "<item>10</item>\n"
|
||||
+ "<item>20</item>\n"
|
||||
+ "<item>30</item>\n"
|
||||
+ "<item>40</item>\n"
|
||||
+ "</screenOffBrightnessSensorValueToLux>\n"
|
||||
+ "</displayConfiguration>\n";
|
||||
}
|
||||
|
||||
@@ -544,6 +564,7 @@ public final class DisplayDeviceConfigTest {
|
||||
when(mResources.getIntArray(
|
||||
R.array.config_highAmbientBrightnessThresholdsOfFixedRefreshRate))
|
||||
.thenReturn(HIGH_AMBIENT_THRESHOLD_OF_PEAK_REFRESH_RATE);
|
||||
|
||||
mDisplayDeviceConfig = DisplayDeviceConfig.create(mContext, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.display;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.server.testutils.OffsettableClock;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ScreenOffBrightnessSensorControllerTest {
|
||||
|
||||
private static final int[] SENSOR_TO_LUX = new int[]{-1, 10, 20, 30, 40};
|
||||
|
||||
private ScreenOffBrightnessSensorController mController;
|
||||
private OffsettableClock mClock;
|
||||
private Sensor mLightSensor;
|
||||
|
||||
@Mock SensorManager mSensorManager;
|
||||
@Mock Handler mNoOpHandler;
|
||||
@Mock BrightnessMappingStrategy mBrightnessMappingStrategy;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
|
||||
mClock = new OffsettableClock.Stopped();
|
||||
mLightSensor = TestUtils.createSensor(Sensor.TYPE_LIGHT, "Light Sensor");
|
||||
mController = new ScreenOffBrightnessSensorController(
|
||||
mSensorManager,
|
||||
mLightSensor,
|
||||
mNoOpHandler,
|
||||
mClock::now,
|
||||
SENSOR_TO_LUX,
|
||||
mBrightnessMappingStrategy
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBrightness() throws Exception {
|
||||
when(mSensorManager.registerListener(any(SensorEventListener.class), eq(mLightSensor),
|
||||
eq(SensorManager.SENSOR_DELAY_NORMAL), any(Handler.class)))
|
||||
.thenReturn(true);
|
||||
mController.setLightSensorEnabled(true);
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
|
||||
eq(SensorManager.SENSOR_DELAY_NORMAL), any(Handler.class));
|
||||
SensorEventListener listener = listenerCaptor.getValue();
|
||||
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
|
||||
assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
|
||||
mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
int sensorValue = 1;
|
||||
float brightness = 0.2f;
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, sensorValue));
|
||||
when(mBrightnessMappingStrategy.getBrightness(SENSOR_TO_LUX[sensorValue]))
|
||||
.thenReturn(brightness);
|
||||
assertEquals(brightness, mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
sensorValue = 2;
|
||||
brightness = 0.4f;
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, sensorValue));
|
||||
when(mBrightnessMappingStrategy.getBrightness(SENSOR_TO_LUX[sensorValue]))
|
||||
.thenReturn(brightness);
|
||||
assertEquals(brightness, mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
sensorValue = 3;
|
||||
brightness = 0.6f;
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, sensorValue));
|
||||
when(mBrightnessMappingStrategy.getBrightness(SENSOR_TO_LUX[sensorValue]))
|
||||
.thenReturn(brightness);
|
||||
assertEquals(brightness, mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
sensorValue = 4;
|
||||
brightness = 0.8f;
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, sensorValue));
|
||||
when(mBrightnessMappingStrategy.getBrightness(SENSOR_TO_LUX[sensorValue]))
|
||||
.thenReturn(brightness);
|
||||
assertEquals(brightness, mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
sensorValue = 5;
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, sensorValue));
|
||||
assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
|
||||
mController.getAutomaticScreenBrightness(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSensorValueValidTime() throws Exception {
|
||||
when(mSensorManager.registerListener(any(SensorEventListener.class), eq(mLightSensor),
|
||||
eq(SensorManager.SENSOR_DELAY_NORMAL), any(Handler.class)))
|
||||
.thenReturn(true);
|
||||
mController.setLightSensorEnabled(true);
|
||||
ArgumentCaptor<SensorEventListener> listenerCaptor =
|
||||
ArgumentCaptor.forClass(SensorEventListener.class);
|
||||
verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
|
||||
eq(SensorManager.SENSOR_DELAY_NORMAL), any(Handler.class));
|
||||
SensorEventListener listener = listenerCaptor.getValue();
|
||||
|
||||
listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 1));
|
||||
mController.setLightSensorEnabled(false);
|
||||
assertNotEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
|
||||
mController.getAutomaticScreenBrightness(), 0);
|
||||
|
||||
mClock.fastForward(2000);
|
||||
mController.setLightSensorEnabled(false);
|
||||
assertEquals(PowerManager.BRIGHTNESS_INVALID_FLOAT,
|
||||
mController.getAutomaticScreenBrightness(), 0);
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ import java.lang.reflect.Method;
|
||||
|
||||
public final class TestUtils {
|
||||
|
||||
public static SensorEvent createSensorEvent(Sensor sensor, int lux) throws Exception {
|
||||
public static SensorEvent createSensorEvent(Sensor sensor, int value) throws Exception {
|
||||
final Constructor<SensorEvent> constructor =
|
||||
SensorEvent.class.getDeclaredConstructor(int.class);
|
||||
constructor.setAccessible(true);
|
||||
final SensorEvent event = constructor.newInstance(1);
|
||||
event.sensor = sensor;
|
||||
event.values[0] = lux;
|
||||
event.values[0] = value;
|
||||
event.timestamp = SystemClock.elapsedRealtimeNanos();
|
||||
return event;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user