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

Commit fd0cc436 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "BrightnessTracker should accomodate multiple ambient sensors" into tm-qpr-dev am: 5cb3c557

parents 65574a3c 5cb3c557
Loading
Loading
Loading
Loading
+40 −0
Original line number Diff line number Diff line
@@ -602,6 +602,14 @@ class AutomaticBrightnessController {
        mAmbientBrightnessThresholdsIdle.dump(pw);
    }

    public float[] getLastSensorValues() {
        return mAmbientLightRingBuffer.getAllLuxValues();
    }

    public long[] getLastSensorTimestamps() {
        return mAmbientLightRingBuffer.getAllTimestamps();
    }

    private String configStateToString(int state) {
        switch (state) {
        case AUTO_BRIGHTNESS_ENABLED:
@@ -1231,10 +1239,42 @@ class AutomaticBrightnessController {
            return mRingLux[offsetOf(index)];
        }

        public float[] getAllLuxValues() {
            float[] values = new float[mCount];
            if (mCount == 0) {
                return values;
            }

            if (mStart < mEnd) {
                System.arraycopy(mRingLux, mStart, values, 0, mCount);
            } else {
                System.arraycopy(mRingLux, mStart, values, 0, mCapacity - mStart);
                System.arraycopy(mRingLux, 0, values, mCapacity - mStart, mEnd);
            }

            return values;
        }

        public long getTime(int index) {
            return mRingTime[offsetOf(index)];
        }

        public long[] getAllTimestamps() {
            long[] values = new long[mCount];
            if (mCount == 0) {
                return values;
            }

            if (mStart < mEnd) {
                System.arraycopy(mRingTime, mStart, values, 0, mCount);
            } else {
                System.arraycopy(mRingTime, mStart, values, 0, mCapacity - mStart);
                System.arraycopy(mRingTime, 0, values, mCapacity - mStart, mEnd);
            }

            return values;
        }

        public void push(long time, float lux) {
            int next = mEnd;
            if (mCount == mCapacity) {
+18 −71
Original line number Diff line number Diff line
@@ -79,10 +79,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Date;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@@ -101,8 +99,6 @@ public class BrightnessTracker {
    private static final int MAX_EVENTS = 100;
    // Discard events when reading or writing that are older than this.
    private static final long MAX_EVENT_AGE = TimeUnit.DAYS.toMillis(30);
    // Time over which we keep lux sensor readings.
    private static final long LUX_EVENT_HORIZON = TimeUnit.SECONDS.toNanos(10);

    private static final String TAG_EVENTS = "events";
    private static final String TAG_EVENT = "event";
@@ -174,8 +170,6 @@ public class BrightnessTracker {
    // Lock held while collecting data related to brightness changes.
    private final Object mDataCollectionLock = new Object();
    @GuardedBy("mDataCollectionLock")
    private Deque<LightData> mLastSensorReadings = new ArrayDeque<>();
    @GuardedBy("mDataCollectionLock")
    private float mLastBatteryLevel = Float.NaN;
    @GuardedBy("mDataCollectionLock")
    private float mLastBrightness = -1;
@@ -327,7 +321,8 @@ public class BrightnessTracker {
     */
    public void notifyBrightnessChanged(float brightness, boolean userInitiated,
            float powerBrightnessFactor, boolean isUserSetBrightness,
            boolean isDefaultBrightnessConfig, String uniqueDisplayId) {
            boolean isDefaultBrightnessConfig, String uniqueDisplayId, float[] luxValues,
            long[] luxTimestamps) {
        if (DEBUG) {
            Slog.d(TAG, String.format("notifyBrightnessChanged(brightness=%f, userInitiated=%b)",
                        brightness, userInitiated));
@@ -335,7 +330,7 @@ public class BrightnessTracker {
        Message m = mBgHandler.obtainMessage(MSG_BRIGHTNESS_CHANGED,
                userInitiated ? 1 : 0, 0 /*unused*/, new BrightnessChangeValues(brightness,
                        powerBrightnessFactor, isUserSetBrightness, isDefaultBrightnessConfig,
                        mInjector.currentTimeMillis(), uniqueDisplayId));
                        mInjector.currentTimeMillis(), uniqueDisplayId, luxValues, luxTimestamps));
        m.sendToTarget();
    }

@@ -349,7 +344,8 @@ public class BrightnessTracker {

    private void handleBrightnessChanged(float brightness, boolean userInitiated,
            float powerBrightnessFactor, boolean isUserSetBrightness,
            boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) {
            boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId,
            float[] luxValues, long[] luxTimestamps) {
        BrightnessChangeEvent.Builder builder;

        synchronized (mDataCollectionLock) {
@@ -376,28 +372,22 @@ public class BrightnessTracker {
            builder.setIsDefaultBrightnessConfig(isDefaultBrightnessConfig);
            builder.setUniqueDisplayId(uniqueDisplayId);

            final int readingCount = mLastSensorReadings.size();
            if (readingCount == 0) {
            if (luxValues.length == 0) {
                // No sensor data so ignore this.
                return;
            }

            float[] luxValues = new float[readingCount];
            long[] luxTimestamps = new long[readingCount];

            int pos = 0;
            long[] luxTimestampsMillis = new long[luxTimestamps.length];

            // Convert sensor timestamp in elapsed time nanos to current time millis.
            // Convert lux timestamp in elapsed time to current time.
            long currentTimeMillis = mInjector.currentTimeMillis();
            long elapsedTimeNanos = mInjector.elapsedRealtimeNanos();
            for (LightData reading : mLastSensorReadings) {
                luxValues[pos] = reading.lux;
                luxTimestamps[pos] = currentTimeMillis -
                        TimeUnit.NANOSECONDS.toMillis(elapsedTimeNanos - reading.timestamp);
                ++pos;
            for (int i = 0; i < luxTimestamps.length; i++) {
                luxTimestampsMillis[i] = currentTimeMillis - (TimeUnit.NANOSECONDS.toMillis(
                        elapsedTimeNanos) - luxTimestamps[i]);
            }
            builder.setLuxValues(luxValues);
            builder.setLuxTimestamps(luxTimestamps);
            builder.setLuxTimestamps(luxTimestampsMillis);

            builder.setBatteryLevel(mLastBatteryLevel);
            builder.setLastBrightness(previousBrightness);
@@ -452,9 +442,6 @@ public class BrightnessTracker {
        if (mLightSensor != lightSensor) {
            mLightSensor = lightSensor;
            stopSensorListener();
            synchronized (mDataCollectionLock) {
                mLastSensorReadings.clear();
            }
            // Attempt to restart the sensor listener. It will check to see if it should be running
            // so there is no need to also check here.
            startSensorListener();
@@ -798,12 +785,6 @@ public class BrightnessTracker {
            pw.println("  mLightSensor=" + mLightSensor);
            pw.println("  mLastBatteryLevel=" + mLastBatteryLevel);
            pw.println("  mLastBrightness=" + mLastBrightness);
            pw.println("  mLastSensorReadings.size=" + mLastSensorReadings.size());
            if (!mLastSensorReadings.isEmpty()) {
                pw.println("  mLastSensorReadings time span "
                        + mLastSensorReadings.peekFirst().timestamp + "->"
                        + mLastSensorReadings.peekLast().timestamp);
            }
        }
        synchronized (mEventsLock) {
            pw.println("  mEventsDirty=" + mEventsDirty);
@@ -919,43 +900,6 @@ public class BrightnessTracker {
        return ParceledListSlice.emptyList();
    }

    // Not allowed to keep the SensorEvent so used to copy the data we care about.
    private static class LightData {
        public float lux;
        // Time in elapsedRealtimeNanos
        public long timestamp;
    }

    private void recordSensorEvent(SensorEvent event) {
        long horizon = mInjector.elapsedRealtimeNanos() - LUX_EVENT_HORIZON;
        synchronized (mDataCollectionLock) {
            if (DEBUG) {
                Slog.v(TAG, "Sensor event " + event);
            }
            if (!mLastSensorReadings.isEmpty()
                    && event.timestamp < mLastSensorReadings.getLast().timestamp) {
                // Ignore event that came out of order.
                return;
            }
            LightData data = null;
            while (!mLastSensorReadings.isEmpty()
                    && mLastSensorReadings.getFirst().timestamp < horizon) {
                // Remove data that has fallen out of the window.
                data = mLastSensorReadings.removeFirst();
            }
            // We put back the last one we removed so we know how long
            // the first sensor reading was valid for.
            if (data != null) {
                mLastSensorReadings.addFirst(data);
            }

            data = new LightData();
            data.timestamp = event.timestamp;
            data.lux = event.values[0];
            mLastSensorReadings.addLast(data);
        }
    }

    private void recordAmbientBrightnessStats(SensorEvent event) {
        mAmbientBrightnessStatsTracker.add(mCurrentUserId, event.values[0]);
    }
@@ -969,7 +913,6 @@ public class BrightnessTracker {
    private final class SensorListener implements SensorEventListener {
        @Override
        public void onSensorChanged(SensorEvent event) {
            recordSensorEvent(event);
            recordAmbientBrightnessStats(event);
        }

@@ -1056,7 +999,7 @@ public class BrightnessTracker {
                    handleBrightnessChanged(values.brightness, userInitiatedChange,
                            values.powerBrightnessFactor, values.isUserSetBrightness,
                            values.isDefaultBrightnessConfig, values.timestamp,
                            values.uniqueDisplayId);
                            values.uniqueDisplayId, values.luxValues, values.luxTimestamps);
                    break;
                case MSG_START_SENSOR_LISTENER:
                    startSensorListener();
@@ -1092,16 +1035,20 @@ public class BrightnessTracker {
        public final boolean isDefaultBrightnessConfig;
        public final long timestamp;
        public final String uniqueDisplayId;
        public final float[] luxValues;
        public final long[] luxTimestamps;

        BrightnessChangeValues(float brightness, float powerBrightnessFactor,
                boolean isUserSetBrightness, boolean isDefaultBrightnessConfig,
                long timestamp, String uniqueDisplayId) {
                long timestamp, String uniqueDisplayId, float[] luxValues, long[] luxTimestamps) {
            this.brightness = brightness;
            this.powerBrightnessFactor = powerBrightnessFactor;
            this.isUserSetBrightness = isUserSetBrightness;
            this.isDefaultBrightnessConfig = isDefaultBrightnessConfig;
            this.timestamp = timestamp;
            this.uniqueDisplayId = uniqueDisplayId;
            this.luxValues = luxValues;
            this.luxTimestamps = luxTimestamps;
        }
    }

+3 −1
Original line number Diff line number Diff line
@@ -2471,7 +2471,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                    : 1.0f;
            mBrightnessTracker.notifyBrightnessChanged(brightnessInNits, userInitiated,
                    powerFactor, hadUserDataPoint,
                    mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId);
                    mAutomaticBrightnessController.isDefaultConfig(), mUniqueDisplayId,
                    mAutomaticBrightnessController.getLastSensorValues(),
                    mAutomaticBrightnessController.getLastSensorTimestamps());
        }
    }

+99 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.display;

import static com.android.server.display.AutomaticBrightnessController.AUTO_BRIGHTNESS_ENABLED;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
@@ -178,7 +179,7 @@ public class AutomaticBrightnessControllerTest {

        // Send new sensor value and verify
        listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux1));
        assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), 0.001f);
        assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), EPSILON);

        // Set up system to return 0.0f (minimum possible brightness) as a brightness value
        float lux2 = 10.0f;
@@ -192,7 +193,7 @@ public class AutomaticBrightnessControllerTest {

        // Send new sensor value and verify
        listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux2));
        assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), 0.001f);
        assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), EPSILON);
    }

    @Test
@@ -221,7 +222,7 @@ public class AutomaticBrightnessControllerTest {

        // Send new sensor value and verify
        listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux1));
        assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), 0.001f);
        assertEquals(normalizedBrightness1, mController.getAutomaticScreenBrightness(), EPSILON);


        // Set up system to return 1.0f as a brightness value (brightness_max)
@@ -236,7 +237,7 @@ public class AutomaticBrightnessControllerTest {

        // Send new sensor value and verify
        listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, (int) lux2));
        assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), 0.001f);
        assertEquals(normalizedBrightness2, mController.getAutomaticScreenBrightness(), EPSILON);
    }

    @Test
