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

Commit 3a409a02 authored by Fiona Campbell's avatar Fiona Campbell Committed by Android (Google) Code Review
Browse files

Merge "Reload the Ambient Light Sensor on Display Change"

parents 45447454 eec9ec7c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2630,6 +2630,9 @@ public class DisplayDeviceConfig {
        }
    }

    /**
     * Uniquely identifies a Sensor, with the combination of Type and Name.
     */
    static class SensorData {
        public String type;
        public String name;
+74 −43
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
import android.sysprop.SurfaceFlingerProperties;
import android.text.TextUtils;
import android.util.IndentingPrintWriter;
import android.util.Pair;
import android.util.Slog;
@@ -70,6 +69,7 @@ import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.display.utils.AmbientFilter;
import com.android.server.display.utils.AmbientFilterFactory;
import com.android.server.display.utils.SensorUtils;
import com.android.server.sensors.SensorManagerInternal;
import com.android.server.sensors.SensorManagerInternal.ProximityActiveListener;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -683,14 +683,20 @@ public class DisplayModeDirector {
    }

    /**
     * A utility to make this class aware of the new display configs whenever the default display is
     * changed
     * Called when the underlying display device of the default display is changed.
     * Some data in this class relates to the physical display of the device, and so we need to
     * reload the configurations based on this.
     * E.g. the brightness sensors and refresh rate capabilities depend on the physical display
     * device that is being used, so will be reloaded.
     *
     * @param displayDeviceConfig configurations relating to the underlying display device.
     */
    public void defaultDisplayDeviceUpdated(DisplayDeviceConfig displayDeviceConfig) {
        mSettingsObserver.setRefreshRates(displayDeviceConfig,
            /* attemptLoadingFromDeviceConfig= */ true);
        mBrightnessObserver.updateBlockingZoneThresholds(displayDeviceConfig,
            /* attemptLoadingFromDeviceConfig= */ true);
        mBrightnessObserver.reloadLightSensor(displayDeviceConfig);
    }

    /**
@@ -1739,6 +1745,9 @@ public class DisplayModeDirector {

        private SensorManager mSensorManager;
        private Sensor mLightSensor;
        private Sensor mRegisteredLightSensor;
        private String mLightSensorType;
        private String mLightSensorName;
        private final LightSensorEventListener mLightSensorListener =
                new LightSensorEventListener();
        // Take it as low brightness before valid sensor data comes
@@ -1899,17 +1908,8 @@ public class DisplayModeDirector {
            return mLowAmbientBrightnessThresholds;
        }

        public void registerLightSensor(SensorManager sensorManager, Sensor lightSensor) {
            mSensorManager = sensorManager;
            mLightSensor = lightSensor;

            mSensorManager.registerListener(mLightSensorListener,
                    mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
        }

        public void observe(SensorManager sensorManager) {
            mSensorManager = sensorManager;
            final ContentResolver cr = mContext.getContentResolver();
            mBrightness = getBrightness(Display.DEFAULT_DISPLAY);

            // DeviceConfig is accessible after system ready.
@@ -2053,6 +2053,10 @@ public class DisplayModeDirector {
                pw.println("    mAmbientHighBrightnessThresholds: " + d);
            }

            pw.println("    mRegisteredLightSensor: " + mRegisteredLightSensor);
            pw.println("    mLightSensor: " + mLightSensor);
            pw.println("    mLightSensorName: " + mLightSensorName);
            pw.println("    mLightSensorType: " + mLightSensorType);
            mLightSensorListener.dumpLocked(pw);

            if (mAmbientFilter != null) {
@@ -2106,27 +2110,9 @@ public class DisplayModeDirector {
            }

            if (mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange) {
                Resources resources = mContext.getResources();
                String lightSensorType = resources.getString(
                        com.android.internal.R.string.config_displayLightSensorType);
                Sensor lightSensor = getLightSensor();

                Sensor lightSensor = null;
                if (!TextUtils.isEmpty(lightSensorType)) {
                    List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL);
                    for (int i = 0; i < sensors.size(); i++) {
                        Sensor sensor = sensors.get(i);
                        if (lightSensorType.equals(sensor.getStringType())) {
                            lightSensor = sensor;
                            break;
                        }
                    }
                }

                if (lightSensor == null) {
                    lightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
                }

                if (lightSensor != null) {
                if (lightSensor != null && lightSensor != mLightSensor) {
                    final Resources res = mContext.getResources();

                    mAmbientFilter = AmbientFilterFactory.createBrightnessFilter(TAG, res);
@@ -2137,14 +2123,40 @@ public class DisplayModeDirector {
                mLightSensor = null;
            }

            if (mRefreshRateChangeable) {
            updateSensorStatus();
            if (mRefreshRateChangeable) {
                synchronized (mLock) {
                    onBrightnessChangedLocked();
                }
            }
        }

        private void reloadLightSensor(DisplayDeviceConfig displayDeviceConfig) {
            reloadLightSensorData(displayDeviceConfig);
            restartObserver();
        }

        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) {
                Resources resources = mContext.getResources();
                mLightSensorType = resources.getString(
                        com.android.internal.R.string.config_displayLightSensorType);
                mLightSensorName = "";
            }
        }

        private Sensor getLightSensor() {
            return SensorUtils.findSensor(mSensorManager, mLightSensorType,
                    mLightSensorName, Sensor.TYPE_LIGHT);
        }

        /**
         * Checks to see if at least one value is positive, in which case it is necessary to listen
         * to value changes.
@@ -2288,19 +2300,38 @@ public class DisplayModeDirector {

            if ((mShouldObserveAmbientLowChange || mShouldObserveAmbientHighChange)
                     && isDeviceActive() && !mLowPowerModeEnabled && mRefreshRateChangeable) {
                registerLightSensor();

            } else {
                unregisterSensorListener();
            }
        }

        private void registerLightSensor() {
            if (mRegisteredLightSensor == mLightSensor) {
                return;
            }

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

            mSensorManager.registerListener(mLightSensorListener,
                    mLightSensor, LIGHT_SENSOR_RATE_MS * 1000, mHandler);
            mRegisteredLightSensor = mLightSensor;
            if (mLoggingEnabled) {
                Slog.d(TAG, "updateSensorStatus: registerListener");
            }
            } else {
        }

        private void unregisterSensorListener() {
            mLightSensorListener.removeCallbacks();
            mSensorManager.unregisterListener(mLightSensorListener);
            mRegisteredLightSensor = null;
            if (mLoggingEnabled) {
                Slog.d(TAG, "updateSensorStatus: unregisterListener");
            }
        }
        }

        private boolean isDeviceActive() {
            return mDefaultDisplayState == Display.STATE_ON;
+4 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@ public class SensorUtils {
     */
    public static Sensor findSensor(SensorManager sensorManager, String sensorType,
            String sensorName, int fallbackType) {
        if (sensorManager == null) {
            return null;
        }

        if ("".equals(sensorName) && "".equals(sensorType)) {
            return null;
        }
+58 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -73,6 +74,7 @@ import android.provider.Settings;
import android.test.mock.MockContentResolver;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Display;
import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.RefreshRateRanges;
@@ -102,6 +104,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;

import java.util.ArrayList;
import java.util.Arrays;
@@ -2293,6 +2296,61 @@ public class DisplayModeDirectorTest {
                new int[]{20});
    }

    @Test
    public void testSensorReloadOnDeviceSwitch() throws Exception {
        // First, configure brightness zones or DMD won't register for sensor data.
        final FakeDeviceConfig config = mInjector.getDeviceConfig();
        config.setRefreshRateInHighZone(60);
        config.setHighDisplayBrightnessThresholds(new int[] { 255 });
        config.setHighAmbientBrightnessThresholds(new int[] { 8000 });

        DisplayModeDirector director =
                createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
        setPeakRefreshRate(90 /*fps*/);
        director.getSettingsObserver().setDefaultRefreshRate(90);
        director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON);

        Sensor lightSensorOne = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
        Sensor lightSensorTwo = TestUtils.createSensor(Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
        SensorManager sensorManager = createMockSensorManager(lightSensorOne, lightSensorTwo);
        when(sensorManager.getDefaultSensor(5)).thenReturn(lightSensorOne, lightSensorTwo);
        director.start(sensorManager);
        ArgumentCaptor<SensorEventListener> listenerCaptor =
                ArgumentCaptor.forClass(SensorEventListener.class);
        verify(sensorManager, Mockito.timeout(TimeUnit.SECONDS.toMillis(1)))
                .registerListener(
                        listenerCaptor.capture(),
                        eq(lightSensorOne),
                        anyInt(),
                        any(Handler.class));

        DisplayDeviceConfig ddcMock = mock(DisplayDeviceConfig.class);
        when(ddcMock.getDefaultLowRefreshRate()).thenReturn(50);
        when(ddcMock.getDefaultHighRefreshRate()).thenReturn(55);
        when(ddcMock.getLowDisplayBrightnessThresholds()).thenReturn(new int[]{25});
        when(ddcMock.getLowAmbientBrightnessThresholds()).thenReturn(new int[]{30});
        when(ddcMock.getHighDisplayBrightnessThresholds()).thenReturn(new int[]{210});
        when(ddcMock.getHighAmbientBrightnessThresholds()).thenReturn(new int[]{2100});

        Resources resMock = mock(Resources.class);
        when(resMock.getInteger(
                com.android.internal.R.integer.config_displayWhiteBalanceBrightnessFilterHorizon))
                .thenReturn(3);
        ArgumentCaptor<TypedValue> valueArgumentCaptor = ArgumentCaptor.forClass(TypedValue.class);
        doAnswer((Answer<Void>) invocation -> {
            valueArgumentCaptor.getValue().type = 4;
            valueArgumentCaptor.getValue().data = 13;
            return null;
        }).when(resMock).getValue(anyInt(), valueArgumentCaptor.capture(), eq(true));
        when(mContext.getResources()).thenReturn(resMock);

        director.defaultDisplayDeviceUpdated(ddcMock);

        verify(sensorManager).unregisterListener(any(SensorEventListener.class));
        verify(sensorManager).registerListener(any(SensorEventListener.class),
                eq(lightSensorTwo), anyInt(), any(Handler.class));
    }

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