From 373794989baaf46d724431694831e9aa388ab783 Mon Sep 17 00:00:00 2001 From: Rupesh Bansal Date: Sat, 25 Jun 2022 17:46:38 +0000 Subject: [PATCH] Moving BrightnessInfo and BrightnessReason outside of DisplayPowerController to have the support of declaring the brightness relevant states in DisplayPowerController agnostic fashion. We primarily need this because currently DisplayPowerController is tightly coupled with these classes, even though it is not really in the realm of DisplayPowerController to evaluate it. In future, the vision is to have a different class which keeps track of all the changes happening to the brightness and store them in a RingBuffer(Like we do today). This is taking it one step closer to that, with more verbose tests Bug: 233051797 Test: atest BrightnessEventTest && atest BrightnessReasonTest Change-Id: I15d47cc669bda1c160f02e205168c7aeee9d6658 --- .../AutomaticBrightnessController.java | 17 +- .../display/DisplayPowerController.java | 276 ++---------------- .../display/brightness/BrightnessEvent.java | 262 +++++++++++++++++ .../display/brightness/BrightnessReason.java | 200 +++++++++++++ .../brightness/BrightnessEventTest.java | 78 +++++ .../brightness/BrightnessReasonTest.java | 92 ++++++ 6 files changed, 661 insertions(+), 264 deletions(-) create mode 100644 services/core/java/com/android/server/display/brightness/BrightnessEvent.java create mode 100644 services/core/java/com/android/server/display/brightness/BrightnessReason.java create mode 100644 services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java create mode 100644 services/tests/servicestests/src/com/android/server/display/brightness/BrightnessReasonTest.java diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 6fd88411593f2..114690a033241 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -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) { diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 95c8fef12976a..4e33fd07c28e3 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -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 = diff --git a/services/core/java/com/android/server/display/brightness/BrightnessEvent.java b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java new file mode 100644 index 0000000000000..6698612dc6522 --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/BrightnessEvent.java @@ -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 " : ""); + } +} diff --git a/services/core/java/com/android/server/display/brightness/BrightnessReason.java b/services/core/java/com/android/server/display/brightness/BrightnessReason.java new file mode 100644 index 0000000000000..d8eacd930d400 --- /dev/null +++ b/services/core/java/com/android/server/display/brightness/BrightnessReason.java @@ -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); + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java new file mode 100644 index 0000000000000..e305957c62905 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessEventTest.java @@ -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; + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessReasonTest.java b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessReasonTest.java new file mode 100644 index 0000000000000..ffc2e0dfe26c6 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/display/brightness/BrightnessReasonTest.java @@ -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; + } +}