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

Commit 0dcdae30 authored by Julius D'souza's avatar Julius D'souza Committed by Android (Google) Code Review
Browse files

Merge "DO NOT MERGE: Ambient light sensor changes for doze mode." into cw-f-dev

parents c4ceb503 c4e1e490
Loading
Loading
Loading
Loading
+32 −0
Original line number Diff line number Diff line
@@ -1178,6 +1178,38 @@
    <integer-array name="config_dynamicHysteresisLuxLevels">
    </integer-array>

    <!-- This flag requires config_dozeSensorLuxLevels to have one or more entries and only affects
         the screen brightness while dozing. The screen brightness of a device is based off of a
         ring buffer of the last n seconds of ambient light sensor sample readings.

         If this flag is true, then this buffer is cleared and the screen brightness is based off of
         ambient light sensor readings that are obtained while the device is dozing.  This mode may
         be better suited for watches.

         If this flag is false, then this buffer is untouched. -->
    <bool name="config_useNewSensorSamplesForDoze">false</bool>

    <!-- Array of ambient light sensor lux threshold values for determining screen brightness for
         devices that have both an ambient light sensor and the screen on while dozing. This is
         used to determine the screen brightness while dozing by calculating the index to use for
         lookup and then setting the screen brightness value to the corresponding value of
         config_dozeBrightnessBacklightValues.

         The (zero-based) index is calculated as follows: (MAX is the largest index of the array)
         condition                      calculated index
         value < lux[0]                 0
         lux[n] <= value < lux[n+1]     n+1
         lux[MAX] <= value              MAX+1 -->
    <integer-array name="config_dozeSensorLuxLevels">
    </integer-array>

    <!-- Array of values for determining screen brightness for devices that have both an ambient
         light sensor and the screen on while dozing. The length of this array is assumed to be one
         greater than config_dozeModeSensorLuxLevels if they are not both empty. See the
         config_dozeModeSensorLuxLevels description for how the backlight value is chosen. -->
    <integer-array name="config_dozeBrightnessBacklightValues">
    </integer-array>

    <!-- Amount of time it takes for the light sensor to warm up in milliseconds.
         For this time after the screen turns on, the Power Manager
         will not debounce light sensor readings -->
+3 −0
Original line number Diff line number Diff line
@@ -1648,6 +1648,8 @@
  <java-symbol type="array" name="config_dynamicHysteresisBrightLevels" />
  <java-symbol type="array" name="config_dynamicHysteresisDarkLevels" />
  <java-symbol type="array" name="config_dynamicHysteresisLuxLevels" />
  <java-symbol type="array" name="config_dozeBrightnessBacklightValues" />
  <java-symbol type="array" name="config_dozeSensorLuxLevels" />
  <java-symbol type="array" name="config_protectedNetworks" />
  <java-symbol type="array" name="config_statusBarIcons" />
  <java-symbol type="array" name="config_tether_bluetooth_regexs" />
@@ -1665,6 +1667,7 @@
  <java-symbol type="array" name="config_defaultNotificationVibePattern" />
  <java-symbol type="array" name="config_notificationFallbackVibePattern" />
  <java-symbol type="array" name="config_onlySingleDcAllowed" />
  <java-symbol type="bool" name="config_useNewSensorSamplesForDoze" />
  <java-symbol type="bool" name="config_useAttentionLight" />
  <java-symbol type="bool" name="config_animateScreenLights" />
  <java-symbol type="bool" name="config_automatic_brightness_available" />
