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

Commit 129b7d26 authored by Fiona Campbell's avatar Fiona Campbell Committed by Gerrit Code Review
Browse files

Merge "LightSensorController extraction from BrightnessClamperContorller" into main

parents 896d744e 87651547
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -587,7 +587,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                        mUniqueDisplayId,
                        mThermalBrightnessThrottlingDataId,
                        logicalDisplay.getPowerThrottlingDataIdLocked(),
                        mDisplayDeviceConfig), mContext, flags, mSensorManager);
                        mDisplayDeviceConfig,
                        mDisplayId), mContext, flags, mSensorManager);
        // Seed the cached brightness
        saveBrightnessInfo(getScreenBrightnessSetting());
        mAutomaticBrightnessStrategy =
@@ -892,7 +893,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
            // will call updatePowerState if needed.
            mBrightnessClamperController.onDisplayChanged(
                    new BrightnessClamperController.DisplayDeviceData(uniqueId,
                        thermalBrightnessThrottlingDataId, powerThrottlingDataId, config));
                            thermalBrightnessThrottlingDataId, powerThrottlingDataId,
                            config, mDisplayId));

            if (changed) {
                updatePowerState();
+52 −112
Original line number Diff line number Diff line
@@ -23,23 +23,17 @@ import static com.android.server.display.brightness.clamper.BrightnessClamper.Ty
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManagerInternal;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.PowerManager;
import android.os.SystemClock;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.util.IndentingPrintWriter;
import android.util.Slog;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayBrightnessState;
import com.android.server.display.DisplayDeviceConfig;
@@ -50,30 +44,22 @@ import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.config.SensorData;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
import com.android.server.display.utils.DebugUtils;
import com.android.server.display.utils.SensorUtils;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * Clampers controller, all in DisplayControllerHandler
 */
public class BrightnessClamperController {
    private static final String TAG = "BrightnessClamperController";
    // To enable these logs, run:
    // 'adb shell setprop persist.log.tag.BrightnessClamperController DEBUG && adb reboot'
    private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
    public static final float INVALID_LUX = -1f;

    private final DeviceConfigParameterProvider mDeviceConfigParameterProvider;
    private final Handler mHandler;
    private final SensorManager mSensorManager;
    private final LightSensorController mLightSensorController;

    private final ClamperChangeListener mClamperChangeListenerExternal;
    private final Executor mExecutor;
    private final List<BrightnessClamper<? super DisplayDeviceData>> mClampers;
@@ -85,70 +71,49 @@ public class BrightnessClamperController {
    private float mCustomAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET;
    @Nullable
    private Type mClamperType = null;
    private final SensorEventListener mLightSensorListener;
    private Sensor mRegisteredLightSensor = null;
    private Sensor mLightSensor;
    private String mLightSensorType;
    private String mLightSensorName;
    private AmbientFilter mAmbientFilter;
    private final DisplayDeviceConfig mDisplayDeviceConfig;
    private final Resources mResources;
    private final int mLightSensorRate;

    private final Injector mInjector;
    private boolean mClamperApplied = false;

    private final LightSensorController.LightSensorListener mLightSensorListener =
            new LightSensorController.LightSensorListener() {
                @Override
                public void onAmbientLuxChange(float lux) {
                    mModifiers.forEach(mModifier -> mModifier.setAmbientLux(lux));
                }
            };

    public BrightnessClamperController(Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context,
            DisplayManagerFlags flags, SensorManager sensorManager) {
        this(null, handler, clamperChangeListener, data, context, flags, sensorManager);
        this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager);
    }

    @VisibleForTesting
    BrightnessClamperController(Injector injector, Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context,
            DisplayManagerFlags flags, SensorManager sensorManager) {
        mInjector = injector == null ? new Injector() : injector;
        mDeviceConfigParameterProvider = mInjector.getDeviceConfigParameterProvider();
        mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider();
        mHandler = handler;
        mSensorManager = sensorManager;
        mDisplayDeviceConfig = data.mDisplayDeviceConfig;
        mLightSensorListener = new SensorEventListener() {
            @Override
            public void onSensorChanged(SensorEvent event) {
                long now = SystemClock.elapsedRealtime();
                mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp),
                        event.values[0]);
                final float lux = mAmbientFilter.getEstimate(now);
                mModifiers.forEach(mModifier -> mModifier.setAmbientLux(lux));
            }

            @Override
            public void onAccuracyChanged(Sensor sensor, int accuracy) {
                // unused
            }
        };
        mLightSensorController = injector.getLightSensorController(sensorManager, context,
                mLightSensorListener, mHandler);

        mClamperChangeListenerExternal = clamperChangeListener;
        mExecutor = new HandlerExecutor(handler);
        mResources = context.getResources();
        mLightSensorRate = context.getResources().getInteger(
                R.integer.config_autoBrightnessLightSensorRate);

        Runnable clamperChangeRunnableInternal = this::recalculateBrightnessCap;

        ClamperChangeListener clamperChangeListenerInternal = () -> {
            if (!mHandler.hasCallbacks(clamperChangeRunnableInternal)) {
                mHandler.post(clamperChangeRunnableInternal);
            }
        };

        mClampers = mInjector.getClampers(handler, clamperChangeListenerInternal, data, flags,
        mClampers = injector.getClampers(handler, clamperChangeListenerInternal, data, flags,
                context);
        mModifiers = mInjector.getModifiers(flags, context, handler, clamperChangeListener,
                data.mDisplayDeviceConfig, mSensorManager);
        mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener,
                data.mDisplayDeviceConfig);
        mOnPropertiesChangedListener =
                properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
        mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId());
        start();
    }

