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

Commit 562760e4 authored by Oleg Petsjonkin's avatar Oleg Petsjonkin
Browse files

Introducing clampers to DPC

Introduced base BrightnessClamper and BrightnessClampersContorller - aggregator for all future clampers. DeviceConfig string parsing code is moved to DeviceConfigParsingUtils and generalised for similar structure parsing.

Bug: b/263362199
Test: atest com.android.server.display.utils atest com.server.display.brightness
Change-Id: Ifcc94abb04ad6d049f8acde1d6e9bda849b45022
parent 7283fc8b
Loading
Loading
Loading
Loading
+27 −107
Original line number Original line Diff line number Diff line
@@ -38,17 +38,24 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.utils.DeviceConfigParsingUtils;


import java.io.PrintWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executor;
import java.util.function.BiFunction;
import java.util.function.Function;


/**
/**
 * This class monitors various conditions, such as skin temperature throttling status, and limits
 * This class monitors various conditions, such as skin temperature throttling status, and limits
 * the allowed brightness range accordingly.
 * the allowed brightness range accordingly.
 *
 * @deprecated will be replaced by
 * {@link com.android.server.display.brightness.clamper.BrightnessThermalClamper}
 */
 */
@Deprecated
class BrightnessThrottler {
class BrightnessThrottler {
    private static final String TAG = "BrightnessThrottler";
    private static final String TAG = "BrightnessThrottler";
    private static final boolean DEBUG = false;
    private static final boolean DEBUG = false;
@@ -93,8 +100,21 @@ class BrightnessThrottler {
    // time the underlying display device changes.
    // time the underlying display device changes.
    // This map is indexed by uniqueDisplayId, to provide maps for throttlingId -> throttlingData.
    // This map is indexed by uniqueDisplayId, to provide maps for throttlingId -> throttlingData.
    // HashMap< uniqueDisplayId, HashMap< throttlingDataId, ThermalBrightnessThrottlingData >>
    // HashMap< uniqueDisplayId, HashMap< throttlingDataId, ThermalBrightnessThrottlingData >>
    private final HashMap<String, HashMap<String, ThermalBrightnessThrottlingData>>
    private final Map<String, Map<String, ThermalBrightnessThrottlingData>>
            mThermalBrightnessThrottlingDataOverride = new HashMap<>(1);
            mThermalBrightnessThrottlingDataOverride = new HashMap<>();

    private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> {
        try {
            int status = DeviceConfigParsingUtils.parseThermalStatus(key);
            float brightnessPoint = DeviceConfigParsingUtils.parseBrightness(value);
            return new ThrottlingLevel(status, brightnessPoint);
        } catch (IllegalArgumentException iae) {
            return null;
        }
    };

    private final Function<List<ThrottlingLevel>, ThermalBrightnessThrottlingData>
            mDataSetMapper = ThermalBrightnessThrottlingData::create;


    BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId,
    BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId,
            String throttlingDataId,
            String throttlingDataId,
@@ -257,79 +277,15 @@ class BrightnessThrottler {
    // 456,2,moderate,0.9,critical,0.7,id_2
    // 456,2,moderate,0.9,critical,0.7,id_2
    // displayId, number, <state, val> * number
    // displayId, number, <state, val> * number
    // displayId, <number, <state, val> * number>, throttlingId
    // displayId, <number, <state, val> * number>, throttlingId
    private boolean parseAndAddData(@NonNull String strArray,
            @NonNull HashMap<String, HashMap<String, ThermalBrightnessThrottlingData>>
                    displayIdToThrottlingIdToBtd) {
        boolean validConfig = true;
        String[] items = strArray.split(",");
        int i = 0;

        try {
            String uniqueDisplayId = items[i++];

            // number of throttling points
            int noOfThrottlingPoints = Integer.parseInt(items[i++]);
            List<ThrottlingLevel> throttlingLevels = new ArrayList<>(noOfThrottlingPoints);

            // throttling level and point
            for (int j = 0; j < noOfThrottlingPoints; j++) {
                String severity = items[i++];
                int status = parseThermalStatus(severity);
                float brightnessPoint = parseBrightness(items[i++]);
                throttlingLevels.add(new ThrottlingLevel(status, brightnessPoint));
            }

            String throttlingDataId = (i < items.length) ? items[i++] : DEFAULT_ID;
            ThermalBrightnessThrottlingData throttlingLevelsData =
                    DisplayDeviceConfig.ThermalBrightnessThrottlingData.create(throttlingLevels);

            // Add throttlingLevelsData to inner map where necessary.
            HashMap<String, ThermalBrightnessThrottlingData> throttlingMapForDisplay =
                    displayIdToThrottlingIdToBtd.get(uniqueDisplayId);
            if (throttlingMapForDisplay == null) {
                throttlingMapForDisplay = new HashMap<>();
                throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData);
                displayIdToThrottlingIdToBtd.put(uniqueDisplayId, throttlingMapForDisplay);
            } else if (throttlingMapForDisplay.containsKey(throttlingDataId)) {
                Slog.e(TAG, "Throttling data for display " + uniqueDisplayId
                        + "contains duplicate throttling ids: '" + throttlingDataId + "'");
                return false;
            } else {
                throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData);
            }
        } catch (NumberFormatException | IndexOutOfBoundsException
                | UnknownThermalStatusException e) {
            Slog.e(TAG, "Throttling data is invalid array: '" + strArray + "'", e);
            validConfig = false;
        }

        if (i != items.length) {
            validConfig = false;
        }
        return validConfig;
    }

