Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0bdd9352 authored by Santos Cordon's avatar Santos Cordon
Browse files

Add brightness event logging.

- Add more data/context to BrightnessEvents.
- Log BrightnessEvents as they occur.
- Replace BrightnessReason logging with BrightnessEvent.

Example output:
BrightnessEvent: disp=0, brt=0.050589137, rcmdBrt=0.050589137, preBrt=NaN, lux=194.08928, preLux=0.0, hbmMax=0.62, hbmMode=off, thrmMax=1.0, flags=, reason=automatic

Bug: 227483176
Test: Manually verify output of dumpsys and logcat
Test: atest com.android.server.display
Change-Id: I0cb88baf6c66e9ff6b07fb32666258cad4fe434f
parent 323def83
Loading
Loading
Loading
Loading
+36 −4
Original line number Diff line number Diff line
@@ -46,6 +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 java.io.PrintWriter;

@@ -147,6 +148,9 @@ class AutomaticBrightnessController {
    // The currently accepted nominal ambient light level.
    private float mAmbientLux;

    // The last ambient lux value prior to passing the darkening or brightening threshold.
    private float mPreThresholdLux;

    // True if mAmbientLux holds a valid value.
    private boolean mAmbientLuxValid;

@@ -154,6 +158,9 @@ class AutomaticBrightnessController {
    private float mAmbientBrighteningThreshold;
    private float mAmbientDarkeningThreshold;

    // The last brightness value prior to passing the darkening or brightening threshold.
    private float mPreThresholdBrightness;

    // The screen brightness threshold at which to brighten or darken the screen.
    private float mScreenBrighteningThreshold;
    private float mScreenDarkeningThreshold;
@@ -325,6 +332,21 @@ class AutomaticBrightnessController {
    }

    public float getAutomaticScreenBrightness() {
        return getAutomaticScreenBrightness(null);
    }

    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)
                    | (mDisplayPolicy == DisplayPowerRequest.POLICY_DOZE
                        ? BrightnessEvent.FLAG_DOZE_SCALE : 0);
        }

        if (!mAmbientLuxValid) {
            return PowerManager.BRIGHTNESS_INVALID_FLOAT;
        }