@@ -156,7 +121,9 @@ public class BrightnessClamperController {
     * Should be called when display changed. Forwards the call to individual clampers
     */
    public void onDisplayChanged(DisplayDeviceData data) {
        mLightSensorController.configure(data.getAmbientLightSensor(), data.getDisplayId());
        mClampers.forEach(clamper -> clamper.onDisplayChanged(data));
        adjustLightSensorSubscription();
    }

    /**
@@ -184,9 +151,9 @@ public class BrightnessClamperController {
        }

        if (displayState != STATE_ON) {
            unregisterSensorListener();
            mLightSensorController.stop();
        } else {
            maybeRegisterLightSensor();
            adjustLightSensorSubscription();
        }

        for (int i = 0; i < mModifiers.size(); i++) {
@@ -231,9 +198,8 @@ public class BrightnessClamperController {
        writer.println("  mBrightnessCap: " + mBrightnessCap);
        writer.println("  mClamperType: " + mClamperType);
        writer.println("  mClamperApplied: " + mClamperApplied);
        writer.println("  mLightSensor=" + mLightSensor);
        writer.println("  mRegisteredLightSensor=" + mRegisteredLightSensor);
        IndentingPrintWriter ipw = new IndentingPrintWriter(writer, "    ");
        mLightSensorController.dump(ipw);
        mClampers.forEach(clamper -> clamper.dump(ipw));
        mModifiers.forEach(modifier -> modifier.dump(ipw));
    }
@@ -245,6 +211,7 @@ public class BrightnessClamperController {
    public void stop() {
        mDeviceConfigParameterProvider.removeOnPropertiesChangedListener(
                mOnPropertiesChangedListener);
        mLightSensorController.stop();
        mClampers.forEach(BrightnessClamper::stop);
        mModifiers.forEach(BrightnessStateModifier::stop);
    }
@@ -281,10 +248,15 @@ public class BrightnessClamperController {
        if (!mClampers.isEmpty()) {
            mDeviceConfigParameterProvider.addOnPropertiesChangedListener(
                    mExecutor, mOnPropertiesChangedListener);
            reloadLightSensorData(mDisplayDeviceConfig);
            mLightSensor = mInjector.getLightSensor(
                    mSensorManager, mLightSensorType, mLightSensorName);
            maybeRegisterLightSensor();
        }
        adjustLightSensorSubscription();
    }

    private void adjustLightSensorSubscription() {
        if (mModifiers.stream().anyMatch(BrightnessStateModifier::shouldListenToLightSensor)) {
            mLightSensorController.restart();
        } else {
            mLightSensorController.stop();
        }
    }

@@ -323,7 +295,7 @@ public class BrightnessClamperController {

        List<BrightnessStateModifier> getModifiers(DisplayManagerFlags flags, Context context,
                Handler handler, ClamperChangeListener listener,
                DisplayDeviceConfig displayDeviceConfig, SensorManager sensorManager) {
                DisplayDeviceConfig displayDeviceConfig) {
            List<BrightnessStateModifier> modifiers = new ArrayList<>();
            modifiers.add(new DisplayDimModifier(context));
            modifiers.add(new BrightnessLowPowerModeModifier());
@@ -335,11 +307,12 @@ public class BrightnessClamperController {
            return modifiers;
        }

        Sensor getLightSensor(SensorManager sensorManager, String type, String name) {
            return SensorUtils.findSensor(sensorManager, type,
                    name, Sensor.TYPE_LIGHT);
        LightSensorController getLightSensorController(SensorManager sensorManager,
                Context context, LightSensorController.LightSensorListener listener,
                Handler handler) {
            return new LightSensorController(sensorManager, context.getResources(),
                    listener, handler);
        }

    }

    /**
@@ -354,17 +327,21 @@ public class BrightnessClamperController {
        private final String mThermalThrottlingDataId;
        @NonNull
        private final String mPowerThrottlingDataId;

        @NonNull
        private final DisplayDeviceConfig mDisplayDeviceConfig;

        private final int mDisplayId;

        public DisplayDeviceData(@NonNull String uniqueDisplayId,
                @NonNull String thermalThrottlingDataId,
                @NonNull String powerThrottlingDataId,
                @NonNull DisplayDeviceConfig displayDeviceConfig) {
                @NonNull DisplayDeviceConfig displayDeviceConfig,
                int displayId) {
            mUniqueDisplayId = uniqueDisplayId;
            mThermalThrottlingDataId = thermalThrottlingDataId;
            mPowerThrottlingDataId = powerThrottlingDataId;
            mDisplayDeviceConfig = displayDeviceConfig;
            mDisplayId = displayId;
        }


@@ -412,55 +389,18 @@ public class BrightnessClamperController {
        }

        @NonNull
        @Override
        public SensorData getTempSensor() {
            return mDisplayDeviceConfig.getTempSensor();
        }
    }

    private void maybeRegisterLightSensor() {
        if (mModifiers.stream().noneMatch(BrightnessStateModifier::shouldListenToLightSensor)) {
            return;
        }

        if (mRegisteredLightSensor == mLightSensor) {
            return;
        }

        if (mRegisteredLightSensor != null) {
            unregisterSensorListener();
        }

        mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, mResources);
        mSensorManager.registerListener(mLightSensorListener,
                mLightSensor, mLightSensorRate * 1000, mHandler);
        mRegisteredLightSensor = mLightSensor;

        if (DEBUG) {
            Slog.d(TAG, "maybeRegisterLightSensor");
        }
    }

    private void unregisterSensorListener() {
        mSensorManager.unregisterListener(mLightSensorListener);
        mRegisteredLightSensor = null;
        mModifiers.forEach(mModifier -> mModifier.setAmbientLux(INVALID_LUX)); // set lux to invalid
        if (DEBUG) {
            Slog.d(TAG, "unregisterSensorListener");
        }
        @NonNull
        SensorData getAmbientLightSensor() {
            return mDisplayDeviceConfig.getAmbientLightSensor();
        }

    private void reloadLightSensorData(DisplayDeviceConfig displayDeviceConfig) {
        // The displayDeviceConfig (ddc) contains display specific preferences. When loaded,
        // it naturally falls back to the global config.xml.
        if (displayDeviceConfig != null
                && displayDeviceConfig.getAmbientLightSensor() != null) {
            // This covers both the ddc and the config.xml fallback
            mLightSensorType = displayDeviceConfig.getAmbientLightSensor().type;
            mLightSensorName = displayDeviceConfig.getAmbientLightSensor().name;
        } else if (mLightSensorName == null && mLightSensorType == null) {
            mLightSensorType = mResources.getString(
                    com.android.internal.R.string.config_displayLightSensorType);
            mLightSensorName = "";
        int getDisplayId() {
            return mDisplayId;
        }
    }
}
+163 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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.clamper;

import android.annotation.Nullable;
import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Slog;
import android.view.Display;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.config.SensorData;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
import com.android.server.display.utils.DebugUtils;
import com.android.server.display.utils.SensorUtils;

import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;

/**
 * Manages light sensor subscription and notifies its listener about ambient lux changes
 */
public class LightSensorController {
    private static final String TAG = "LightSensorController";

    // To enable these logs, run:
    // 'adb shell setprop persist.log.tag.LightSensorController DEBUG && adb reboot'
    private static final boolean DEBUG = DebugUtils.isDebuggable(TAG);
    static final float INVALID_LUX = -1f;

    private final SensorManager mSensorManager;
    private final LightSensorListener mLightSensorListener;
    private final Handler mHandler;
    private final Injector mInjector;
    private final AmbientFilter mAmbientFilter;

    private Sensor mLightSensor;
    private Sensor mRegisteredLightSensor = null;
    private final int mLightSensorRate;

    private final SensorEventListener mLightSensorEventListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            long now = mInjector.getTime();
            mAmbientFilter.addValue(TimeUnit.NANOSECONDS.toMillis(event.timestamp),
                    event.values[0]);
            final float lux = mAmbientFilter.getEstimate(now);
            mLightSensorListener.onAmbientLuxChange(lux);
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {
            // unused
        }
    };

    LightSensorController(SensorManager sensorManager, Resources resources,
            LightSensorListener listener, Handler handler) {
        this(sensorManager, resources, listener, handler, new Injector());
    }

    @VisibleForTesting
    LightSensorController(SensorManager sensorManager, Resources resources,
            LightSensorListener listener, Handler handler, Injector injector) {
        mSensorManager = sensorManager;
        mLightSensorRate = injector.getLightSensorRate(resources);
        mAmbientFilter = injector.getAmbientFilter(resources);
        mLightSensorListener = listener;
        mHandler = handler;
        mInjector = injector;
    }

    void restart() {
        if (mRegisteredLightSensor == mLightSensor) {
            return;
        }
        if (mRegisteredLightSensor != null) {
            stop();
        }
        if (mLightSensor == null) {
            return;
        }

        mSensorManager.registerListener(mLightSensorEventListener,
                mLightSensor, mLightSensorRate * 1000, mHandler);
        mRegisteredLightSensor = mLightSensor;

        if (DEBUG) {
            Slog.d(TAG, "restart");
        }
    }

    void stop() {
        if (mRegisteredLightSensor == null) {
            return;
        }
        mSensorManager.unregisterListener(mLightSensorEventListener);
        mRegisteredLightSensor = null;
        mAmbientFilter.clear();
        mLightSensorListener.onAmbientLuxChange(INVALID_LUX);
        if (DEBUG) {
            Slog.d(TAG, "stop");
        }
    }

    void configure(SensorData sensorData, int displayId) {
        final int fallbackType = displayId == Display.DEFAULT_DISPLAY
                ? Sensor.TYPE_LIGHT : SensorUtils.NO_FALLBACK;
        mLightSensor = mInjector.getLightSensor(mSensorManager, sensorData, fallbackType);
    }

    void dump(PrintWriter writer) {
        writer.println("LightSensorController");
        writer.println("  mLightSensor=" + mLightSensor);
        writer.println("  mRegisteredLightSensor=" + mRegisteredLightSensor);
    }

    static class Injector {
        @Nullable
        Sensor getLightSensor(SensorManager sensorManager, SensorData sensorData,
                int fallbackType) {
            return SensorUtils.findSensor(sensorManager, sensorData, fallbackType);
        }

        AmbientFilter getAmbientFilter(Resources resources) {
            return AmbientFilterFactory.createBrightnessFilter(TAG, resources);
        }

        int getLightSensorRate(Resources resources) {
            return resources.getInteger(R.integer.config_autoBrightnessLightSensorRate);
        }

        // should be consistent with SensorEvent.timestamp
        long getTime() {
            return SystemClock.elapsedRealtime();
        }
    }

    interface  LightSensorListener {
        void onAmbientLuxChange(float ambientLux);
    }
}
+78 −35

File changed.

Preview size limit exceeded, changes collapsed.

+168 −0

File added.

Preview size limit exceeded, changes collapsed.