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

Commit 5b825096 authored by Julius D'souza's avatar Julius D'souza
Browse files

DO NOT MERGE: Add light sample filtering logic for devices with

ambient light sensors that can be regularly obstructed.

Bug: 36869173

Change-Id: Ie2a1399c149c87df657b265911a7bb8417a1b8b9
parent a6863457
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1079,6 +1079,27 @@
         to reduce it to preserve the battery. Value of 100% means no scaling. -->
    <fraction name="config_screenAutoBrightnessDozeScaleFactor">100%</fraction>

    <!-- What percentage of possible ambient light sensor values below the current ambient lux
         calculation count count as valid samples. If a new lux sample is below
         (current ambient lux) * (threshold), the light sample is saved in a separate dark light
         buffer. When enough samples have accumulated continuously based off of the current light
         sensor rate and config_autoBrightnessDarkAmbientLightHorizon, the current ambient
         lux and screen brightness are recalculated; otherwise, the dark light buffer is cleared.
         This is useful for devices where the ambient light sensor can expect regular light
         obstruction, e.g. if the sensor is under the screen and a finger moves directly over the
         relevant area.

         This should be used with config_autoBrightnessDarkAmbientLightHorizon set to greater
         than 0 and set to a value less than 100% to be enabled. -->
    <fraction name="config_autoBrightnessDarkHorizonThresholdFactor">100%</fraction>

    <!-- The amount of time that the dark light buffer should hold samples for in milliseconds;
         see the description of config_autoBrightnessDarkHorizonThresholdFactor for details. This
         should be used with config_autoBrightnessDarkHorizonThresholdFactor.

         Set this to 0 to disable this feature. -->
    <integer name="config_autoBrightnessDarkAmbientLightHorizon">0</integer>

    <!-- When the screen is turned on, the previous estimate of the ambient light level at the time
         the screen was turned off is restored and is used to determine the initial screen
         brightness.
+2 −0
Original line number Diff line number Diff line
@@ -1736,8 +1736,10 @@
  <java-symbol type="dimen" name="default_minimal_size_resizable_task" />
  <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
  <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
  <java-symbol type="fraction" name="config_autoBrightnessDarkHorizonThresholdFactor" />
  <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
  <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
  <java-symbol type="integer" name="config_autoBrightnessDarkAmbientLightHorizon"/>
  <java-symbol type="integer" name="config_autoBrightnessDarkeningLightDebounce"/>
  <java-symbol type="integer" name="config_autoBrightnessInitialLightSensorRate"/>
  <java-symbol type="integer" name="config_autoBrightnessLightSensorRate"/>
+59 −6
Original line number Diff line number Diff line
@@ -35,11 +35,13 @@ import android.os.SystemClock;
import android.text.format.DateUtils;
import android.util.EventLog;
import android.util.MathUtils;
import android.util.Pair;
import android.util.Spline;
import android.util.Slog;
import android.util.TimeUtils;

import java.io.PrintWriter;
import java.util.ArrayDeque;

