Merge changes from topic "b200851199" into sc-qpr1-dev

* changes:
  Make DisplayModeDirector aware of whether HBM is active
  Change DisplayModeDirector's brightness source to DisplayListener
This commit is contained in:
Daniel Solomon
2021-10-05 22:44:18 +00:00
committed by Android (Google) Code Review
6 changed files with 308 additions and 125 deletions

View File

@@ -60,12 +60,18 @@ public final class BrightnessInfo implements Parcelable {
/** Brightness */
public final float brightness;
/** Brightness after {@link DisplayPowerController} adjustments */
public final float adjustedBrightness;
/** Current minimum supported brightness. */
public final float brightnessMinimum;
/** Current maximum supported brightness. */
public final float brightnessMaximum;
/** Brightness values greater than this point are only used in High Brightness Mode. */
public final float highBrightnessTransitionPoint;
/**
* Current state of high brightness mode.
* Can be any of HIGH_BRIGHTNESS_MODE_* values.
@@ -73,11 +79,20 @@ public final class BrightnessInfo implements Parcelable {
public final int highBrightnessMode;
public BrightnessInfo(float brightness, float brightnessMinimum, float brightnessMaximum,
@HighBrightnessMode int highBrightnessMode) {
@HighBrightnessMode int highBrightnessMode, float highBrightnessTransitionPoint) {
this(brightness, brightness, brightnessMinimum, brightnessMaximum, highBrightnessMode,
highBrightnessTransitionPoint);
}
public BrightnessInfo(float brightness, float adjustedBrightness, float brightnessMinimum,
float brightnessMaximum, @HighBrightnessMode int highBrightnessMode,
float highBrightnessTransitionPoint) {
this.brightness = brightness;
this.adjustedBrightness = adjustedBrightness;
this.brightnessMinimum = brightnessMinimum;
this.brightnessMaximum = brightnessMaximum;
this.highBrightnessMode = highBrightnessMode;
this.highBrightnessTransitionPoint = highBrightnessTransitionPoint;
}
/**
@@ -103,9 +118,11 @@ public final class BrightnessInfo implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeFloat(brightness);
dest.writeFloat(adjustedBrightness);
dest.writeFloat(brightnessMinimum);
dest.writeFloat(brightnessMaximum);
dest.writeInt(highBrightnessMode);
dest.writeFloat(highBrightnessTransitionPoint);
}
public static final @android.annotation.NonNull Creator<BrightnessInfo> CREATOR =
@@ -123,9 +140,11 @@ public final class BrightnessInfo implements Parcelable {
private BrightnessInfo(Parcel source) {
brightness = source.readFloat();
adjustedBrightness = source.readFloat();
brightnessMinimum = source.readFloat();
brightnessMaximum = source.readFloat();
highBrightnessMode = source.readInt();
highBrightnessTransitionPoint = source.readFloat();
}
}

View File

@@ -17,6 +17,7 @@
package com.android.server.display;
import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
import static android.os.PowerManager.BRIGHTNESS_INVALID;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,6 +41,7 @@ import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -60,6 +62,7 @@ import android.view.DisplayInfo;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.display.utils.AmbientFilter;
@@ -155,7 +158,7 @@ public class DisplayModeDirector {
mAppRequestObserver = new AppRequestObserver();
mSettingsObserver = new SettingsObserver(context, handler);
mDisplayObserver = new DisplayObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler);
mBrightnessObserver = new BrightnessObserver(context, handler, injector);
mUdfpsObserver = new UdfpsObserver();
final BallotBox ballotBox = (displayId, priority, vote) -> {
synchronized (mLock) {
@@ -1427,8 +1430,6 @@ public class DisplayModeDirector {
@Override
public void onDisplayChanged(int displayId) {
updateDisplayModes(displayId);
// TODO: Break the coupling between DisplayObserver and BrightnessObserver.
mBrightnessObserver.onDisplayChanged(displayId);
}
private void updateDisplayModes(int displayId) {
@@ -1465,7 +1466,7 @@ public class DisplayModeDirector {
* {@link R.array#config_ambientThresholdsOfPeakRefreshRate}.
*/
@VisibleForTesting
public class BrightnessObserver extends ContentObserver {
public class BrightnessObserver implements DisplayManager.DisplayListener {
private final static int LIGHT_SENSOR_RATE_MS = 250;
private int[] mLowDisplayBrightnessThresholds;
private int[] mLowAmbientBrightnessThresholds;
@@ -1488,6 +1489,8 @@ public class DisplayModeDirector {
private int mBrightness = -1;
private final Context mContext;
private final Injector mInjector;
private final Handler mHandler;
// Enable light sensor only when mShouldObserveAmbientLowChange is true or
// mShouldObserveAmbientHighChange is true, screen is on, peak refresh rate
@@ -1500,9 +1503,11 @@ public class DisplayModeDirector {
private int mRefreshRateInLowZone;
private int mRefreshRateInHighZone;
BrightnessObserver(Context context, Handler handler) {
super(handler);
BrightnessObserver(Context context, Handler handler, Injector injector) {
mContext = context;
mHandler = handler;
mInjector = injector;
mLowDisplayBrightnessThresholds = context.getResources().getIntArray(
R.array.config_brightnessThresholdsOfPeakRefreshRate);
mLowAmbientBrightnessThresholds = context.getResources().getIntArray(
@@ -1569,8 +1574,7 @@ public class DisplayModeDirector {
public void observe(SensorManager sensorManager) {
mSensorManager = sensorManager;
final ContentResolver cr = mContext.getContentResolver();
mBrightness = Settings.System.getIntForUser(cr,
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
mBrightness = getBrightness(Display.DEFAULT_DISPLAY);
// DeviceConfig is accessible after system ready.
int[] lowDisplayBrightnessThresholds =
@@ -1603,6 +1607,10 @@ public class DisplayModeDirector {
restartObserver();
mDeviceConfigDisplaySettings.startListening();
mInjector.registerDisplayListener(this, mHandler,
DisplayManager.EVENT_FLAG_DISPLAY_CHANGED |
DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS);
}
public void setLoggingEnabled(boolean loggingEnabled) {
@@ -1718,28 +1726,30 @@ public class DisplayModeDirector {
}
}
@Override
public void onDisplayAdded(int displayId) {}
@Override
public void onDisplayRemoved(int displayId) {}
@Override
public void onDisplayChanged(int displayId) {
if (displayId == Display.DEFAULT_DISPLAY) {
updateDefaultDisplayState();
}
}
@Override
public void onChange(boolean selfChange, Uri uri, int userId) {
synchronized (mLock) {
final ContentResolver cr = mContext.getContentResolver();
int brightness = Settings.System.getIntForUser(cr,
Settings.System.SCREEN_BRIGHTNESS, -1 /*default*/, cr.getUserId());
if (brightness != mBrightness) {
mBrightness = brightness;
onBrightnessChangedLocked();
// We don't support multiple display blocking zones yet, so only handle
// brightness changes for the default display for now.
int brightness = getBrightness(displayId);
synchronized (mLock) {
if (brightness != mBrightness) {
mBrightness = brightness;
onBrightnessChangedLocked();
}
}
}
}
private void restartObserver() {
final ContentResolver cr = mContext.getContentResolver();
if (mRefreshRateInLowZone > 0) {
mShouldObserveDisplayLowChange = hasValidThreshold(
mLowDisplayBrightnessThresholds);
@@ -1760,15 +1770,6 @@ public class DisplayModeDirector {
mShouldObserveAmbientHighChange = false;
}
if (mShouldObserveDisplayLowChange || mShouldObserveDisplayHighChange) {
// Content Service does not check if an listener has already been registered.
// To ensure only one listener is registered, force an unregistration first.
mInjector.unregisterBrightnessObserver(cr, this);
mInjector.registerBrightnessObserver(cr, this);
} else {
mInjector.unregisterBrightnessObserver(cr, this);
}
if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
Resources resources = mContext.getResources();
String lightSensorType = resources.getString(
@@ -1968,6 +1969,15 @@ public class DisplayModeDirector {
return mDefaultDisplayState == Display.STATE_ON;
}
private int getBrightness(int displayId) {
final BrightnessInfo info = mInjector.getBrightnessInfo(displayId);
if (info != null) {
return BrightnessSynchronizer.brightnessFloatToInt(info.adjustedBrightness);
}
return BRIGHTNESS_INVALID;
}
private final class LightSensorEventListener implements SensorEventListener {
final private static int INJECT_EVENTS_INTERVAL_MS = LIGHT_SENSOR_RATE_MS;
private float mLastSensorData;
@@ -2283,6 +2293,7 @@ public class DisplayModeDirector {
private final BallotBox mBallotBox;
private final Handler mHandler;
private final SparseIntArray mHbmMode = new SparseIntArray();
private final SparseBooleanArray mHbmActive = new SparseBooleanArray();
private final Injector mInjector;
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
private int mRefreshRateInHbmSunlight;
@@ -2351,6 +2362,7 @@ public class DisplayModeDirector {
public void onDisplayRemoved(int displayId) {
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
mHbmMode.delete(displayId);
mHbmActive.delete(displayId);
}
@Override
@@ -2360,12 +2372,17 @@ public class DisplayModeDirector {
// Display no longer there. Assume we'll get an onDisplayRemoved very soon.
return;
}
final int hbmMode = info.highBrightnessMode;
if (hbmMode == mHbmMode.get(displayId)) {
final boolean isHbmActive = hbmMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF &&
info.adjustedBrightness > info.highBrightnessTransitionPoint;
if (hbmMode == mHbmMode.get(displayId) &&
isHbmActive == mHbmActive.get(displayId)) {
// no change, ignore.
return;
}
mHbmMode.put(displayId, hbmMode);
mHbmActive.put(displayId, isHbmActive);
recalculateVotesForDisplay(displayId);
}
@@ -2379,28 +2396,36 @@ public class DisplayModeDirector {
}
private void recalculateVotesForDisplay(int displayId) {
final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
Vote vote = null;
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
vote = Vote.forRefreshRates(limitation.range.min, limitation.range.max);
break;
if (mHbmActive.get(displayId, false)) {
final int hbmMode =
mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
mDisplayManagerInternal.getRefreshRateLimitations(displayId);
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
vote = Vote.forRefreshRates(limitation.range.min,
limitation.range.max);
break;
}
}
}
} else if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR &&
mRefreshRateInHbmHdr > 0) {
// HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
// a vote from Device properties
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
} else {
Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId);
}
}
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
&& mRefreshRateInHbmHdr > 0) {
vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
}
mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
}
@@ -2408,6 +2433,7 @@ public class DisplayModeDirector {
void dumpLocked(PrintWriter pw) {
pw.println(" HbmObserver");
pw.println(" mHbmMode: " + mHbmMode);
pw.println(" mHbmActive: " + mHbmActive);
pw.println(" mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight);
pw.println(" mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr);
}
@@ -2630,19 +2656,11 @@ public class DisplayModeDirector {
}
interface Injector {
// TODO: brightnessfloat: change this to the float setting
Uri DISPLAY_BRIGHTNESS_URI = Settings.System.getUriFor(Settings.System.SCREEN_BRIGHTNESS);
Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE);
@NonNull
DeviceConfigInterface getDeviceConfig();
void registerBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
void unregisterBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer);
@@ -2671,19 +2689,6 @@ public class DisplayModeDirector {
return DeviceConfigInterface.REAL;
}
@Override
public void registerBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.registerContentObserver(DISPLAY_BRIGHTNESS_URI, false /*notifyDescendants*/,
observer, UserHandle.USER_SYSTEM);
}
@Override
public void unregisterBrightnessObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {
cr.unregisterContentObserver(observer);
}
@Override
public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr,
@NonNull ContentObserver observer) {

View File

@@ -1259,10 +1259,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
putScreenBrightnessSetting(brightnessState, /* updateCurrent */ true);
}
// We save the brightness info *after* the brightness setting has been changed so that
// the brightness info reflects the latest value.
saveBrightnessInfo(getScreenBrightnessSetting());
// Apply dimming by at least some minimum amount when user activity
// timeout is about to expire.
if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
@@ -1393,6 +1389,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
hadUserBrightnessPoint);
}
// We save the brightness info *after* the brightness setting has been changed and
// adjustments made so that the brightness info reflects the latest value.
saveBrightnessInfo(getScreenBrightnessSetting(), animateValue);
} else {
saveBrightnessInfo(getScreenBrightnessSetting());
}
// Log any changes to what is currently driving the brightness setting.
@@ -1509,18 +1510,27 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
synchronized (mCachedBrightnessInfo) {
return new BrightnessInfo(
mCachedBrightnessInfo.brightness,
mCachedBrightnessInfo.adjustedBrightness,
mCachedBrightnessInfo.brightnessMin,
mCachedBrightnessInfo.brightnessMax,
mCachedBrightnessInfo.hbmMode);
mCachedBrightnessInfo.hbmMode,
mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
}
private void saveBrightnessInfo(float brightness) {
saveBrightnessInfo(brightness, brightness);
}
private void saveBrightnessInfo(float brightness, float adjustedBrightness) {
synchronized (mCachedBrightnessInfo) {
mCachedBrightnessInfo.brightness = brightness;
mCachedBrightnessInfo.adjustedBrightness = adjustedBrightness;
mCachedBrightnessInfo.brightnessMin = mHbmController.getCurrentBrightnessMin();
mCachedBrightnessInfo.brightnessMax = mHbmController.getCurrentBrightnessMax();
mCachedBrightnessInfo.hbmMode = mHbmController.getHighBrightnessMode();
mCachedBrightnessInfo.highBrightnessTransitionPoint =
mHbmController.getTransitionPoint();
}
}
@@ -2195,6 +2205,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mSkipScreenOnBrightnessRamp=" + mSkipScreenOnBrightnessRamp);
pw.println(" mColorFadeFadesConfig=" + mColorFadeFadesConfig);
pw.println(" mColorFadeEnabled=" + mColorFadeEnabled);
synchronized (mCachedBrightnessInfo) {
pw.println(" mCachedBrightnessInfo.brightness=" + mCachedBrightnessInfo.brightness);
pw.println(" mCachedBrightnessInfo.adjustedBrightness=" +
mCachedBrightnessInfo.adjustedBrightness);
pw.println(" mCachedBrightnessInfo.brightnessMin=" +
mCachedBrightnessInfo.brightnessMin);
pw.println(" mCachedBrightnessInfo.brightnessMax=" +
mCachedBrightnessInfo.brightnessMax);
pw.println(" mCachedBrightnessInfo.hbmMode=" + mCachedBrightnessInfo.hbmMode);
pw.println(" mCachedBrightnessInfo.highBrightnessTransitionPoint=" +
mCachedBrightnessInfo.highBrightnessTransitionPoint);
}
pw.println(" mDisplayBlanksAfterDozeConfig=" + mDisplayBlanksAfterDozeConfig);
pw.println(" mBrightnessBucketsInDozeConfig=" + mBrightnessBucketsInDozeConfig);
@@ -2606,8 +2628,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
static class CachedBrightnessInfo {
public float brightness;
public float adjustedBrightness;
public float brightnessMin;
public float brightnessMax;
public int hbmMode;
public float highBrightnessTransitionPoint;
}
}

View File

@@ -59,6 +59,9 @@ class HighBrightnessModeController {
private static final float HDR_PERCENT_OF_SCREEN_REQUIRED = 0.50f;
@VisibleForTesting
static final float HBM_TRANSITION_POINT_INVALID = Float.POSITIVE_INFINITY;
private final float mBrightnessMin;
private final float mBrightnessMax;
private final Handler mHandler;
@@ -214,6 +217,14 @@ class HighBrightnessModeController {
return mHbmMode;
}
float getTransitionPoint() {
if (deviceSupportsHbm()) {
return mHbmData.transitionPoint;
} else {
return HBM_TRANSITION_POINT_INVALID;
}
}
void stop() {
registerHdrListener(null /*displayToken*/);
mSkinThermalStatusObserver.stopObserving();

View File

@@ -26,6 +26,7 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_R
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE;
import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
import static com.google.common.truth.Truth.assertThat;
@@ -74,6 +75,7 @@ import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.Preconditions;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.internal.util.test.FakeSettingsProviderRule;
@@ -110,6 +112,7 @@ public class DisplayModeDirectorTest {
private static final boolean DEBUG = false;
private static final float FLOAT_TOLERANCE = 0.01f;
private static final int DISPLAY_ID = 0;
private static final float TRANSITION_POINT = 0.763f;
private Context mContext;
private FakesInjector mInjector;
@@ -751,19 +754,27 @@ public class DisplayModeDirectorTest {
director.start(sensorManager);
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor<DisplayListener> displayListenerCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> sensorListenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
Mockito.verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
.registerListener(
listenerCaptor.capture(),
sensorListenerCaptor.capture(),
eq(lightSensor),
anyInt(),
any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
SensorEventListener sensorListener = sensorListenerCaptor.getValue();
setBrightness(10);
setBrightness(10, 10, displayListener);
// Sensor reads 20 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 90 /*fps*/);
@@ -771,9 +782,11 @@ public class DisplayModeDirectorTest {
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
setBrightness(125);
// We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this
// parameter to the necessary threshold
setBrightness(10, 125, displayListener);
// Sensor reads 1000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
@@ -799,6 +812,14 @@ public class DisplayModeDirectorTest {
director.start(sensorManager);
ArgumentCaptor<DisplayListener> displayListenerCaptor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(displayListenerCaptor.capture(),
any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
| DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS));
DisplayListener displayListener = displayListenerCaptor.getValue();
ArgumentCaptor<SensorEventListener> listenerCaptor =
ArgumentCaptor.forClass(SensorEventListener.class);
verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
@@ -807,20 +828,22 @@ public class DisplayModeDirectorTest {
eq(lightSensor),
anyInt(),
any(Handler.class));
SensorEventListener listener = listenerCaptor.getValue();
SensorEventListener sensorListener = listenerCaptor.getValue();
setBrightness(100);
setBrightness(100, 100, displayListener);
// Sensor reads 2000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNull();
setBrightness(255);
// We expect DisplayModeDirector to act on BrightnessInfo.adjustedBrightness; set only this
// parameter to the necessary threshold
setBrightness(100, 255, displayListener);
// Sensor reads 9000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 60 /*fps*/);
@@ -1435,16 +1458,58 @@ public class DisplayModeDirectorTest {
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HBM
// Turn on HBM, with brightness in the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR));
new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, hbmRefreshRate);
// Turn on HBM, with brightness below the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HBM, with brightness in the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(TRANSITION_POINT + FLOAT_TOLERANCE, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, hbmRefreshRate);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HBM, with brightness below the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(TRANSITION_POINT - FLOAT_TOLERANCE, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.45f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1514,7 +1579,8 @@ public class DisplayModeDirectorTest {
// Turn on HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, initialRefreshRate);
@@ -1531,14 +1597,16 @@ public class DisplayModeDirectorTest {
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn HBM on again and ensure the updated vote value stuck
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, updatedRefreshRate);
@@ -1553,7 +1621,8 @@ public class DisplayModeDirectorTest {
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1584,14 +1653,82 @@ public class DisplayModeDirectorTest {
// Turn on HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF));
new BrightnessInfo(0.43f, 0.1f, 0.8f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
}
@Test
public void testHbmVoting_HbmUnsupported() {
DisplayModeDirector director =
createDirectorFromRefreshRateArray(new float[] {60.0f, 90.0f}, 0);
director.start(createMockSensorManager());
ArgumentCaptor<DisplayListener> captor =
ArgumentCaptor.forClass(DisplayListener.class);
verify(mInjector).registerDisplayListener(captor.capture(), any(Handler.class),
eq(DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
| DisplayManager.EVENT_FLAG_DISPLAY_REMOVED));
DisplayListener listener = captor.getValue();
// Specify Limitation
when(mDisplayManagerInternalMock.getRefreshRateLimitations(DISPLAY_ID)).thenReturn(
List.of(new RefreshRateLimitation(
DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE,
60.0f, 60.0f)));
// Verify that there is no HBM vote initially
Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HBM when HBM is supported; expect a valid transition point and a vote.
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, 60.0f);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on Sunlight HBM when HBM is unsupported; expect an invalid transition point and
// no vote.
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
HBM_TRANSITION_POINT_INVALID));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn on HDR HBM when HBM is unsupported; expect an invalid transition point and
// no vote.
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR,
HBM_TRANSITION_POINT_INVALID));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertNull(vote);
@@ -1600,7 +1737,7 @@ public class DisplayModeDirectorTest {
private void setHbmAndAssertRefreshRate(
DisplayModeDirector director, DisplayListener listener, int mode, float rr) {
when(mInjector.getBrightnessInfo(DISPLAY_ID))
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode));
.thenReturn(new BrightnessInfo(1.0f, 0.0f, 1.0f, mode, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
final Vote vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
@@ -1679,7 +1816,8 @@ public class DisplayModeDirectorTest {
// Turn on HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT));
new BrightnessInfo(1.0f, 0.0f, 1.0f, BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT,
TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
assertVoteForRefreshRate(vote, 60.f);
@@ -1834,11 +1972,14 @@ public class DisplayModeDirectorTest {
}
}
private void setBrightness(int brightness) {
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS,
brightness);
mInjector.notifyBrightnessChanged();
waitForIdleSync();
private void setBrightness(int brightness, int adjustedBrightness, DisplayListener listener) {
float floatBri = BrightnessSynchronizer.brightnessIntToFloat(brightness);
float floatAdjBri = BrightnessSynchronizer.brightnessIntToFloat(adjustedBrightness);
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
new BrightnessInfo(floatBri, floatAdjBri, 0.0f, 1.0f,
BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF, TRANSITION_POINT));
listener.onDisplayChanged(DISPLAY_ID);
}
private void setPeakRefreshRate(float fps) {
@@ -1901,27 +2042,6 @@ public class DisplayModeDirectorTest {
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) {

View File

@@ -20,6 +20,8 @@ import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR;
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
import static android.hardware.display.BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT;
import static com.android.server.display.HighBrightnessModeController.HBM_TRANSITION_POINT_INVALID;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.spy;
@@ -124,6 +126,7 @@ public class HighBrightnessModeControllerTest {
mInjectorMock, mHandler, DISPLAY_WIDTH, DISPLAY_HEIGHT, mDisplayToken, DEFAULT_MIN,
DEFAULT_MAX, null, () -> {}, mContextSpy);
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
}
@Test
@@ -135,6 +138,7 @@ public class HighBrightnessModeControllerTest {
hbmc.setAutoBrightnessEnabled(true);
hbmc.onAmbientLuxChange(MINIMUM_LUX - 1); // below allowed range
assertState(hbmc, DEFAULT_MIN, DEFAULT_MAX, HIGH_BRIGHTNESS_MODE_OFF);
assertEquals(hbmc.getTransitionPoint(), HBM_TRANSITION_POINT_INVALID, 0.0f);
}
@Test