    private void loadThermalBrightnessThrottlingDataFromDeviceConfig() {
    private void loadThermalBrightnessThrottlingDataFromDeviceConfig() {
        HashMap<String, HashMap<String, ThermalBrightnessThrottlingData>> tempThrottlingData =
                new HashMap<>(1);
        mThermalBrightnessThrottlingDataString =
        mThermalBrightnessThrottlingDataString =
                mConfigParameterProvider.getBrightnessThrottlingData();
                mConfigParameterProvider.getBrightnessThrottlingData();
        boolean validConfig = true;
        mThermalBrightnessThrottlingDataOverride.clear();
        mThermalBrightnessThrottlingDataOverride.clear();
        if (mThermalBrightnessThrottlingDataString != null) {
        if (mThermalBrightnessThrottlingDataString != null) {
            String[] throttlingDataSplits = mThermalBrightnessThrottlingDataString.split(";");
            Map<String, Map<String, ThermalBrightnessThrottlingData>> tempThrottlingData =
            for (String s : throttlingDataSplits) {
                    DeviceConfigParsingUtils.parseDeviceConfigMap(
                if (!parseAndAddData(s, tempThrottlingData)) {
                    mThermalBrightnessThrottlingDataString, mDataPointMapper, mDataSetMapper);
                    validConfig = false;
                    break;
                }
            }

            if (validConfig) {
            mThermalBrightnessThrottlingDataOverride.putAll(tempThrottlingData);
            mThermalBrightnessThrottlingDataOverride.putAll(tempThrottlingData);
                tempThrottlingData.clear();
            }

        } else {
        } else {
            Slog.w(TAG, "DeviceConfig ThermalBrightnessThrottlingData is null");
            Slog.w(TAG, "DeviceConfig ThermalBrightnessThrottlingData is null");
        }
        }
@@ -395,42 +351,6 @@ class BrightnessThrottler {
        }
        }
    }
    }


    private float parseBrightness(String intVal) throws NumberFormatException {
        float value = Float.parseFloat(intVal);
        if (value < PowerManager.BRIGHTNESS_MIN || value > PowerManager.BRIGHTNESS_MAX) {
            throw new NumberFormatException("Brightness constraint value out of bounds.");
        }
        return value;
    }

    @PowerManager.ThermalStatus private int parseThermalStatus(@NonNull String value)
            throws UnknownThermalStatusException {
        switch (value) {
            case "none":
                return PowerManager.THERMAL_STATUS_NONE;
            case "light":
                return PowerManager.THERMAL_STATUS_LIGHT;
            case "moderate":
                return PowerManager.THERMAL_STATUS_MODERATE;
            case "severe":
                return PowerManager.THERMAL_STATUS_SEVERE;
            case "critical":
                return PowerManager.THERMAL_STATUS_CRITICAL;
            case "emergency":
                return PowerManager.THERMAL_STATUS_EMERGENCY;
            case "shutdown":
                return PowerManager.THERMAL_STATUS_SHUTDOWN;
            default:
                throw new UnknownThermalStatusException("Invalid Thermal Status: " + value);
        }
    }