@@ -418,6 +419,12 @@ public class AutomaticBrightnessControllerTest {
        // ambient lux goes to 0
        listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, 0));
        assertEquals(0.0f, mController.getAmbientLux(), EPSILON);

        // only the values within the horizon should be kept
        assertArrayEquals(new float[] {10000, 10000, 0, 0, 0}, mController.getLastSensorValues(),
                EPSILON);
        assertArrayEquals(new long[] {4000, 4500, 5000, 5500, 6000},
                mController.getLastSensorTimestamps());
    }

    @Test
@@ -489,4 +496,92 @@ public class AutomaticBrightnessControllerTest {
                0 /* adjustment */, false /* userChanged */, DisplayPowerRequest.POLICY_BRIGHT);
        assertEquals(BRIGHTNESS_MAX_FLOAT, mController.getAutomaticScreenBrightness(), 0.0f);
    }

    @Test
    public void testGetSensorReadings() throws Exception {
        ArgumentCaptor<SensorEventListener> listenerCaptor =
                ArgumentCaptor.forClass(SensorEventListener.class);
        verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
                eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
        SensorEventListener listener = listenerCaptor.getValue();

        // Choose values such that the ring buffer's capacity is extended and the buffer is pruned
        int increment = 11;
        int lux = 5000;
        for (int i = 0; i < 1000; i++) {
            lux += increment;
            mClock.fastForward(increment);
            listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
        }

        int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment + 1);
        float[] sensorValues = mController.getLastSensorValues();
        long[] sensorTimestamps = mController.getLastSensorTimestamps();

        // Only the values within the horizon should be kept
        assertEquals(valuesCount, sensorValues.length);
        assertEquals(valuesCount, sensorTimestamps.length);

        long sensorTimestamp = mClock.now();
        for (int i = valuesCount - 1; i >= 1; i--) {
            assertEquals(lux, sensorValues[i], EPSILON);
            assertEquals(sensorTimestamp, sensorTimestamps[i]);
            lux -= increment;
            sensorTimestamp -= increment;
        }
        assertEquals(lux, sensorValues[0], EPSILON);
        assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
    }

    @Test
    public void testGetSensorReadingsFullBuffer() throws Exception {
        ArgumentCaptor<SensorEventListener> listenerCaptor =
                ArgumentCaptor.forClass(SensorEventListener.class);
        verify(mSensorManager).registerListener(listenerCaptor.capture(), eq(mLightSensor),
                eq(INITIAL_LIGHT_SENSOR_RATE * 1000), any(Handler.class));
        SensorEventListener listener = listenerCaptor.getValue();
        int initialCapacity = 150;

        // Choose values such that the ring buffer is pruned
        int increment1 = 200;
        int lux = 5000;
        for (int i = 0; i < 20; i++) {
            lux += increment1;
            mClock.fastForward(increment1);
            listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
        }

        int valuesCount = (int) Math.ceil((double) AMBIENT_LIGHT_HORIZON_LONG / increment1 + 1);

        // Choose values such that the buffer becomes full
        int increment2 = 1;
        for (int i = 0; i < initialCapacity - valuesCount; i++) {
            lux += increment2;
            mClock.fastForward(increment2);
            listener.onSensorChanged(TestUtils.createSensorEvent(mLightSensor, lux));
        }

        float[] sensorValues = mController.getLastSensorValues();
        long[] sensorTimestamps = mController.getLastSensorTimestamps();

        // The buffer should be full
        assertEquals(initialCapacity, sensorValues.length);
        assertEquals(initialCapacity, sensorTimestamps.length);

        long sensorTimestamp = mClock.now();
        for (int i = initialCapacity - 1; i >= 1; i--) {
            assertEquals(lux, sensorValues[i], EPSILON);
            assertEquals(sensorTimestamp, sensorTimestamps[i]);

            if (i >= valuesCount) {
                lux -= increment2;
                sensorTimestamp -= increment2;
            } else {
                lux -= increment1;
                sensorTimestamp -= increment1;
            }
        }
        assertEquals(lux, sensorValues[0], EPSILON);
        assertEquals(mClock.now() - AMBIENT_LIGHT_HORIZON_LONG, sensorTimestamps[0]);
    }
}
+77 −120

File changed.

Preview size limit exceeded, changes collapsed.