class AutomaticBrightnessController {
    private static final String TAG = "AutomaticBrightnessController";
@@ -111,6 +113,9 @@ class AutomaticBrightnessController {
    // Period of time in which to consider light samples in milliseconds.
    private final int mAmbientLightHorizon;

    // Period of time in which to consider light samples below the current ambient lux threshold.
    private final int mDarkAmbientLightHorizon;

    // The intercept used for the weighting calculation. This is used in order to keep all possible
    // weighting values positive.
    private final int mWeightingIntercept;
@@ -139,6 +144,10 @@ class AutomaticBrightnessController {
    private float mBrighteningLuxThreshold;
    private float mDarkeningLuxThreshold;

    // The percentage of possible values below the current ambient lux which we put in the dark
    // ambient light buffer.
    private final float mDarkHorizonThresholdFactor;

    // The most recent light sample.
    private float mLastObservedLux;

@@ -148,6 +157,14 @@ class AutomaticBrightnessController {
    // The number of light samples collected since the light sensor was enabled.
    private int mRecentLightSamples;

    // The number of light samples that will be held in the deque before being moved to the
    // light ring buffer.
    private int mDarkAmbientLightSampleSize;

    // A deque containing the light sensor readings below the current ambient lux threshold
    // when the display is not dozing.
    private ArrayDeque<Pair<Long, Float>> mDarkAmbientLightDeque;

    // A ring buffer containing all of the recent ambient light sensor readings.
    private AmbientLightRingBuffer mAmbientLightRingBuffer;

@@ -203,7 +220,7 @@ class AutomaticBrightnessController {
            long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig,
            int ambientLightHorizon, float autoBrightnessAdjustmentMaxGamma,
            boolean activeDozeLightSensor, boolean useNewSensorSamplesForDoze,
            LuxLevels luxLevels) {
            float darkHorizonThresholdFactor, int darkAmbientLightHorizon, LuxLevels luxLevels) {
        mCallbacks = callbacks;
        mTwilight = LocalServices.getService(TwilightManager.class);
        mSensorManager = sensorManager;
@@ -223,6 +240,8 @@ class AutomaticBrightnessController {
        mScreenAutoBrightnessAdjustmentMaxGamma = autoBrightnessAdjustmentMaxGamma;
        mUseNewSensorSamplesForDoze = useNewSensorSamplesForDoze;
        mUseActiveDozeLightSensorConfig = activeDozeLightSensor;
        mDarkHorizonThresholdFactor = darkHorizonThresholdFactor;
        mDarkAmbientLightHorizon = darkAmbientLightHorizon;
        mLuxLevels = luxLevels;

        mHandler = new AutomaticBrightnessHandler(looper);
@@ -231,6 +250,10 @@ class AutomaticBrightnessController {
        mInitialHorizonAmbientLightRingBuffer =
            new AmbientLightRingBuffer(mNormalLightSensorRate, mAmbientLightHorizon);

        mDarkAmbientLightSampleSize =
                (int) Math.ceil(darkAmbientLightHorizon / mNormalLightSensorRate);
        mDarkAmbientLightDeque = new ArrayDeque<>();

        if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
            mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
        }
@@ -344,6 +367,7 @@ class AutomaticBrightnessController {
                mCurrentLightSensorRate = -1;
                mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
                mSensorManager.unregisterListener(mLightSensorListener);
                mDarkAmbientLightDeque.clear();
            }
        }
        return false;
@@ -375,14 +399,43 @@ class AutomaticBrightnessController {
        if (time <= mLightSensorEnableTime + mAmbientLightHorizon) {
            mInitialHorizonAmbientLightRingBuffer.push(time, lux);
        }

        // Only consider light samples for the dark light deque when not dozing.
        // and once we've collected enough samples regularly.
        if (mDarkAmbientLightHorizon > 0
                && !mDozing
                && mRecentLightSamples >= mDarkAmbientLightSampleSize
                && mAmbientLux * mDarkHorizonThresholdFactor >= lux) {
            mDarkAmbientLightDeque.addLast(new Pair(time, lux));
            if (DEBUG) {
                Slog.d(TAG, "applyLightSensorMeasurement: light sample filtered to deque: "
                        + mDarkAmbientLightDeque.size() + " / " + mDarkAmbientLightSampleSize);
            }
            if (mDarkAmbientLightSampleSize <= mDarkAmbientLightDeque.size()) {
                if (DEBUG) {
                    Slog.d(TAG, "applyLightSensorMeasurement: moving filtered samples from the "
                            + "deque to the light ring buffer.");
                }
                for (Pair<Long, Float> lightSample : mDarkAmbientLightDeque) {
                    mAmbientLightRingBuffer.push(lightSample.first, lightSample.second);
                }
                mDarkAmbientLightDeque.clear();
                mLastObservedLux = lux;
                mLastObservedLuxTime = time;
                updateAmbientLux();
            }
        } else {
            mAmbientLightRingBuffer.prune(time - mAmbientLightHorizon);
            mAmbientLightRingBuffer.push(time, lux);
            mDarkAmbientLightDeque.clear();

            // Remember this sample value.
            mLastObservedLux = lux;
            mLastObservedLuxTime = time;
        }

    }

    private void adjustLightSensorRate(int lightSensorRate) {
        // if the light sensor rate changed, update the sensor listener
        if (lightSensorRate != mCurrentLightSensorRate) {
+7 −1
Original line number Diff line number Diff line
@@ -363,6 +363,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            final float dozeScaleFactor = resources.getFraction(
                    com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
                    1, 1);
            final float darkHorizonThresholdFactor = resources.getFraction(
                    com.android.internal.R.fraction.config_autoBrightnessDarkHorizonThresholdFactor,
                    1, 1);
            final int darkAmbientLightHorizon = resources.getInteger(
                    com.android.internal.R.integer.config_autoBrightnessDarkAmbientLightHorizon);

            // hysteresis configs
            int[] brightHysteresisLevels = resources.getIntArray(
@@ -410,7 +415,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                        initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                        autoBrightnessResetAmbientLuxAfterWarmUp, ambientLightHorizon,
                        autoBrightnessAdjustmentMaxGamma, mUseActiveDozeLightSensorConfig,
                        useNewSensorSamplesForDoze, luxLevels);
                        useNewSensorSamplesForDoze, darkHorizonThresholdFactor,
                        darkAmbientLightHorizon, luxLevels);
            }
        }