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

Commit cd02f0ac authored by Long Ling's avatar Long Ling Committed by Android (Google) Code Review
Browse files

Merge "Report HBM events to StatsLog"

parents 7f957237 ccfb9d9b
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -54,6 +54,10 @@ class AutomaticBrightnessController {

    private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;

    public static final int AUTO_BRIGHTNESS_ENABLED = 1;
    public static final int AUTO_BRIGHTNESS_DISABLED = 2;
    public static final int AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE = 3;

    // How long the current sensor reading is assumed to be valid beyond the current time.
    // This provides a bit of prediction, as well as ensures that the weight for the last sample is
    // non-zero, which in turn ensures that the total weight is non-zero.
@@ -214,6 +218,7 @@ class AutomaticBrightnessController {
    private IActivityTaskManager mActivityTaskManager;
    private PackageManager mPackageManager;
    private Context mContext;
    private int mState = AUTO_BRIGHTNESS_DISABLED;

    private final Injector mInjector;

@@ -331,10 +336,11 @@ class AutomaticBrightnessController {
        return mCurrentBrightnessMapper.getAutoBrightnessAdjustment();
    }

    public void configure(boolean enable, @Nullable BrightnessConfiguration configuration,
    public void configure(int state, @Nullable BrightnessConfiguration configuration,
            float brightness, boolean userChangedBrightness, float adjustment,
            boolean userChangedAutoBrightnessAdjustment, int displayPolicy) {
        mHbmController.setAutoBrightnessEnabled(enable);
        mState = state;
        mHbmController.setAutoBrightnessEnabled(mState);
        // While dozing, the application processor may be suspended which will prevent us from
        // receiving new information from the light sensor. On some devices, we may be able to
        // switch to a wake-up light sensor instead but for now we will simply disable the sensor
@@ -346,6 +352,7 @@ class AutomaticBrightnessController {
        if (userChangedAutoBrightnessAdjustment) {
            changed |= setAutoBrightnessAdjustment(adjustment);
        }
        final boolean enable = mState == AUTO_BRIGHTNESS_ENABLED;
        if (userChangedBrightness && enable) {
            // Update the brightness curve with the new user control point. It's critical this
            // happens after we update the autobrightness adjustment since it may reset it.
@@ -459,6 +466,7 @@ class AutomaticBrightnessController {
    public void dump(PrintWriter pw) {
        pw.println();
        pw.println("Automatic Brightness Controller Configuration:");
        pw.println("  mState=" + configStateToString(mState));
        pw.println("  mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
        pw.println("  mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
        pw.println("  mDozeScaleFactor=" + mDozeScaleFactor);
@@ -520,6 +528,19 @@ class AutomaticBrightnessController {
        mScreenBrightnessThresholds.dump(pw);
    }

    private String configStateToString(int state) {
        switch (state) {
        case AUTO_BRIGHTNESS_ENABLED:
            return "AUTO_BRIGHTNESS_ENABLED";
        case AUTO_BRIGHTNESS_DISABLED:
            return "AUTO_BRIGHTNESS_DISABLED";
        case AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE:
            return "AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE";
        default:
            return String.valueOf(state);
        }
    }

    private boolean setLightSensorEnabled(boolean enable) {
        if (enable) {
            if (!mLightSensorEnabled) {
+70 −4
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
@@ -127,6 +128,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private static final int MSG_STOP = 9;
    private static final int MSG_UPDATE_BRIGHTNESS = 10;
    private static final int MSG_UPDATE_RBC = 11;
    private static final int MSG_STATSD_HBM_BRIGHTNESS = 12;

    private static final int PROXIMITY_UNKNOWN = -1;
    private static final int PROXIMITY_NEGATIVE = 0;
@@ -136,6 +138,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
    private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;

    private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;

    // Trigger proximity if distance is less than 5 cm.
    private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;

@@ -356,6 +360,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
    private float mBrightnessRampRateSlowDecrease;
    private float mBrightnessRampRateSlowIncrease;

    // Report HBM brightness change to StatsD
    private int mDisplayStatsId;
    private float mLastStatsBrightness = PowerManager.BRIGHTNESS_MIN;

    // Whether or not to skip the initial brightness ramps into STATE_ON.
    private final boolean mSkipScreenOnBrightnessRamp;
@@ -466,6 +473,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        TAG = "DisplayPowerController[" + mDisplayId + "]";
        mDisplayDevice = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
        mUniqueDisplayId = logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
        mDisplayStatsId = mUniqueDisplayId.hashCode();
        mHandler = new DisplayControllerHandler(handler.getLooper());

        if (mDisplayId == Display.DEFAULT_DISPLAY) {
@@ -763,6 +771,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            if (mDisplayDevice != device) {
                mDisplayDevice = device;
                mUniqueDisplayId = uniqueId;
                mDisplayStatsId = mUniqueDisplayId.hashCode();
                mDisplayDeviceConfig = config;
                loadFromDisplayDeviceConfig(token, info);
                updatePowerState();
@@ -816,7 +825,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        loadNitsRange(mContext.getResources());
        setUpAutoBrightness(mContext.getResources(), mHandler);
        reloadReduceBrightColours();
        mHbmController.resetHbmData(info.width, info.height, token,
        mHbmController.resetHbmData(info.width, info.height, token, info.uniqueId,
                mDisplayDeviceConfig.getHighBrightnessModeData());
    }

@@ -1004,7 +1013,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        }
    };

    private final RampAnimator.Listener mRampAnimatorListener = this::sendUpdatePowerState;
    private final RampAnimator.Listener mRampAnimatorListener = new RampAnimator.Listener() {
        @Override
        public void onAnimationEnd() {
            sendUpdatePowerState();

            final float brightness = mPowerState.getScreenBrightness();
            reportStats(brightness);
        }
    };

    /** Clean up all resources that are accessed via the {@link #mHandler} thread. */
    private void cleanupHandlerThreadAfterStop() {
@@ -1179,6 +1196,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    && (state == Display.STATE_ON || autoBrightnessEnabledInDoze)
                    && Float.isNaN(brightnessState)
                    && mAutomaticBrightnessController != null;
        final boolean autoBrightnessDisabledDueToDisplayOff = mPowerRequest.useAutoBrightness
                    && !(state == Display.STATE_ON || autoBrightnessEnabledInDoze);
        final int autoBrightnessState = autoBrightnessEnabled
                ? AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED
                : autoBrightnessDisabledDueToDisplayOff
                ? AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE
                : AutomaticBrightnessController.AUTO_BRIGHTNESS_DISABLED;

        final boolean userSetBrightnessChanged = updateUserSetScreenBrightness();

@@ -1229,7 +1253,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        // Configure auto-brightness.
        if (mAutomaticBrightnessController != null) {
            hadUserBrightnessPoint = mAutomaticBrightnessController.hasUserDataPoints();
            mAutomaticBrightnessController.configure(autoBrightnessEnabled,
            mAutomaticBrightnessController.configure(autoBrightnessState,
                    mBrightnessConfiguration,
                    mLastUserSetScreenBrightness,
                    userSetBrightnessChanged, autoBrightnessAdjustment,
@@ -1626,11 +1650,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig();
        final IBinder displayToken =
                mLogicalDisplay.getPrimaryDisplayDeviceLocked().getDisplayTokenLocked();
        final String displayUniqueId =
                mLogicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId();
        final DisplayDeviceConfig.HighBrightnessModeData hbmData =
                ddConfig != null ? ddConfig.getHighBrightnessModeData() : null;
        final DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
        return new HighBrightnessModeController(mHandler, info.width, info.height, displayToken,
                PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
                displayUniqueId, PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, hbmData,
                () -> {
                    sendUpdatePowerStateLocked();
                    postBrightnessChangeRunnable();
@@ -2462,6 +2488,42 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        }
    }

    private void reportStats(float brightness) {
        float hbmTransitionPoint = PowerManager.BRIGHTNESS_MAX;
        synchronized(mCachedBrightnessInfo) {
            if (mCachedBrightnessInfo.hbmTransitionPoint == null) {
                return;
            }
            hbmTransitionPoint = mCachedBrightnessInfo.hbmTransitionPoint.value;
        }

        final boolean aboveTransition = brightness > hbmTransitionPoint;
        final boolean oldAboveTransition = mLastStatsBrightness > hbmTransitionPoint;

        if (aboveTransition || oldAboveTransition) {
            mLastStatsBrightness = brightness;
            mHandler.removeMessages(MSG_STATSD_HBM_BRIGHTNESS);
            if (aboveTransition != oldAboveTransition) {
                // report immediately
                logHbmBrightnessStats(brightness, mDisplayStatsId);
            } else {
                // delay for rate limiting
                Message msg = mHandler.obtainMessage();
                msg.what = MSG_STATSD_HBM_BRIGHTNESS;
                msg.arg1 = Float.floatToIntBits(brightness);
                msg.arg2 = mDisplayStatsId;
                mHandler.sendMessageDelayed(msg, BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS);
            }
        }
    }

    private final void logHbmBrightnessStats(float brightness, int displayStatsId) {
        synchronized (mHandler) {
            FrameworkStatsLog.write(
                    FrameworkStatsLog.DISPLAY_HBM_BRIGHTNESS_CHANGED, displayStatsId, brightness);
        }
    }

    private final class DisplayControllerHandler extends Handler {
        public DisplayControllerHandler(Looper looper) {
            super(looper, null, true /*async*/);
@@ -2526,6 +2588,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    final int justActivated = msg.arg2;
                    handleRbcChanged(strengthChanged == 1, justActivated == 1);
                    break;

                case MSG_STATSD_HBM_BRIGHTNESS:
                    logHbmBrightnessStats(Float.intBitsToFloat(msg.arg1), msg.arg2);
                    break;
            }
        }
    }
+63 −8
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.util.TimeUtils;
import android.view.SurfaceControlHdrLayerInfoListener;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.display.DisplayDeviceConfig.HighBrightnessModeData;
import com.android.server.display.DisplayManagerService.Clock;

@@ -80,6 +81,7 @@ class HighBrightnessModeController {
    private boolean mIsInAllowedAmbientRange = false;
    private boolean mIsTimeAvailable = false;
    private boolean mIsAutoBrightnessEnabled = false;
    private boolean mIsAutoBrightnessOffByState = false;
    private float mBrightness;
    private int mHbmMode = BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
    private boolean mIsHdrLayerPresent = false;
@@ -88,6 +90,7 @@ class HighBrightnessModeController {
    private int mWidth;
    private int mHeight;
    private float mAmbientLux;
    private int mDisplayStatsId;

    /**
     * If HBM is currently running, this is the start time for the current HBM session.
@@ -102,15 +105,15 @@ class HighBrightnessModeController {
    private LinkedList<HbmEvent> mEvents = new LinkedList<>();

    HighBrightnessModeController(Handler handler, int width, int height, IBinder displayToken,
            float brightnessMin, float brightnessMax, HighBrightnessModeData hbmData,
            Runnable hbmChangeCallback, Context context) {
        this(new Injector(), handler, width, height, displayToken, brightnessMin, brightnessMax,
                hbmData, hbmChangeCallback, context);
            String displayUniqueId, float brightnessMin, float brightnessMax,
            HighBrightnessModeData hbmData, Runnable hbmChangeCallback, Context context) {
        this(new Injector(), handler, width, height, displayToken, displayUniqueId, brightnessMin,
            brightnessMax, hbmData, hbmChangeCallback, context);
    }

    @VisibleForTesting
    HighBrightnessModeController(Injector injector, Handler handler, int width, int height,
            IBinder displayToken, float brightnessMin, float brightnessMax,
            IBinder displayToken, String displayUniqueId, float brightnessMin, float brightnessMax,
            HighBrightnessModeData hbmData, Runnable hbmChangeCallback,
            Context context) {
        mInjector = injector;
@@ -126,10 +129,13 @@ class HighBrightnessModeController {
        mRecalcRunnable = this::recalculateTimeAllowance;
        mHdrListener = new HdrListener();

        resetHbmData(width, height, displayToken, hbmData);
        resetHbmData(width, height, displayToken, displayUniqueId, hbmData);
    }

    void setAutoBrightnessEnabled(boolean isEnabled) {
    void setAutoBrightnessEnabled(int state) {
        final boolean isEnabled = state == AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;
        mIsAutoBrightnessOffByState =
                state == AutomaticBrightnessController.AUTO_BRIGHTNESS_OFF_DUE_TO_DISPLAY_STATE;
        if (!deviceSupportsHbm() || isEnabled == mIsAutoBrightnessEnabled) {
            return;
        }
@@ -231,10 +237,12 @@ class HighBrightnessModeController {
        mSettingsObserver.stopObserving();
    }

    void resetHbmData(int width, int height, IBinder displayToken, HighBrightnessModeData hbmData) {
    void resetHbmData(int width, int height, IBinder displayToken, String displayUniqueId,
            HighBrightnessModeData hbmData) {
        mWidth = width;
        mHeight = height;
        mHbmData = hbmData;
        mDisplayStatsId = displayUniqueId.hashCode();

        unregisterHdrListener();
        mSkinThermalStatusObserver.stopObserving();
@@ -275,6 +283,7 @@ class HighBrightnessModeController {
                + (mIsAutoBrightnessEnabled ? "" : " (old/invalid)"));
        pw.println("  mIsInAllowedAmbientRange=" + mIsInAllowedAmbientRange);
        pw.println("  mIsAutoBrightnessEnabled=" + mIsAutoBrightnessEnabled);
        pw.println("  mIsAutoBrightnessOffByState=" + mIsAutoBrightnessOffByState);
        pw.println("  mIsHdrLayerPresent=" + mIsHdrLayerPresent);
        pw.println("  mBrightnessMin=" + mBrightnessMin);
        pw.println("  mBrightnessMax=" + mBrightnessMax);
@@ -436,11 +445,52 @@ class HighBrightnessModeController {
    private void updateHbmMode() {
        int newHbmMode = calculateHighBrightnessMode();
        if (mHbmMode != newHbmMode) {
            updateHbmStats(mHbmMode, newHbmMode);
            mHbmMode = newHbmMode;
            mHbmChangeCallback.run();
        }
    }

    private void updateHbmStats(int mode, int newMode) {
        int state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF;
        if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR) {
            state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_HDR;
        } else if (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
            state = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT;
        }

        int reason =
                FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN;
        boolean oldHbmSv = (mode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT);
        boolean newHbmSv = (newMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT);
        if (oldHbmSv && !newHbmSv) {
            // If more than one conditions are flipped and turn off HBM sunlight
            // visibility, only one condition will be reported to make it simple.
            if (!mIsAutoBrightnessEnabled && mIsAutoBrightnessOffByState) {
                reason = FrameworkStatsLog
                                 .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_DISPLAY_OFF;
            } else if (!mIsAutoBrightnessEnabled) {
                reason = FrameworkStatsLog
                                 .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_AUTOBRIGHTNESS_OFF;
            } else if (!mIsInAllowedAmbientRange) {
                reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LUX_DROP;
            } else if (!mIsTimeAvailable) {
                reason = FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_TIME_LIMIT;
            } else if (!mIsThermalStatusWithinLimit) {
                reason = FrameworkStatsLog
                                 .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_THERMAL_LIMIT;
            } else if (mIsHdrLayerPresent) {
                reason = FrameworkStatsLog
                                 .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_HDR_PLAYING;
            } else if (mIsBlockedByLowPowerMode) {
                reason = FrameworkStatsLog
                                 .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_BATTERY_SAVE_ON;
            }
        }

        mInjector.reportHbmStateChange(mDisplayStatsId, state, reason);
    }

    private int calculateHighBrightnessMode() {
        if (!deviceSupportsHbm()) {
            return BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
@@ -642,5 +692,10 @@ class HighBrightnessModeController {
            return IThermalService.Stub.asInterface(
                    ServiceManager.getService(Context.THERMAL_SERVICE));
        }

        public void reportHbmStateChange(int display, int state, int reason) {
            FrameworkStatsLog.write(
                    FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED, display, state, reason);
        }
    }
}
+6 −4
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.display;

import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
@@ -111,7 +113,7 @@ public class AutomaticBrightnessControllerTest {

        // Configure the brightness controller and grab an instance of the sensor listener,
        // through which we can deliver fake (for test) sensor values.
        controller.configure(true /* enable */, null /* configuration */,
        controller.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
                0 /* brightness */, false /* userChangedBrightness */, 0 /* adjustment */,
                false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);

@@ -227,7 +229,7 @@ public class AutomaticBrightnessControllerTest {
        listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000));

        // User sets brightness to 100
        mController.configure(true /* enable */, null /* configuration */,
        mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
                0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
                false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);

@@ -250,7 +252,7 @@ public class AutomaticBrightnessControllerTest {
        listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000));

        // User sets brightness to 100
        mController.configure(true /* enable */, null /* configuration */,
        mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
                0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
                false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);

@@ -267,7 +269,7 @@ public class AutomaticBrightnessControllerTest {
        verifyNoMoreInteractions(mBrightnessMappingStrategy);

        // User sets idle brightness to 0.5
        mController.configure(true /* enable */, null /* configuration */,
        mController.configure(AUTO_BRIGHTNESS_ENABLED, null /* configuration */,
                0.5f /* brightness */, true /* userChangedBrightness */, 0 /* adjustment */,
                false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);

+158 −19

File changed.

Preview size limit exceeded, changes collapsed.