+42 −13
Original line number Diff line number Diff line
@@ -109,8 +109,8 @@ class AutomaticBrightnessController {
    // weighting values positive.
    private final int mWeightingIntercept;

    // accessor object for determining thresholds to change brightness dynamically
    private final HysteresisLevels mDynamicHysteresis;
    // accessor object for determining lux levels
    private final LuxLevels mLuxLevels;

    // Amount of time to delay auto-brightness after screen on while waiting for
    // the light sensor to warm-up in milliseconds.
@@ -172,6 +172,9 @@ class AutomaticBrightnessController {
    // Are we going to adjust brightness while dozing.
    private boolean mDozing;

    // True if we are collecting one last light sample when dozing to set the screen brightness
    private boolean mActiveDozeLightSensor = false;

    // True if we are collecting a brightness adjustment sample, along with some data
    // for the initial state of the sample.
    private boolean mBrightnessAdjustmentSamplePending;
@@ -188,7 +191,7 @@ class AutomaticBrightnessController {
            int lightSensorRate, long brighteningLightDebounceConfig,
            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
            int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
            HysteresisLevels dynamicHysteresis) {
            LuxLevels luxLevels) {
        mCallbacks = callbacks;
        mTwilight = LocalServices.getService(TwilightManager.class);
        mSensorManager = sensorManager;
@@ -204,7 +207,7 @@ class AutomaticBrightnessController {
        mAmbientLightHorizon = ambientLightHorizon;
        mWeightingIntercept = ambientLightHorizon;
        mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;
        mDynamicHysteresis = dynamicHysteresis;
        mLuxLevels = luxLevels;

        mHandler = new AutomaticBrightnessHandler(looper);
        mAmbientLightRingBuffer =
@@ -218,7 +221,7 @@ class AutomaticBrightnessController {
    }

    public int getAutomaticScreenBrightness() {
        if (mDozing) {
        if (mDozing && !mLuxLevels.hasDynamicDozeBrightness()) {
            return (int) (mScreenAutoBrightness * mDozeScaleFactor);
        }
        return mScreenAutoBrightness;
@@ -232,13 +235,26 @@ class AutomaticBrightnessController {
        // and hold onto the last computed screen auto brightness.  We save the dozing flag for
        // debugging purposes.
        mDozing = dozing;
        boolean changed = setLightSensorEnabled(enable && !dozing);
        boolean enableSensor = enable && !dozing;
        if (enableSensor && !mLightSensorEnabled && mActiveDozeLightSensor) {
            mActiveDozeLightSensor = false;
        } else if (!enableSensor && mLightSensorEnabled && mLuxLevels.hasDynamicDozeBrightness()) {
            // keep the light sensor active until another light sample is taken in doze mode
            mActiveDozeLightSensor = true;
            if (mLuxLevels.useNewSensorSamplesForDoze()) {
                mAmbientLightRingBuffer.clear();
                mInitialHorizonAmbientLightRingBuffer.clear();
                mAmbientLuxValid = false;
                return;
            }
        }
        boolean changed = setLightSensorEnabled(enableSensor);
        changed |= setScreenAutoBrightnessAdjustment(adjustment);
        changed |= setUseTwilight(useTwilight);
        if (changed) {
            updateAutoBrightness(false /*sendUpdate*/);
        }
        if (enable && !dozing && userInitiatedChange) {
        if (enableSensor && userInitiatedChange) {
            prepareBrightnessAdjustmentSample();
        }
    }
@@ -292,6 +308,9 @@ class AutomaticBrightnessController {
        if (enable) {
            if (!mLightSensorEnabled) {
                mLightSensorEnabled = true;
                mAmbientLightRingBuffer.clear();
                mInitialHorizonAmbientLightRingBuffer.clear();
                mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
                mLightSensorEnableTime = SystemClock.uptimeMillis();
                mSensorManager.registerListener(mLightSensorListener, mLightSensor,
                        mLightSensorRate * 1000, mHandler);
@@ -300,11 +319,9 @@ class AutomaticBrightnessController {
        } else {
            if (mLightSensorEnabled) {
                mLightSensorEnabled = false;
                mAmbientLuxValid = !mResetAmbientLuxAfterWarmUpConfig;
                mRecentLightSamples = 0;
                mAmbientLightRingBuffer.clear();
                mInitialHorizonAmbientLightRingBuffer.clear();
                mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
                Slog.d(TAG, "disabling light sensor");
                mSensorManager.unregisterListener(mLightSensorListener);
            }
        }
@@ -316,6 +333,11 @@ class AutomaticBrightnessController {

        applyLightSensorMeasurement(time, lux);
        updateAmbientLux(time);
        if (mActiveDozeLightSensor) {
            // disable the ambient light sensor and update the screen brightness
            setLightSensorEnabled(false);
            updateAutoBrightness(true /*sendUpdate*/);
        }
    }

    private void applyLightSensorMeasurement(long time, float lux) {
@@ -327,6 +349,7 @@ class AutomaticBrightnessController {
        }
        mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
        mAmbientLightRingBuffer.push(time, lux);
        Slog.d(TAG, "pushing lux: " + lux);

        // Remember this sample value.
        mLastObservedLux = lux;
@@ -343,8 +366,8 @@ class AutomaticBrightnessController {

    private void setAmbientLux(float lux) {
        mAmbientLux = lux;
        mBrighteningLuxThreshold = mDynamicHysteresis.getBrighteningThreshold(lux);
        mDarkeningLuxThreshold = mDynamicHysteresis.getDarkeningThreshold(lux);
        mBrighteningLuxThreshold = mLuxLevels.getBrighteningThreshold(lux);
        mDarkeningLuxThreshold = mLuxLevels.getDarkeningThreshold(lux);
    }

    private float calculateAmbientLux(long now) {
@@ -516,8 +539,14 @@ class AutomaticBrightnessController {
            }
        }

        int newScreenAutoBrightness =
        int newScreenAutoBrightness;
        if (mActiveDozeLightSensor) {
            newScreenAutoBrightness = mLuxLevels.getDozeBrightness(mAmbientLux);
        } else {
            newScreenAutoBrightness =
                clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
        }

        if (mScreenAutoBrightness != newScreenAutoBrightness) {
            if (DEBUG) {
                Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
+19 −10
Original line number Diff line number Diff line
@@ -322,15 +322,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
                1, 1);

        int[] brightLevels = resources.getIntArray(
                com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
        int[] darkLevels = resources.getIntArray(
                com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
        int[] luxLevels = resources.getIntArray(
                com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
        HysteresisLevels dynamicHysteresis = new HysteresisLevels(
                brightLevels, darkLevels, luxLevels);

        if (mUseSoftwareAutoBrightnessConfig) {
            int[] lux = resources.getIntArray(
                    com.android.internal.R.array.config_autoBrightnessLevels);
@@ -342,6 +333,24 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
                    1, 1);

            // hysteresis configs
            int[] brightHysteresisLevels = resources.getIntArray(
                    com.android.internal.R.array.config_dynamicHysteresisBrightLevels);
            int[] darkHysteresisLevels = resources.getIntArray(
                    com.android.internal.R.array.config_dynamicHysteresisDarkLevels);
            int[] luxHysteresisLevels = resources.getIntArray(
                    com.android.internal.R.array.config_dynamicHysteresisLuxLevels);
            // doze brightness configs
            int[] dozeSensorLuxLevels = resources.getIntArray(
                    com.android.internal.R.array.config_dozeSensorLuxLevels);
            int[] dozeBrightnessBacklightValues = resources.getIntArray(
                    com.android.internal.R.array.config_dozeBrightnessBacklightValues);
            boolean useNewSensorSamplesForDoze = resources.getBoolean(
                    com.android.internal.R.bool.config_useNewSensorSamplesForDoze);
            LuxLevels luxLevels = new LuxLevels(brightHysteresisLevels, darkHysteresisLevels,
                    luxHysteresisLevels, useNewSensorSamplesForDoze, dozeSensorLuxLevels,
                    dozeBrightnessBacklightValues);

            Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
            if (screenAutoBrightnessSpline == null) {
                Slog.e(TAG, "Error in config.xml.  config_autoBrightnessLcdBacklightValues "
@@ -368,7 +377,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                        mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate,
                        brighteningLightDebounce, darkeningLightDebounce,
                        autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
                        autoBrightnessAdjustmentMaxGamma, dynamicHysteresis);
                        autoBrightnessAdjustmentMaxGamma, luxLevels);
            }
        }

+145 −0
Original line number Diff line number Diff line
@@ -19,48 +19,63 @@ package com.android.server.display;
import android.util.Slog;

/**
 * A helper class for handling access to illuminance hysteresis level values.
 * A helper class for handling access to illuminance level values.
 */
final class HysteresisLevels {
    private static final String TAG = "HysteresisLevels";
final class LuxLevels {
    private static final String TAG = "LuxLevels";

    // Default hysteresis constraints for brightening or darkening.
    // The recent lux must have changed by at least this fraction relative to the
    // current ambient lux before a change will be considered.
    private static final float DEFAULT_BRIGHTENING_HYSTERESIS = 0.10f;
    private static final float DEFAULT_DARKENING_HYSTERESIS = 0.20f;
    private static final boolean DEBUG = true;

    private static final boolean DEBUG = false;
    private final boolean mUseNewSensorSamplesForDoze;

    private final float[] mBrightLevels;
    private final float[] mDarkLevels;
    private final float[] mLuxLevels;
    private final float[] mLuxHysteresisLevels;
    private final float[] mDozeBacklightLevels;
    private final float[] mDozeSensorLuxLevels;

  /**
   * Creates a {@code HysteresisLevels} object with the given equal-length
   * integer arrays.
   * Creates a {@code LuxLevels} object with the given integer arrays. The following arrays
   * are either empty or have the following relations:
   * {@code brightLevels} and {@code darkLevels} have the same length n.
   * {@code luxLevels} has length n+1.
   *
   * {@code dozeSensorLuxLevels} has length r.
   * {@code dozeBacklightLevels} has length r+1.
   *
   * @param brightLevels an array of brightening hysteresis constraint constants
   * @param darkLevels an array of darkening hysteresis constraint constants
   * @param luxLevels a monotonically increasing array of illuminance
   *                  thresholds in units of lux
   * @param luxHysteresisLevels a monotonically increasing array of illuminance thresholds in lux
   * @param dozeSensorLuxLevels a monotonically increasing array of ALS thresholds in lux
   * @param dozeBacklightLevels an array of screen brightness values for doze mode in lux
   */
    public HysteresisLevels(int[] brightLevels, int[] darkLevels, int[] luxLevels) {
        if (brightLevels.length != darkLevels.length || darkLevels.length != luxLevels.length + 1) {
    public LuxLevels(int[] brightLevels, int[] darkLevels, int[] luxHysteresisLevels,
            boolean useNewSensorSamplesForDoze, int[] dozeSensorLuxLevels,
            int[] dozeBacklightLevels) {
        if (brightLevels.length != darkLevels.length ||
            darkLevels.length !=luxHysteresisLevels.length + 1) {
            throw new IllegalArgumentException("Mismatch between hysteresis array lengths.");
        }
        if (dozeBacklightLevels.length > 0 && dozeSensorLuxLevels.length > 0
            && dozeBacklightLevels.length != dozeSensorLuxLevels.length + 1) {
            throw new IllegalArgumentException("Mismatch between doze lux array lengths.");
        }
        mBrightLevels = setArrayFormat(brightLevels, 1000.0f);
        mDarkLevels = setArrayFormat(darkLevels, 1000.0f);
        mLuxLevels = setArrayFormat(luxLevels, 1.0f);
        mLuxHysteresisLevels = setArrayFormat(luxHysteresisLevels, 1.0f);
        mUseNewSensorSamplesForDoze = useNewSensorSamplesForDoze;
        mDozeSensorLuxLevels = setArrayFormat(dozeSensorLuxLevels, 1.0f);
        mDozeBacklightLevels = setArrayFormat(dozeBacklightLevels, 1.0f);
    }

    /**
     * Return the brightening hysteresis threshold for the given lux level.
     */
    public float getBrighteningThreshold(float lux) {
        float brightConstant = getReferenceLevel(lux, mBrightLevels);
        float brightConstant = getReferenceLevel(lux, mBrightLevels, mLuxHysteresisLevels);
        float brightThreshold = lux * (1.0f + brightConstant);
        if (DEBUG) {
            Slog.d(TAG, "bright hysteresis constant=: " + brightConstant + ", threshold="
            Slog.d(TAG, "bright hysteresis constant= " + brightConstant + ", threshold="
                + brightThreshold + ", lux=" + lux);
        }
        return brightThreshold;
@@ -70,27 +85,53 @@ final class HysteresisLevels {
     * Return the darkening hysteresis threshold for the given lux level.
     */
    public float getDarkeningThreshold(float lux) {
        float darkConstant = getReferenceLevel(lux, mDarkLevels);
        float darkConstant = getReferenceLevel(lux, mDarkLevels, mLuxHysteresisLevels);
        float darkThreshold = lux * (1.0f - darkConstant);
        if (DEBUG) {
            Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold="
            Slog.d(TAG, "dark hysteresis constant= " + darkConstant + ", threshold="
                + darkThreshold + ", lux=" + lux);
        }
        return darkThreshold;
    }

    /**
     * Return the hysteresis constant for the closest lux threshold value to the
     * current illuminance from the given array.
     * Return the doze backlight brightness level for the given ambient sensor lux level.
     */
    public int getDozeBrightness(float lux) {
        int dozeBrightness = (int) getReferenceLevel(lux, mDozeBacklightLevels,
            mDozeSensorLuxLevels);
        if (DEBUG) {
            Slog.d(TAG, "doze brightness: " + dozeBrightness + ", lux=" + lux);
        }
        return dozeBrightness;
    }

    /**
     * Find the index of the closest value in {@code thresholdLevels} to {@code lux} and return
     * the {@code referenceLevels} entry with that index.
     */
    private float getReferenceLevel(float lux, float[] referenceLevels) {
    private float getReferenceLevel(float lux, float[] referenceLevels, float[] thresholdLevels) {
        int index = 0;
        while (mLuxLevels.length > index && lux >= mLuxLevels[index]) {
        while (thresholdLevels.length > index && lux >= thresholdLevels[index]) {
            ++index;
        }
        return referenceLevels[index];
    }

    /**
     * Return if the doze backlight brightness level is specified dynamically.
     */
    public boolean hasDynamicDozeBrightness() {
        return mDozeSensorLuxLevels.length > 0;
    }

    /**
     * Return if new ALS samples should be used for determining screen brightness while dozing.
     */
    public boolean useNewSensorSamplesForDoze() {
        return mUseNewSensorSamplesForDoze;
    }

    /**
     * Return a float array where each i-th element equals {@code configArray[i]/divideFactor}.
     */
Loading