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

Commit bdd55137 authored by sashwinbalaji's avatar sashwinbalaji
Browse files

display: brightnessThrottler to support sensor based Throttling

Use TempSensor in DisplayDeviceConfig to support custom sensor based
throttling.

If tempsensor null or empty:
	- Register for type skin (as currently done)
	- Continue with current flow
If tempsensor valud:
	- Register for type in tempsensor.type
	- In notify throttling verify notification for tempsensor.name
	- Continue with current flow

Also update below maps from hashmap to map:
- mThermalBrightnessThrottlingDataMapByThrottlingId
- mPowerThrottlingDataMapByThrottlingId

Bug: 279114539
Test: atest BrightnessThrottlerTest
Test: local build with updated config and check debug logs
Change-Id: Ib599620a73e32c748df183b8cf95b119280d0614
parent 870fd130
Loading
Loading
Loading
Loading
+48 −13
Original line number Diff line number Diff line
@@ -37,9 +37,11 @@ import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.config.SensorData;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.utils.DebugUtils;
import com.android.server.display.utils.DeviceConfigParsingUtils;
import com.android.server.display.utils.SensorUtils;

import java.io.PrintWriter;
import java.util.HashMap;
@@ -79,7 +81,7 @@ class BrightnessThrottler {

    // Maps the throttling ID to the data. Sourced from DisplayDeviceConfig.
    @NonNull
    private HashMap<String, ThermalBrightnessThrottlingData> mDdcThermalThrottlingDataMap;
    private Map<String, ThermalBrightnessThrottlingData> mDdcThermalThrottlingDataMap;

    // Current throttling data being used.
    // Null if we do not support throttling.
@@ -97,6 +99,10 @@ class BrightnessThrottler {
    // The brightness throttling configuration that should be used.
    private String mThermalBrightnessThrottlingDataId;

    // Temperature Sensor to be monitored for throttling.
    @NonNull
    private SensorData mTempSensor;

    // This is a collection of brightness throttling data that has been written as overrides from
    // the DeviceConfig. This will always take priority over the display device config data.
    // We need to store the data for every display device, so we do not need to update this each
@@ -121,17 +127,19 @@ class BrightnessThrottler {

    BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId,
            String throttlingDataId,
            @NonNull HashMap<String, ThermalBrightnessThrottlingData>
                    thermalBrightnessThrottlingDataMap) {
        this(new Injector(), handler, handler, throttlingChangeCallback,
                uniqueDisplayId, throttlingDataId, thermalBrightnessThrottlingDataMap);
            @NonNull DisplayDeviceConfig displayDeviceConfig) {
        this(new Injector(), handler, handler, throttlingChangeCallback, uniqueDisplayId,
                throttlingDataId,
                displayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(),
                displayDeviceConfig.getTempSensor());
    }

    @VisibleForTesting
    BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler,
            Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId,
            @NonNull HashMap<String, ThermalBrightnessThrottlingData>
                    thermalBrightnessThrottlingDataMap) {
            @NonNull Map<String, ThermalBrightnessThrottlingData>
                    thermalBrightnessThrottlingDataMap,
            @NonNull SensorData tempSensor) {
        mInjector = injector;

        mHandler = handler;
@@ -147,7 +155,7 @@ class BrightnessThrottler {
        mDdcThermalThrottlingDataMap = thermalBrightnessThrottlingDataMap;
        loadThermalBrightnessThrottlingDataFromDeviceConfig();
        loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(mDdcThermalThrottlingDataMap,
                mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
                tempSensor, mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
    }

    boolean deviceSupportsThrottling() {
@@ -180,12 +188,14 @@ class BrightnessThrottler {
    }

    void loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
            HashMap<String, ThermalBrightnessThrottlingData> ddcThrottlingDataMap,
            Map<String, ThermalBrightnessThrottlingData> ddcThrottlingDataMap,
            SensorData tempSensor,
            String brightnessThrottlingDataId,
            String uniqueDisplayId) {
        mDdcThermalThrottlingDataMap = ddcThrottlingDataMap;
        mThermalBrightnessThrottlingDataId = brightnessThrottlingDataId;
        mUniqueDisplayId = uniqueDisplayId;
        mTempSensor = tempSensor;
        resetThermalThrottlingData();
    }

@@ -310,7 +320,7 @@ class BrightnessThrottler {
        }

        if (deviceSupportsThrottling()) {
            mSkinThermalStatusObserver.startObserving();
            mSkinThermalStatusObserver.startObserving(mTempSensor);
        }
    }

@@ -357,6 +367,7 @@ class BrightnessThrottler {
    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
        private final Injector mInjector;
        private final Handler mHandler;
        private SensorData mObserverTempSensor;

        private IThermalService mThermalService;
        private boolean mStarted;
@@ -371,28 +382,51 @@ class BrightnessThrottler {
            if (DEBUG) {
                Slog.d(TAG, "New thermal throttling status = " + temp.getStatus());
            }

            if (mObserverTempSensor.name != null
                    && !mObserverTempSensor.name.equals(temp.getName())) {
                Slog.i(TAG, "Skipping thermal throttling notification as monitored sensor: "
                            + mObserverTempSensor.name
                            + " != notified sensor: "
                            + temp.getName());
                return;
            }
            mHandler.post(() -> {
                final @Temperature.ThrottlingStatus int status = temp.getStatus();
                thermalStatusChanged(status);
            });
        }

        void startObserving() {
            if (mStarted) {
        void startObserving(SensorData tempSensor) {
            if (!mStarted || mObserverTempSensor == null) {
                mObserverTempSensor = tempSensor;
                registerThermalListener();
                return;
            }

            String curType = mObserverTempSensor.type;
            mObserverTempSensor = tempSensor;
            if (curType.equals(tempSensor.type)) {
                if (DEBUG) {
                    Slog.d(TAG, "Thermal status observer already started");
                }
                return;
            }
            stopObserving();
            registerThermalListener();
        }

        void registerThermalListener() {
            mThermalService = mInjector.getThermalService();
            if (mThermalService == null) {
                Slog.e(TAG, "Could not observe thermal status. Service not available");
                return;
            }
            int temperatureType = SensorUtils.getSensorTemperatureType(mObserverTempSensor);
            try {
                // We get a callback immediately upon registering so there's no need to query
                // for the current value.
                mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
                mThermalService.registerThermalEventListenerWithType(this, temperatureType);
                mStarted = true;
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to register thermal status listener", e);
@@ -418,6 +452,7 @@ class BrightnessThrottler {
        void dump(PrintWriter writer) {
            writer.println("  SkinThermalStatusObserver:");
            writer.println("    mStarted: " + mStarted);
            writer.println("    mObserverTempSensor: " + mObserverTempSensor);
            if (mThermalService != null) {
                writer.println("    ThermalService available");
            } else {
+4 −4
Original line number Diff line number Diff line
@@ -831,10 +831,10 @@ public class DisplayDeviceConfig {
    private String mLowBlockingZoneThermalMapId = null;
    private String mHighBlockingZoneThermalMapId = null;

    private final HashMap<String, ThermalBrightnessThrottlingData>
    private final Map<String, ThermalBrightnessThrottlingData>
            mThermalBrightnessThrottlingDataMapByThrottlingId = new HashMap<>();

    private final HashMap<String, PowerThrottlingData>
    private final Map<String, PowerThrottlingData>
            mPowerThrottlingDataMapByThrottlingId = new HashMap<>();

    private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
@@ -1556,7 +1556,7 @@ public class DisplayDeviceConfig {
    /**
     * @return brightness throttling configuration data for this display, for each throttling id.
     */
    public HashMap<String, ThermalBrightnessThrottlingData>
    public Map<String, ThermalBrightnessThrottlingData>
            getThermalBrightnessThrottlingDataMapByThrottlingId() {
        return mThermalBrightnessThrottlingDataMapByThrottlingId;
    }
@@ -1575,7 +1575,7 @@ public class DisplayDeviceConfig {
    /**
     * @return power throttling configuration data for this display, for each throttling id.
     **/
    public HashMap<String, PowerThrottlingData>
    public Map<String, PowerThrottlingData>
            getPowerThrottlingDataMapByThrottlingId() {
        return mPowerThrottlingDataMapByThrottlingId;
    }
+3 −1
Original line number Diff line number Diff line
@@ -861,6 +861,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                mThermalBrightnessThrottlingDataId = thermalBrightnessThrottlingDataId;
                mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
                        config.getThermalBrightnessThrottlingDataMapByThrottlingId(),
                        config.getTempSensor(),
                        mThermalBrightnessThrottlingDataId,
                        mUniqueDisplayId);
            }
@@ -923,6 +924,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
        mBrightnessRangeController.loadFromConfig(hbmMetadata, token, info, mDisplayDeviceConfig);
        mBrightnessThrottler.loadThermalBrightnessThrottlingDataFromDisplayDeviceConfig(
                mDisplayDeviceConfig.getThermalBrightnessThrottlingDataMapByThrottlingId(),
                mDisplayDeviceConfig.getTempSensor(),
                mThermalBrightnessThrottlingDataId, mUniqueDisplayId);
    }

@@ -1996,7 +1998,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    postBrightnessChangeRunnable();
                }, mUniqueDisplayId,
                mLogicalDisplay.getDisplayInfoLocked().thermalBrightnessThrottlingDataId,
                ddConfig.getThermalBrightnessThrottlingDataMapByThrottlingId());
                ddConfig);
    }

    private void blockScreenOn() {
+64 −3
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.internal.os.BackgroundThread;
import com.android.server.display.BrightnessThrottler.Injector;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.ThermalBrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.config.SensorData;
import com.android.server.display.mode.DisplayModeDirectorTest;

import org.junit.Before;
@@ -56,6 +57,7 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -292,6 +294,53 @@ public class BrightnessThrottlerTest {
        assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());
    }


    @Test
    public void testThermalThrottlingWithDisplaySensor() throws Exception {
        final ThrottlingLevel level =
                    new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL, 0.25f);
        List<ThrottlingLevel> levels = new ArrayList<>(List.of(level));
        final ThermalBrightnessThrottlingData data = ThermalBrightnessThrottlingData.create(levels);
        final SensorData tempSensor = new SensorData("DISPLAY", "VIRTUAL-SKIN-DISPLAY");
        final BrightnessThrottler throttler =
                    createThrottlerSupportedWithTempSensor(data, tempSensor);
        assertTrue(throttler.deviceSupportsThrottling());

        verify(mThermalServiceMock)
                    .registerThermalEventListenerWithType(
                        mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_DISPLAY));
        final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();

        // Set VIRTUAL-SKIN-DISPLAY tatus too low to verify no throttling.
        listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus - 1));
        mTestLooper.dispatchAll();
        assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
        assertFalse(throttler.isThrottled());
        assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());

        // Verify when skin sensor throttled, no brightness throttling triggered.
        listener.notifyThrottling(getSkinTemp(level.thermalStatus + 1));
        mTestLooper.dispatchAll();
        assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
        assertFalse(throttler.isThrottled());
        assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());

        // Verify when display sensor of another name throttled, no brightness throttling triggered.
        listener.notifyThrottling(getDisplayTempWithName("ANOTHER-NAME", level.thermalStatus + 1));
        mTestLooper.dispatchAll();
        assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
        assertFalse(throttler.isThrottled());
        assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());

        // Verify when display sensor of current name throttled, brightness throttling triggered.
        listener.notifyThrottling(getDisplayTempWithName(tempSensor.name, level.thermalStatus + 1));
        mTestLooper.dispatchAll();
        assertEquals(level.brightness, throttler.getBrightnessCap(), 0f);
        assertTrue(throttler.isThrottled());
        assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_THERMAL,
                throttler.getBrightnessMaxReason());
    }

    @Test public void testUpdateThermalThrottlingData() throws Exception {
        // Initialise brightness throttling levels
        // Ensure that they are overridden by setting the data through device config.
@@ -476,18 +525,30 @@ public class BrightnessThrottlerTest {
        return new BrightnessThrottler(mInjectorMock, mHandler, mHandler,
                /* throttlingChangeCallback= */ () -> {}, /* uniqueDisplayId= */ null,
                /* thermalThrottlingDataId= */ null,
                /* thermalThrottlingDataMap= */ new HashMap<>(1));
                /* thermalThrottlingDataMap= */ new HashMap<>(1),
                /* tempSensor= */ null);
    }

    private BrightnessThrottler createThrottlerSupported(ThermalBrightnessThrottlingData data) {
        SensorData tempSensor = SensorData.loadTempSensorUnspecifiedConfig();
        return createThrottlerSupportedWithTempSensor(data, tempSensor);
    }
    private BrightnessThrottler createThrottlerSupportedWithTempSensor(
                ThermalBrightnessThrottlingData data, SensorData tempSensor) {
        assertNotNull(data);
        HashMap<String, ThermalBrightnessThrottlingData> throttlingDataMap = new HashMap<>(1);
        Map<String, ThermalBrightnessThrottlingData> throttlingDataMap = new HashMap<>(1);
        throttlingDataMap.put("default", data);
        return new BrightnessThrottler(mInjectorMock, mHandler, BackgroundThread.getHandler(),
                () -> {}, "123", "default", throttlingDataMap);
                    () -> {}, "123", "default", throttlingDataMap, tempSensor);
    }

    private Temperature getSkinTemp(@ThrottlingStatus int status) {
        return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
    }

    private Temperature getDisplayTempWithName(
                String sensorName, @ThrottlingStatus int status) {
        assertNotNull(sensorName);
        return new Temperature(30.0f, Temperature.TYPE_DISPLAY, sensorName, status);
    }
}