@@ -506,6 +528,8 @@ class AutomaticBrightnessController {
        pw.println("  mCurrentLightSensorRate=" + mCurrentLightSensorRate);
        pw.println("  mAmbientLux=" + mAmbientLux);
        pw.println("  mAmbientLuxValid=" + mAmbientLuxValid);
        pw.println("  mPreThesholdLux=" + mPreThresholdLux);
        pw.println("  mPreThesholdBrightness=" + mPreThresholdBrightness);
        pw.println("  mAmbientBrighteningThreshold=" + mAmbientBrighteningThreshold);
        pw.println("  mAmbientDarkeningThreshold=" + mAmbientDarkeningThreshold);
        pw.println("  mScreenBrighteningThreshold=" + mScreenBrighteningThreshold);
@@ -574,7 +598,11 @@ class AutomaticBrightnessController {
        } else if (mLightSensorEnabled) {
            mLightSensorEnabled = false;
            mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
            if (!mAmbientLuxValid) {
                mPreThresholdLux = PowerManager.BRIGHTNESS_INVALID_FLOAT;
            }
            mScreenAutoBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
            mPreThresholdBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
            mRecentLightSamples = 0;
            mAmbientLightRingBuffer.clear();
            mCurrentLightSensorRate = -1;
@@ -790,6 +818,7 @@ class AutomaticBrightnessController {
                || (slowAmbientLux <= mAmbientDarkeningThreshold
                        && fastAmbientLux <= mAmbientDarkeningThreshold
                        && nextDarkenTransition <= time)) {
            mPreThresholdLux = mAmbientLux;
            setAmbientLux(fastAmbientLux);
            if (mLoggingEnabled) {
                Slog.d(TAG, "updateAmbientLux: "
@@ -834,11 +863,11 @@ class AutomaticBrightnessController {
        // If screenAutoBrightness is set, we should have screen{Brightening,Darkening}Threshold,
        // in which case we ignore the new screen brightness if it doesn't differ enough from the
        // previous one.
        if (!Float.isNaN(mScreenAutoBrightness)
                && !isManuallySet
        boolean withinThreshold = !Float.isNaN(mScreenAutoBrightness)
                && newScreenAutoBrightness > mScreenDarkeningThreshold
                && newScreenAutoBrightness < mScreenBrighteningThreshold
                && currentBrightnessWithinAllowedRange) {
                && newScreenAutoBrightness < mScreenBrighteningThreshold;

        if (withinThreshold && !isManuallySet && currentBrightnessWithinAllowedRange) {
            if (mLoggingEnabled) {
                Slog.d(TAG, "ignoring newScreenAutoBrightness: "
                        + mScreenDarkeningThreshold + " < " + newScreenAutoBrightness
@@ -853,6 +882,9 @@ class AutomaticBrightnessController {
                        + "mScreenAutoBrightness=" + mScreenAutoBrightness + ", "
                        + "newScreenAutoBrightness=" + newScreenAutoBrightness);
            }
            if (!withinThreshold) {
                mPreThresholdBrightness = mScreenAutoBrightness;
            }
            mScreenAutoBrightness = newScreenAutoBrightness;
            mScreenBrighteningThreshold = clampScreenBrightness(
                    mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness));
+157 −30
Original line number Diff line number Diff line
@@ -216,9 +216,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call

    private final float mScreenBrightnessDefault;

    // Previously logged screen brightness. Used for autobrightness event dumpsys.
    private float mPreviousScreenBrightness = Float.NaN;

    // The minimum allowed brightness while in VR.
    private final float mScreenBrightnessForVrRangeMinimum;

@@ -394,8 +391,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call

    private final Runnable mOnBrightnessChangeRunnable;

    // Used for keeping record in dumpsys for when and to which brightness auto adaptions were made.
    private RingBuffer<AutobrightnessEvent> mAutobrightnessEventRingBuffer;
    private final BrightnessEvent mLastBrightnessEvent;
    private final BrightnessEvent mTempBrightnessEvent;

    // Keeps a record of brightness changes for dumpsys.
    private RingBuffer<BrightnessEvent> mBrightnessEventRingBuffer;

    // A record of state for skipping brightness ramps.
    private int mSkipRampState = RAMP_STATE_SKIP_NONE;
@@ -455,6 +455,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
    private float mTemporaryAutoBrightnessAdjustment;

    private boolean mIsRbcActive;

    // Animators.
    private ObjectAnimator mColorFadeOnAnimator;
    private ObjectAnimator mColorFadeOffAnimator;
@@ -481,6 +483,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
        mDisplayStatsId = mUniqueDisplayId.hashCode();
        mHandler = new DisplayControllerHandler(handler.getLooper());
        mLastBrightnessEvent = new BrightnessEvent(mDisplayId);
        mTempBrightnessEvent = new BrightnessEvent(mDisplayId);

        if (mDisplayId == Display.DEFAULT_DISPLAY) {
            mBatteryStats = BatteryStatsService.getService();
@@ -634,8 +638,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        for (int i = 0; i < mNitsRange.length; i++) {
            adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
        }
        mAutomaticBrightnessController.recalculateSplines(mCdsi.isReduceBrightColorsActivated(),
                adjustedNits);
        mIsRbcActive = mCdsi.isReduceBrightColorsActivated();
        mAutomaticBrightnessController.recalculateSplines(mIsRbcActive, adjustedNits);


        // If rbc is turned on, off or there is a change in strength, we want to reset the short
@@ -991,8 +995,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    mDisplayDeviceConfig.getAmbientHorizonShort(),
                    mDisplayDeviceConfig.getAmbientHorizonLong());

            mAutobrightnessEventRingBuffer =
                    new RingBuffer<>(AutobrightnessEvent.class, RINGBUFFER_MAX);
            mBrightnessEventRingBuffer =
                    new RingBuffer<>(BrightnessEvent.class, RINGBUFFER_MAX);
        } else {
            mUseSoftwareAutoBrightnessConfig = false;
        }
@@ -1088,6 +1092,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        boolean mustInitialize = false;
        int brightnessAdjustmentFlags = 0;
        mBrightnessReasonTemp.set(null);
        mTempBrightnessEvent.reset();
        synchronized (mLock) {
            if (mStopped) {
                return;
@@ -1314,7 +1319,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        if (Float.isNaN(brightnessState)) {
            float newAutoBrightnessAdjustment = autoBrightnessAdjustment;
            if (autoBrightnessEnabled) {
                brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness();
                brightnessState = mAutomaticBrightnessController.getAutomaticScreenBrightness(
                        mTempBrightnessEvent);
                newAutoBrightnessAdjustment =
                        mAutomaticBrightnessController.getAutomaticScreenBrightnessAdjustment();
            }
@@ -1376,6 +1382,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        // we broadcast this change through setting.
        final float unthrottledBrightnessState = brightnessState;
        if (mBrightnessThrottler.isThrottled()) {
            mTempBrightnessEvent.thermalMax = mBrightnessThrottler.getBrightnessCap();
            brightnessState = Math.min(brightnessState, mBrightnessThrottler.getBrightnessCap());
            mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_THROTTLED);
            if (!mAppliedThrottling) {
@@ -1567,13 +1574,35 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            Slog.v(TAG, "Brightness [" + brightnessState + "] manual adjustment.");
        }

        // Add any automatic changes to autobrightness ringbuffer for dumpsys.
        if (mBrightnessReason.reason == BrightnessReason.REASON_AUTOMATIC
                && !BrightnessSynchronizer.floatEquals(
                        mPreviousScreenBrightness, brightnessState)) {
            mPreviousScreenBrightness = brightnessState;
            mAutobrightnessEventRingBuffer.append(new AutobrightnessEvent(
                    System.currentTimeMillis(), brightnessState));

        // 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);
        // 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;
        if ((!mTempBrightnessEvent.equalsMainData(mLastBrightnessEvent) && !tempToTempTransition)
                || brightnessAdjustmentFlags != 0) {
            mLastBrightnessEvent.copyFrom(mTempBrightnessEvent);
            BrightnessEvent newEvent = new BrightnessEvent(mTempBrightnessEvent);

            // 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);
            Slog.i(TAG, newEvent.toString(/* includeTime= */ false));

            if (mBrightnessEventRingBuffer != null) {
                mBrightnessEventRingBuffer.append(newEvent);
            }
        }

        // Update display white-balance.
@@ -2482,6 +2511,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        pw.println("  mPendingScreenOff=" + mPendingScreenOff);
        pw.println("  mReportedToPolicy="
                + reportedToPolicyToString(mReportedScreenStateToPolicy));
        pw.println("  mIsRbcActive=" + mIsRbcActive);

        if (mScreenBrightnessRampAnimator != null) {
            pw.println("  mScreenBrightnessRampAnimator.isAnimating()="
@@ -2503,7 +2533,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call

        if (mAutomaticBrightnessController != null) {
            mAutomaticBrightnessController.dump(pw);
            dumpAutobrightnessEvents(pw);
            dumpBrightnessEvents(pw);
        }

        if (mHbmController != null) {
@@ -2560,16 +2590,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        }
    }

    private void dumpAutobrightnessEvents(PrintWriter pw) {
        int size = mAutobrightnessEventRingBuffer.size();
    private void dumpBrightnessEvents(PrintWriter pw) {
        int size = mBrightnessEventRingBuffer.size();
        if (size < 1) {
            pw.println("No Automatic Brightness Adjustments");
            return;
        }

        pw.println("Automatic Brightness Adjustments Last " + size + " Events: ");
        AutobrightnessEvent[] eventArray = mAutobrightnessEventRingBuffer.toArray();
        for (int i = 0; i < mAutobrightnessEventRingBuffer.size(); i++) {
        BrightnessEvent[] eventArray = mBrightnessEventRingBuffer.toArray();
        for (int i = 0; i < mBrightnessEventRingBuffer.size(); i++) {
            pw.println("  " + eventArray[i].toString());
        }
    }
@@ -2646,18 +2676,115 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        }
    }

    private static class AutobrightnessEvent {
        final long mTime;
        final float mBrightness;

        AutobrightnessEvent(long time, float brightness) {
            mTime = time;
            mBrightness = brightness;
    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 TimeUtils.formatForLogging(mTime) + " - Brightness: " + mBrightness;
            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 " : "");
        }
    }