Merge "Moving BrightnessInfo and BrightnessReason outside of DisplayPowerController to have the support of declaring the brightness relevant states in DisplayPowerController agnostic fashion."

This commit is contained in:
Rupesh Bansal
2022-07-26 15:39:51 +00:00
committed by Android (Google) Code Review
6 changed files with 661 additions and 264 deletions

View File

@@ -46,7 +46,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.EventLogTags;
import com.android.server.display.DisplayPowerController.BrightnessEvent;
import com.android.server.display.brightness.BrightnessEvent;
import java.io.PrintWriter;
@@ -337,14 +337,15 @@ class AutomaticBrightnessController {
float getAutomaticScreenBrightness(BrightnessEvent brightnessEvent) {
if (brightnessEvent != null) {
brightnessEvent.lux =
mAmbientLuxValid ? mAmbientLux : PowerManager.BRIGHTNESS_INVALID_FLOAT;
brightnessEvent.preThresholdLux = mPreThresholdLux;
brightnessEvent.preThresholdBrightness = mPreThresholdBrightness;
brightnessEvent.recommendedBrightness = mScreenAutoBrightness;
brightnessEvent.flags |= (!mAmbientLuxValid ? BrightnessEvent.FLAG_INVALID_LUX : 0)
brightnessEvent.setLux(
mAmbientLuxValid ? mAmbientLux : PowerManager.BRIGHTNESS_INVALID_FLOAT);
brightnessEvent.setPreThresholdLux(mPreThresholdLux);
brightnessEvent.setPreThresholdBrightness(mPreThresholdBrightness);
brightnessEvent.setRecommendedBrightness(mScreenAutoBrightness);
brightnessEvent.setFlags(brightnessEvent.getFlags()
| (!mAmbientLuxValid ? BrightnessEvent.FLAG_INVALID_LUX : 0)
| (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE
? BrightnessEvent.FLAG_DOZE_SCALE : 0);
? BrightnessEvent.FLAG_DOZE_SCALE : 0));
}
if (!mAmbientLuxValid) {

View File

@@ -67,6 +67,8 @@ import com.android.internal.util.RingBuffer;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
import com.android.server.display.utils.SensorUtils;
@@ -76,7 +78,6 @@ import com.android.server.display.whitebalance.DisplayWhiteBalanceSettings;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
import java.util.Objects;
/**
* Controls the power state of the display.
@@ -1430,7 +1431,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// we broadcast this change through setting.
final float unthrottledBrightnessState = brightnessState;
if (mBrightnessThrottler.isThrottled()) {
mTempBrightnessEvent.thermalMax = mBrightnessThrottler.getBrightnessCap();
mTempBrightnessEvent.setThermalMax(mBrightnessThrottler.getBrightnessCap());
brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
if (!mAppliedThrottling) {
@@ -1551,8 +1552,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// TODO(b/216365040): The decision to prevent HBM for HDR in low power mode should be
// done in HighBrightnessModeController.
if (mHbmController.getHighBrightnessMode() == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
&& ((mBrightnessReason.modifier & BrightnessReason.MODIFIER_DIMMED) == 0
|| (mBrightnessReason.modifier & BrightnessReason.MODIFIER_LOW_POWER) == 0)) {
&& ((mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_DIMMED) == 0
|| (mBrightnessReason.getModifier() & BrightnessReason.MODIFIER_LOW_POWER)
== 0)) {
// We want to scale HDR brightness level with the SDR level
animateValue = mHbmController.getHdrBrightnessValue();
}
@@ -1615,7 +1617,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
+ mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
+ "', previous reason: '" + mBrightnessReason + "'.");
mBrightnessReason.set(mBrightnessReasonTemp);
} else if (mBrightnessReasonTemp.reason == BrightnessReason.REASON_MANUAL
} else if (mBrightnessReasonTemp.getReason() == BrightnessReason.REASON_MANUAL
&& userSetBrightnessChanged) {
Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment.");
}
@@ -1624,17 +1626,19 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Log brightness events when a detail of significance has changed. Generally this is the
// brightness itself changing, but also includes data like HBM cap, thermal throttling
// brightness cap, RBC state, etc.
mTempBrightnessEvent.time = System.currentTimeMillis();
mTempBrightnessEvent.brightness = brightnessState;
mTempBrightnessEvent.reason.set(mBrightnessReason);
mTempBrightnessEvent.hbmMax = mHbmController.getCurrentBrightnessMax();
mTempBrightnessEvent.hbmMode = mHbmController.getHighBrightnessMode();
mTempBrightnessEvent.flags |= (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0);
mTempBrightnessEvent.setTime(System.currentTimeMillis());
mTempBrightnessEvent.setBrightness(brightnessState);
mTempBrightnessEvent.setReason(mBrightnessReason);
mTempBrightnessEvent.setHbmMax(mHbmController.getCurrentBrightnessMax());
mTempBrightnessEvent.setHbmMode(mHbmController.getHighBrightnessMode());
mTempBrightnessEvent.setFlags(mTempBrightnessEvent.getFlags()
| (mIsRbcActive ? BrightnessEvent.FLAG_RBC : 0));
// Temporary is what we use during slider interactions. We avoid logging those so that
// we don't spam logcat when the slider is being used.
boolean tempToTempTransition =
mTempBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY
&& mLastBrightnessEvent.reason.reason == BrightnessReason.REASON_TEMPORARY;
mTempBrightnessEvent.getReason().getReason() == BrightnessReason.REASON_TEMPORARY
&& mLastBrightnessEvent.getReason().getReason()
== BrightnessReason.REASON_TEMPORARY;
if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
|| brightnessAdjustmentFlags != 0) {
mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
@@ -1642,8 +1646,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Adjustment flags (and user-set flag) only get added after the equality checks since
// they are transient.
newEvent.adjustmentFlags = brightnessAdjustmentFlags;
newEvent.flags |= (userSetBrightnessChanged ? BrightnessEvent.FLAG_USER_SET : 0);
newEvent.setAdjustmentFlags(brightnessAdjustmentFlags);
newEvent.setFlags(newEvent.getFlags() | (userSetBrightnessChanged
? BrightnessEvent.FLAG_USER_SET : 0));
Slog.i(TAG, newEvent.toString(/* includeTime= */ false));
if (mBrightnessEventRingBuffer != null) {
@@ -2734,117 +2739,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
class BrightnessEvent {
static final int FLAG_RBC = 0x1;
static final int FLAG_INVALID_LUX = 0x2;
static final int FLAG_DOZE_SCALE = 0x3;
static final int FLAG_USER_SET = 0x4;
public final BrightnessReason reason = new BrightnessReason();
public int displayId;
public float lux;
public float preThresholdLux;
public long time;
public float brightness;
public float recommendedBrightness;
public float preThresholdBrightness;
public float hbmMax;
public float thermalMax;
public int hbmMode;
public int flags;
public int adjustmentFlags;
BrightnessEvent(BrightnessEvent that) {
copyFrom(that);
}
BrightnessEvent(int displayId) {
this.displayId = displayId;
reset();
}
void copyFrom(BrightnessEvent that) {
displayId = that.displayId;
time = that.time;
lux = that.lux;
preThresholdLux = that.preThresholdLux;
brightness = that.brightness;
recommendedBrightness = that.recommendedBrightness;
preThresholdBrightness = that.preThresholdBrightness;
hbmMax = that.hbmMax;
thermalMax = that.thermalMax;
flags = that.flags;
hbmMode = that.hbmMode;
reason.set(that.reason);
adjustmentFlags = that.adjustmentFlags;
}
void reset() {
time = SystemClock.uptimeMillis();
brightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
recommendedBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
lux = 0;
preThresholdLux = 0;
preThresholdBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
hbmMax = PowerManager.BRIGHTNESS_MAX;
thermalMax = PowerManager.BRIGHTNESS_MAX;
flags = 0;
hbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
reason.set(null);
adjustmentFlags = 0;
}
boolean equalsMainData(BrightnessEvent that) {
// This equals comparison purposefully ignores time since it is regularly changing and
// we don't want to log a brightness event just because the time changed.
return displayId == that.displayId
&& Float.floatToRawIntBits(brightness)
== Float.floatToRawIntBits(that.brightness)
&& Float.floatToRawIntBits(recommendedBrightness)
== Float.floatToRawIntBits(that.recommendedBrightness)
&& Float.floatToRawIntBits(preThresholdBrightness)
== Float.floatToRawIntBits(that.preThresholdBrightness)
&& Float.floatToRawIntBits(lux) == Float.floatToRawIntBits(that.lux)
&& Float.floatToRawIntBits(preThresholdLux)
== Float.floatToRawIntBits(that.preThresholdLux)
&& Float.floatToRawIntBits(hbmMax) == Float.floatToRawIntBits(that.hbmMax)
&& hbmMode == that.hbmMode
&& Float.floatToRawIntBits(thermalMax)
== Float.floatToRawIntBits(that.thermalMax)
&& flags == that.flags
&& adjustmentFlags == that.adjustmentFlags
&& reason.equals(that.reason);
}
public String toString(boolean includeTime) {
return (includeTime ? TimeUtils.formatForLogging(time) + " - " : "")
+ "BrightnessEvent: "
+ "disp=" + displayId
+ ", brt=" + brightness + ((flags & FLAG_USER_SET) != 0 ? "(user_set)" : "")
+ ", rcmdBrt=" + recommendedBrightness
+ ", preBrt=" + preThresholdBrightness
+ ", lux=" + lux
+ ", preLux=" + preThresholdLux
+ ", hbmMax=" + hbmMax
+ ", hbmMode=" + BrightnessInfo.hbmToString(hbmMode)
+ ", thrmMax=" + thermalMax
+ ", flags=" + flagsToString()
+ ", reason=" + reason.toString(adjustmentFlags);
}
@Override
public String toString() {
return toString(/* includeTime */ true);
}
private String flagsToString() {
return ((flags & FLAG_USER_SET) != 0 ? "user_set " : "")
+ ((flags & FLAG_RBC) != 0 ? "rbc " : "")
+ ((flags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "")
+ ((flags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "");
}
}
private final class DisplayControllerHandler extends Handler {
public DisplayControllerHandler(Looper looper) {
@@ -2996,137 +2891,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
/**
* Stores data about why the brightness was changed. Made up of one main
* {@code BrightnessReason.REASON_*} reason and various {@code BrightnessReason.MODIFIER_*}
* modifiers.
*/
private final class BrightnessReason {
static final int REASON_UNKNOWN = 0;
static final int REASON_MANUAL = 1;
static final int REASON_DOZE = 2;
static final int REASON_DOZE_DEFAULT = 3;
static final int REASON_AUTOMATIC = 4;
static final int REASON_SCREEN_OFF = 5;
static final int REASON_VR = 6;
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 MODIFIER_DIMMED = 0x1;
static final int MODIFIER_LOW_POWER = 0x2;
static final int MODIFIER_HDR = 0x4;
static final int MODIFIER_THROTTLED = 0x8;
static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR
| MODIFIER_THROTTLED;
// ADJUSTMENT_*
// These things can happen at any point, even if the main brightness reason doesn't
// fundamentally change, so they're not stored.
// Auto-brightness adjustment factor changed
static final int ADJUSTMENT_AUTO_TEMP = 0x1;
// Temporary adjustment to the auto-brightness adjustment factor.
static final int ADJUSTMENT_AUTO = 0x2;
// One of REASON_*
public int reason;
// Any number of MODIFIER_*
public int modifier;
public void set(BrightnessReason other) {
setReason(other == null ? REASON_UNKNOWN : other.reason);
setModifier(other == null ? 0 : other.modifier);
}
public void setReason(int reason) {
if (reason < REASON_UNKNOWN || reason > REASON_MAX) {
Slog.w(TAG, "brightness reason out of bounds: " + reason);
} else {
this.reason = reason;
}
}
public void setModifier(int modifier) {
if ((modifier & ~MODIFIER_MASK) != 0) {
Slog.w(TAG, "brightness modifier out of bounds: 0x"
+ Integer.toHexString(modifier));
} else {
this.modifier = modifier;
}
}
public void addModifier(int modifier) {
setModifier(modifier | this.modifier);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BrightnessReason)) {
return false;
}
BrightnessReason other = (BrightnessReason) obj;
return other.reason == reason && other.modifier == modifier;
}
@Override
public int hashCode() {
return Objects.hash(reason, modifier);
}
@Override
public String toString() {
return toString(0);
}
public String toString(int adjustments) {
final StringBuilder sb = new StringBuilder();
sb.append(reasonToString(reason));
sb.append(" [");
if ((adjustments & ADJUSTMENT_AUTO_TEMP) != 0) {
sb.append(" temp_adj");
}
if ((adjustments & ADJUSTMENT_AUTO) != 0) {
sb.append(" auto_adj");
}
if ((modifier & MODIFIER_LOW_POWER) != 0) {
sb.append(" low_pwr");
}
if ((modifier & MODIFIER_DIMMED) != 0) {
sb.append(" dim");
}
if ((modifier & MODIFIER_HDR) != 0) {
sb.append(" hdr");
}
if ((modifier & MODIFIER_THROTTLED) != 0) {
sb.append(" throttled");
}
int strlen = sb.length();
if (sb.charAt(strlen - 1) == '[') {
sb.setLength(strlen - 2);
} else {
sb.append(" ]");
}
return sb.toString();
}
private String reasonToString(int reason) {
switch (reason) {
case REASON_MANUAL: return "manual";
case REASON_DOZE: return "doze";
case REASON_DOZE_DEFAULT: return "doze_default";
case REASON_AUTOMATIC: return "automatic";
case REASON_SCREEN_OFF: return "screen_off";
case REASON_VR: return "vr";
case REASON_OVERRIDE: return "override";
case REASON_TEMPORARY: return "temporary";
case REASON_BOOST: return "boost";
default: return Integer.toString(reason);
}
}
}
static class CachedBrightnessInfo {
public MutableFloat brightness = new MutableFloat(PowerManager.BRIGHTNESS_INVALID_FLOAT);
public MutableFloat adjustedBrightness =

View File

@@ -0,0 +1,262 @@
/*
* 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.brightness;
import android.hardware.display.BrightnessInfo;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.TimeUtils;
/**
* Represents a particular brightness change event.
*/
public final class BrightnessEvent {
public static final int FLAG_RBC = 0x1;
public static final int FLAG_INVALID_LUX = 0x2;
public static final int FLAG_DOZE_SCALE = 0x3;
public static final int FLAG_USER_SET = 0x4;
private BrightnessReason mReason = new BrightnessReason();
private int mDisplayId;
private float mLux;
private float mPreThresholdLux;
private long mTime;
private float mBrightness;
private float mRecommendedBrightness;
private float mPreThresholdBrightness;
private float mHbmMax;
private float mThermalMax;
private int mHbmMode;
private int mFlags;
private int mAdjustmentFlags;
public BrightnessEvent(BrightnessEvent that) {
copyFrom(that);
}
public BrightnessEvent(int displayId) {
this.mDisplayId = displayId;
reset();
}
/**
* A utility to clone a brightness event into another event
*
* @param that BrightnessEvent which is to be copied
*/
public void copyFrom(BrightnessEvent that) {
mDisplayId = that.getDisplayId();
mTime = that.getTime();
mLux = that.getLux();
mPreThresholdLux = that.getPreThresholdLux();
mBrightness = that.getBrightness();
mRecommendedBrightness = that.getRecommendedBrightness();
mPreThresholdBrightness = that.getPreThresholdBrightness();
mHbmMax = that.getHbmMax();
mThermalMax = that.getThermalMax();
mFlags = that.getFlags();
mHbmMode = that.getHbmMode();
mReason.set(that.getReason());
mAdjustmentFlags = that.getAdjustmentFlags();
}
/**
* A utility to reset the BrightnessEvent to default values
*/
public void reset() {
mTime = SystemClock.uptimeMillis();
mBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mRecommendedBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mLux = 0;
mPreThresholdLux = 0;
mPreThresholdBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mHbmMax = PowerManager.BRIGHTNESS_MAX;
mThermalMax = PowerManager.BRIGHTNESS_MAX;
mFlags = 0;
mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
mReason.set(null);
mAdjustmentFlags = 0;
}
/**
* A utility to compare two BrightnessEvents. This purposefully ignores comparing time as the
* two events might have been created at different times, but essentially hold the same
* underlying values
*
* @param that The brightnessEvent with which the current brightnessEvent is to be compared
* @return A boolean value representing if the two events are same or not.
*/
public boolean equalsMainData(BrightnessEvent that) {
// This equals comparison purposefully ignores time since it is regularly changing and
// we don't want to log a brightness event just because the time changed.
return mDisplayId == that.mDisplayId
&& Float.floatToRawIntBits(mBrightness)
== Float.floatToRawIntBits(that.mBrightness)
&& Float.floatToRawIntBits(mRecommendedBrightness)
== Float.floatToRawIntBits(that.mRecommendedBrightness)
&& Float.floatToRawIntBits(mPreThresholdBrightness)
== Float.floatToRawIntBits(that.mPreThresholdBrightness)
&& Float.floatToRawIntBits(mLux) == Float.floatToRawIntBits(that.mLux)
&& Float.floatToRawIntBits(mPreThresholdLux)
== Float.floatToRawIntBits(that.mPreThresholdLux)
&& Float.floatToRawIntBits(mHbmMax) == Float.floatToRawIntBits(that.mHbmMax)
&& mHbmMode == that.mHbmMode
&& Float.floatToRawIntBits(mThermalMax)
== Float.floatToRawIntBits(that.mThermalMax)
&& mFlags == that.mFlags
&& mAdjustmentFlags == that.mAdjustmentFlags
&& mReason.equals(that.mReason);
}
/**
* A utility to stringify a BrightnessEvent
* @param includeTime Indicates if the time field is to be added in the stringify version of the
* BrightnessEvent
* @return A stringified BrightnessEvent
*/
public String toString(boolean includeTime) {
return (includeTime ? TimeUtils.formatForLogging(mTime) + " - " : "")
+ "BrightnessEvent: "
+ "disp=" + mDisplayId
+ ", brt=" + mBrightness + ((mFlags & FLAG_USER_SET) != 0 ? "(user_set)" : "")
+ ", rcmdBrt=" + mRecommendedBrightness
+ ", preBrt=" + mPreThresholdBrightness
+ ", lux=" + mLux
+ ", preLux=" + mPreThresholdLux
+ ", hbmMax=" + mHbmMax
+ ", hbmMode=" + BrightnessInfo.hbmToString(mHbmMode)
+ ", thrmMax=" + mThermalMax
+ ", flags=" + flagsToString()
+ ", reason=" + mReason.toString(mAdjustmentFlags);
}
@Override
public String toString() {
return toString(/* includeTime */ true);
}
public void setReason(BrightnessReason reason) {
this.mReason = reason;
}
public BrightnessReason getReason() {
return mReason;
}
public int getDisplayId() {
return mDisplayId;
}
public void setDisplayId(int displayId) {
this.mDisplayId = displayId;
}
public float getLux() {
return mLux;
}
public void setLux(float lux) {
this.mLux = lux;
}
public float getPreThresholdLux() {
return mPreThresholdLux;
}
public void setPreThresholdLux(float preThresholdLux) {
this.mPreThresholdLux = preThresholdLux;
}
public long getTime() {
return mTime;
}
public void setTime(long time) {
this.mTime = time;
}
public float getBrightness() {
return mBrightness;
}
public void setBrightness(float brightness) {
this.mBrightness = brightness;
}
public float getRecommendedBrightness() {
return mRecommendedBrightness;
}
public void setRecommendedBrightness(float recommendedBrightness) {
this.mRecommendedBrightness = recommendedBrightness;
}
public float getPreThresholdBrightness() {
return mPreThresholdBrightness;
}
public void setPreThresholdBrightness(float preThresholdBrightness) {
this.mPreThresholdBrightness = preThresholdBrightness;
}
public float getHbmMax() {
return mHbmMax;
}
public void setHbmMax(float hbmMax) {
this.mHbmMax = hbmMax;
}
public float getThermalMax() {
return mThermalMax;
}
public void setThermalMax(float thermalMax) {
this.mThermalMax = thermalMax;
}
public int getHbmMode() {
return mHbmMode;
}
public void setHbmMode(int hbmMode) {
this.mHbmMode = hbmMode;
}
public int getFlags() {
return mFlags;
}
public void setFlags(int flags) {
this.mFlags = flags;
}
public int getAdjustmentFlags() {
return mAdjustmentFlags;
}
public void setAdjustmentFlags(int adjustmentFlags) {
this.mAdjustmentFlags = adjustmentFlags;
}
private String flagsToString() {
return ((mFlags & FLAG_USER_SET) != 0 ? "user_set " : "")
+ ((mFlags & FLAG_RBC) != 0 ? "rbc " : "")
+ ((mFlags & FLAG_INVALID_LUX) != 0 ? "invalid_lux " : "")
+ ((mFlags & FLAG_DOZE_SCALE) != 0 ? "doze_scale " : "");
}
}

View File

@@ -0,0 +1,200 @@
/*
* 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.brightness;
import android.util.Slog;
import java.util.Objects;
/**
* Stores data about why the brightness was changed. Made up of one main
* {@code BrightnessReason.REASON_*} reason and various {@code BrightnessReason.MODIFIER_*}
* modifiers.
*/
public final class BrightnessReason {
private static final String TAG = "BrightnessReason";
public static final int REASON_UNKNOWN = 0;
public static final int REASON_MANUAL = 1;
public static final int REASON_DOZE = 2;
public static final int REASON_DOZE_DEFAULT = 3;
public static final int REASON_AUTOMATIC = 4;
public static final int REASON_SCREEN_OFF = 5;
public static final int REASON_VR = 6;
public static final int REASON_OVERRIDE = 7;
public static final int REASON_TEMPORARY = 8;
public static final int REASON_BOOST = 9;
public static final int REASON_MAX = REASON_BOOST;
public static final int MODIFIER_DIMMED = 0x1;
public static final int MODIFIER_LOW_POWER = 0x2;
public static final int MODIFIER_HDR = 0x4;
public static final int MODIFIER_THROTTLED = 0x8;
public static final int MODIFIER_MASK = MODIFIER_DIMMED | MODIFIER_LOW_POWER | MODIFIER_HDR
| MODIFIER_THROTTLED;
// ADJUSTMENT_*
// These things can happen at any point, even if the main brightness reason doesn't
// fundamentally change, so they're not stored.
// Auto-brightness adjustment factor changed
public static final int ADJUSTMENT_AUTO_TEMP = 0x1;
// Temporary adjustment to the auto-brightness adjustment factor.
public static final int ADJUSTMENT_AUTO = 0x2;
// One of REASON_*
private int mReason;
// Any number of MODIFIER_*
private int mModifier;
/**
* A utility to clone a BrightnessReason from another BrightnessReason event
*
* @param other The BrightnessReason object which is to be cloned
*/
public void set(BrightnessReason other) {
setReason(other == null ? REASON_UNKNOWN : other.mReason);
setModifier(other == null ? 0 : other.mModifier);
}
/**
* A utility to add a modifier to the BrightnessReason object
*
* @param modifier The modifier which is to be added
*/
public void addModifier(int modifier) {
setModifier(modifier | this.mModifier);
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof BrightnessReason)) {
return false;
}
BrightnessReason other = (BrightnessReason) obj;
return other.mReason == mReason && other.mModifier == mModifier;
}
@Override
public int hashCode() {
return Objects.hash(mReason, mModifier);
}
@Override
public String toString() {
return toString(0);
}
/**
* A utility to stringify a BrightnessReason
*
* @param adjustments Indicates if the adjustments field is to be added in the stringify version
* of the BrightnessReason
* @return A stringified BrightnessReason
*/
public String toString(int adjustments) {
final StringBuilder sb = new StringBuilder();
sb.append(reasonToString(mReason));
sb.append(" [");
if ((adjustments & ADJUSTMENT_AUTO_TEMP) != 0) {
sb.append(" temp_adj");
}
if ((adjustments & ADJUSTMENT_AUTO) != 0) {
sb.append(" auto_adj");
}
if ((mModifier & MODIFIER_LOW_POWER) != 0) {
sb.append(" low_pwr");
}
if ((mModifier & MODIFIER_DIMMED) != 0) {
sb.append(" dim");
}
if ((mModifier & MODIFIER_HDR) != 0) {
sb.append(" hdr");
}
if ((mModifier & MODIFIER_THROTTLED) != 0) {
sb.append(" throttled");
}
int strlen = sb.length();
if (sb.charAt(strlen - 1) == '[') {
sb.setLength(strlen - 2);
} else {
sb.append(" ]");
}
return sb.toString();
}
/**
* A utility to set the reason of the BrightnessReason object
*
* @param reason The value to which the reason is to be updated.
*/
public void setReason(int reason) {
if (reason < REASON_UNKNOWN || reason > REASON_MAX) {
Slog.w(TAG, "brightness reason out of bounds: " + reason);
} else {
this.mReason = reason;
}
}
public int getReason() {
return mReason;
}
public int getModifier() {
return mModifier;
}
/**
* A utility to set the modified of the current BrightnessReason object
*
* @param modifier The value to which the modifier is to be updated
*/
public void setModifier(int modifier) {
if ((modifier & ~MODIFIER_MASK) != 0) {
Slog.w(TAG, "brightness modifier out of bounds: 0x"
+ Integer.toHexString(modifier));
} else {
this.mModifier = modifier;
}
}
private String reasonToString(int reason) {
switch (reason) {
case REASON_MANUAL:
return "manual";
case REASON_DOZE:
return "doze";
case REASON_DOZE_DEFAULT:
return "doze_default";
case REASON_AUTOMATIC:
return "automatic";
case REASON_SCREEN_OFF:
return "screen_off";
case REASON_VR:
return "vr";
case REASON_OVERRIDE:
return "override";
case REASON_TEMPORARY:
return "temporary";
case REASON_BOOST:
return "boost";
default:
return Integer.toString(reason);
}
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.brightness;
import static org.junit.Assert.assertEquals;
import android.hardware.display.BrightnessInfo;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public final class BrightnessEventTest {
private BrightnessEvent mBrightnessEvent;
@Before
public void setUp() {
mBrightnessEvent = new BrightnessEvent(1);
mBrightnessEvent.setReason(
getReason(BrightnessReason.REASON_DOZE, BrightnessReason.MODIFIER_LOW_POWER));
mBrightnessEvent.setLux(100.0f);
mBrightnessEvent.setPreThresholdLux(150.0f);
mBrightnessEvent.setTime(System.currentTimeMillis());
mBrightnessEvent.setBrightness(0.6f);
mBrightnessEvent.setRecommendedBrightness(0.6f);
mBrightnessEvent.setHbmMax(0.62f);
mBrightnessEvent.setThermalMax(0.65f);
mBrightnessEvent.setHbmMode(BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
mBrightnessEvent.setFlags(0);
mBrightnessEvent.setAdjustmentFlags(0);
}
@Test
public void testEqualsMainDataComparesAllFieldsExceptTime() {
BrightnessEvent secondBrightnessEvent = new BrightnessEvent(1);
secondBrightnessEvent.copyFrom(mBrightnessEvent);
secondBrightnessEvent.setTime(0);
assertEquals(secondBrightnessEvent.equalsMainData(mBrightnessEvent), true);
}
@Test
public void testToStringWorksAsExpected() {
String actualString = mBrightnessEvent.toString(false);
String expectedString =
"BrightnessEvent: disp=1, brt=0.6, rcmdBrt=0.6, preBrt=NaN, lux=100.0, preLux=150"
+ ".0, hbmMax=0.62, hbmMode=off, thrmMax=0.65, flags=, reason=doze [ "
+ "low_pwr ]";
assertEquals(actualString, expectedString);
}
private BrightnessReason getReason(int reason, int modifier) {
BrightnessReason brightnessReason = new BrightnessReason();
brightnessReason.setReason(reason);
brightnessReason.setModifier(modifier);
return brightnessReason;
}
}

View File

@@ -0,0 +1,92 @@
/*
* 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.brightness;
import static org.junit.Assert.assertEquals;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@SmallTest
@Presubmit
@RunWith(AndroidJUnit4.class)
public final class BrightnessReasonTest {
private BrightnessReason mBrightnessReason;
@Before
public void setUp() {
mBrightnessReason = getReason(BrightnessReason.REASON_DOZE,
BrightnessReason.MODIFIER_LOW_POWER);
}
@Test
public void setSetsAppropriateValues() {
mBrightnessReason.set(null);
assertEquals(mBrightnessReason.getReason(), BrightnessReason.REASON_UNKNOWN);
assertEquals(mBrightnessReason.getModifier(), 0);
mBrightnessReason.set(
getReason(BrightnessReason.REASON_BOOST, BrightnessReason.MODIFIER_THROTTLED));
assertEquals(mBrightnessReason.getReason(), BrightnessReason.REASON_BOOST);
assertEquals(mBrightnessReason.getModifier(), BrightnessReason.MODIFIER_THROTTLED);
}
@Test
public void toStringGeneratesExpectedString() {
String actualString = mBrightnessReason.toString();
String expectedString = "doze [ low_pwr ]";
assertEquals(actualString, expectedString);
}
@Test
public void setModifierDoesntSetIfModifierIsBeyondExtremes() {
int extremeModifier = 0x16;
mBrightnessReason.setModifier(extremeModifier);
assertEquals(mBrightnessReason.getModifier(), BrightnessReason.MODIFIER_LOW_POWER);
}
@Test
public void setReasonDoesntSetIfModifierIsBeyondExtremes() {
int extremeReason = 10;
mBrightnessReason.setReason(extremeReason);
assertEquals(mBrightnessReason.getReason(), BrightnessReason.REASON_DOZE);
extremeReason = -1;
mBrightnessReason.setReason(extremeReason);
assertEquals(mBrightnessReason.getReason(), BrightnessReason.REASON_DOZE);
}
@Test
public void addModifierWorksAsExpected() {
mBrightnessReason.addModifier(BrightnessReason.REASON_BOOST);
assertEquals(mBrightnessReason.getModifier(),
BrightnessReason.REASON_DOZE | BrightnessReason.REASON_BOOST);
}
private BrightnessReason getReason(int reason, int modifier) {
BrightnessReason brightnessReason = new BrightnessReason();
brightnessReason.setReason(reason);
brightnessReason.setModifier(modifier);
return brightnessReason;
}
}