    private static class UnknownThermalStatusException extends Exception {
        UnknownThermalStatusException(String message) {
            super(message);
        }
    }

    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
        private final Injector mInjector;
        private final Injector mInjector;
        private final Handler mHandler;
        private final Handler mHandler;
+7 −3
Original line number Original line Diff line number Diff line
@@ -458,7 +458,7 @@ public class DisplayDeviceConfig {


    public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";
    public static final String QUIRK_CAN_SET_BRIGHTNESS_VIA_HWC = "canSetBrightnessViaHwc";


    static final String DEFAULT_ID = "default";
    public static final String DEFAULT_ID = "default";


    private static final float BRIGHTNESS_DEFAULT = 0.5f;
    private static final float BRIGHTNESS_DEFAULT = 0.5f;
    private static final String ETC_DIR = "etc";
    private static final String ETC_DIR = "etc";
@@ -3127,11 +3127,15 @@ public class DisplayDeviceConfig {
    public static class ThermalBrightnessThrottlingData {
    public static class ThermalBrightnessThrottlingData {
        public List<ThrottlingLevel> throttlingLevels;
        public List<ThrottlingLevel> throttlingLevels;


        static class ThrottlingLevel {
        /**
         * thermal status to brightness cap holder
         */
        public static class ThrottlingLevel {
            public @PowerManager.ThermalStatus int thermalStatus;
            public @PowerManager.ThermalStatus int thermalStatus;
            public float brightness;
            public float brightness;


            ThrottlingLevel(@PowerManager.ThermalStatus int thermalStatus, float brightness) {
            public ThrottlingLevel(
                    @PowerManager.ThermalStatus int thermalStatus, float brightness) {
                this.thermalStatus = thermalStatus;
                this.thermalStatus = thermalStatus;
                this.brightness = brightness;
                this.brightness = brightness;
            }
            }
+23 −1
Original line number Original line Diff line number Diff line
@@ -48,6 +48,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings;
import android.util.FloatProperty;
import android.util.FloatProperty;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Log;
import android.util.MathUtils;
import android.util.MathUtils;
import android.util.MutableFloat;
import android.util.MutableFloat;
@@ -64,7 +65,6 @@ import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.RingBuffer;
import com.android.internal.util.RingBuffer;
import com.android.server.LocalServices;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.am.BatteryStatsService;
@@ -73,6 +73,7 @@ import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessReason;
import com.android.server.display.brightness.BrightnessUtils;
import com.android.server.display.brightness.BrightnessUtils;
import com.android.server.display.brightness.DisplayBrightnessController;
import com.android.server.display.brightness.DisplayBrightnessController;
import com.android.server.display.brightness.clamper.BrightnessClamperController;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ColorDisplayServiceInternal;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
import com.android.server.display.color.ColorDisplayService.ReduceBrightColorsListener;
@@ -380,6 +381,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal


    private final BrightnessThrottler mBrightnessThrottler;
    private final BrightnessThrottler mBrightnessThrottler;


    private final BrightnessClamperController mBrightnessClamperController;

    private final Runnable mOnBrightnessChangeRunnable;
    private final Runnable mOnBrightnessChangeRunnable;


    private final BrightnessEvent mLastBrightnessEvent;
    private final BrightnessEvent mLastBrightnessEvent;
@@ -554,6 +557,13 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
                        mDisplayId, mLogicalDisplay.getDisplayInfoLocked().brightnessDefault,
                        mDisplayId, mLogicalDisplay.getDisplayInfoLocked().brightnessDefault,
                        brightnessSetting, () -> postBrightnessChangeRunnable(),
                        brightnessSetting, () -> postBrightnessChangeRunnable(),
                        new HandlerExecutor(mHandler));
                        new HandlerExecutor(mHandler));

        mBrightnessClamperController = new BrightnessClamperController(mHandler,
                modeChangeCallback::run, new BrightnessClamperController.DisplayDeviceData(
                mUniqueDisplayId,
                mThermalBrightnessThrottlingDataId,
                mDisplayDeviceConfig
        ));
        // Seed the cached brightness
        // Seed the cached brightness
        saveBrightnessInfo(getScreenBrightnessSetting());
        saveBrightnessInfo(getScreenBrightnessSetting());


@@ -782,6 +792,10 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        final String thermalBrightnessThrottlingDataId =
        final String thermalBrightnessThrottlingDataId =
                mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;
                mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId;


        mBrightnessClamperController.onDisplayChanged(
                new BrightnessClamperController.DisplayDeviceData(mUniqueDisplayId,
                        mThermalBrightnessThrottlingDataId, config));

        mHandler.postAtTime(() -> {
        mHandler.postAtTime(() -> {
            boolean changed = false;
            boolean changed = false;
            if (mDisplayDevice != device) {
            if (mDisplayDevice != device) {
@@ -1187,6 +1201,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        mDisplayPowerProximityStateController.cleanup();
        mDisplayPowerProximityStateController.cleanup();
        mBrightnessRangeController.stop();
        mBrightnessRangeController.stop();
        mBrightnessThrottler.stop();
        mBrightnessThrottler.stop();
        mBrightnessClamperController.stop();
        mHandler.removeCallbacksAndMessages(null);
        mHandler.removeCallbacksAndMessages(null);


        // Release any outstanding wakelocks we're still holding because of pending messages.
        // Release any outstanding wakelocks we're still holding because of pending messages.
@@ -1519,6 +1534,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
            // allowed range.
            // allowed range.
            float animateValue = clampScreenBrightness(brightnessState);
            float animateValue = clampScreenBrightness(brightnessState);


            animateValue = mBrightnessClamperController.clamp(animateValue);

            // If there are any HDR layers on the screen, we have a special brightness value that we
            // If there are any HDR layers on the screen, we have a special brightness value that we
            // use instead. We still preserve the calculated brightness for Standard Dynamic Range
            // use instead. We still preserve the calculated brightness for Standard Dynamic Range
            // (SDR) layers, but the main brightness value will be the one for HDR.
            // (SDR) layers, but the main brightness value will be the one for HDR.
@@ -2411,6 +2428,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
        if (mDisplayStateController != null) {
        if (mDisplayStateController != null) {
            mDisplayStateController.dumpsys(pw);
            mDisplayStateController.dumpsys(pw);
        }
        }

        pw.println();
        if (mBrightnessClamperController != null) {
            mBrightnessClamperController.dump(ipw);
        }
    }
    }




+55 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 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.NonNull;
import android.os.PowerManager;

import java.io.PrintWriter;

abstract class BrightnessClamper<T> {

    protected float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
    protected boolean mIsActive = false;

    float getBrightnessCap() {
        return mBrightnessCap;
    }

    boolean isActive() {
        return mIsActive;
    }

    void dump(PrintWriter writer) {
        writer.println("BrightnessClamper:" + getType());
        writer.println(" mBrightnessCap: " + mBrightnessCap);
        writer.println(" mIsActive: " + mIsActive);
    }

    @NonNull
    abstract Type getType();

    abstract void onDeviceConfigChanged();

    abstract void onDisplayChanged(T displayData);

    abstract void stop();

    enum Type {
        THERMAL
    }
}
+207 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2023 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 static com.android.server.display.brightness.clamper.BrightnessClamper.Type;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.PowerManager;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.util.IndentingPrintWriter;

import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.feature.DeviceConfigParameterProvider;

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

/**
 * Clampers controller, all in DisplayControllerHandler
 */
public class BrightnessClamperController {

    private static final boolean ENABLED = false;

    private final DeviceConfigParameterProvider mDeviceConfigParameterProvider;
    private final Handler mHandler;
    private final ClamperChangeListener mClamperChangeListenerExternal;

    private final Executor mExecutor;
    private final List<BrightnessClamper<? super DisplayDeviceData>> mClampers = new ArrayList<>();
    private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
            properties -> mClampers.forEach(BrightnessClamper::onDeviceConfigChanged);
    private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
    @Nullable
    private Type mClamperType = null;

    public BrightnessClamperController(Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data) {
        this(new Injector(), handler, clamperChangeListener, data);
    }

    @VisibleForTesting
    BrightnessClamperController(Injector injector, Handler handler,
            ClamperChangeListener clamperChangeListener, DisplayDeviceData data) {
        mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider();
        mHandler = handler;
        mClamperChangeListenerExternal = clamperChangeListener;
        mExecutor = new HandlerExecutor(handler);

        Runnable clamperChangeRunnableInternal = this::recalculateBrightnessCap;

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

        if (ENABLED) {
            mClampers.add(
                    new BrightnessThermalClamper(handler, clamperChangeListenerInternal, data));
            start();
        }
    }

    /**
     * Should be called when display changed. Forwards the call to individual clampers
     */
    public void onDisplayChanged(DisplayDeviceData data) {
        mClampers.forEach(clamper -> clamper.onDisplayChanged(data));
    }

    /**
     * Applies clamping
     * Called in DisplayControllerHandler
     */
    public float clamp(float value) {
        return Math.min(value, mBrightnessCap);
    }

    /**
     * Used to dump ClampersController state.
     */
    public void dump(PrintWriter writer) {
        writer.println("BrightnessClampersController:");
        writer.println("  mBrightnessCap: " + mBrightnessCap);
        writer.println("  mClamperType: " + mClamperType);
        IndentingPrintWriter ipw = new IndentingPrintWriter(writer, "    ");
        mClampers.forEach(clamper -> clamper.dump(ipw));
    }

    /**
     * This method should be called when the ClamperController is no longer in use.
     * Called in DisplayControllerHandler
     */
    public void stop() {
        mDeviceConfigParameterProvider.removeOnPropertiesChangedListener(
                mOnPropertiesChangedListener);
        mClampers.forEach(BrightnessClamper::stop);
    }


    // Called in DisplayControllerHandler
    private void recalculateBrightnessCap() {
        float brightnessCap = PowerManager.BRIGHTNESS_MAX;
        Type clamperType = null;

        BrightnessClamper<?> minClamper = mClampers.stream()
                .filter(BrightnessClamper::isActive)
                .min((clamper1, clamper2) -> Float.compare(clamper1.getBrightnessCap(),
                        clamper2.getBrightnessCap())).orElse(null);

        if (minClamper != null) {
            brightnessCap = minClamper.getBrightnessCap();
            clamperType = minClamper.getType();
        }

        if (mBrightnessCap != brightnessCap || mClamperType != clamperType) {
            mBrightnessCap = brightnessCap;
            mClamperType = clamperType;
            mClamperChangeListenerExternal.onChanged();
        }
    }

    private void start() {
        mDeviceConfigParameterProvider.addOnPropertiesChangedListener(
                mExecutor, mOnPropertiesChangedListener);
    }

    /**
     * Clampers change listener
     */
    public interface ClamperChangeListener {
        /**
         * Notifies that clamper state changed
         */
        void onChanged();
    }

    @VisibleForTesting
    static class Injector {
        DeviceConfigParameterProvider getDeviceConfigParameterProvider() {
            return new DeviceConfigParameterProvider(DeviceConfigInterface.REAL);
        }
    }

    /**
     * Data for clampers
     */
    public static class DisplayDeviceData implements BrightnessThermalClamper.ThermalData {
        @NonNull
        private final String mUniqueDisplayId;
        @NonNull
        private final String mThermalThrottlingDataId;

        private final DisplayDeviceConfig mDisplayDeviceConfig;

        public DisplayDeviceData(@NonNull String uniqueDisplayId,
                @NonNull String thermalThrottlingDataId,
                @NonNull DisplayDeviceConfig displayDeviceConfig) {
            mUniqueDisplayId = uniqueDisplayId;
            mThermalThrottlingDataId = thermalThrottlingDataId;
            mDisplayDeviceConfig = displayDeviceConfig;
        }


        @NonNull
        @Override
        public String getUniqueDisplayId() {
            return mUniqueDisplayId;
        }

        @NonNull
        @Override
        public String getThermalThrottlingDataId() {
            return mThermalThrottlingDataId;
        }

        @Nullable
        @Override
        public ThermalBrightnessThrottlingData getThermalBrightnessThrottlingData() {
            return mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId().get(
                    mThermalThrottlingDataId);
        }
    }
}
Loading