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

Commit c7fd6969 authored by Adrian Roos's avatar Adrian Roos
Browse files

AOD: Prewarm display while waiting for brightness sensor

This partially reverts commit a79ad59d.

Instead of keeping AOD paused, we now turn the display on, but keep it soft
blanked by keeping the front scrim opaque black until we get a valid sensor
event.

Bug: 65010918
Test: runtest -x packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
Change-Id: Ic39d29814024d52117538a6a19adaf3866c7223e
parent 3e009eef
Loading
Loading
Loading
Loading
+5 −8
Original line number Diff line number Diff line
@@ -58,22 +58,20 @@ public class DozeFactory {
                params);

        DozeMachine machine = new DozeMachine(wrappedService, config, wakeLock);
        DozeScreenBrightness screenBrightness = createDozeScreenBrightness(
                context, wrappedService, sensorManager, host, handler);
        machine.setParts(new DozeMachine.Part[]{
                new DozePauser(handler, machine, alarmManager, new AlwaysOnDisplayPolicy(context)),
                new DozeFalsingManagerAdapter(FalsingManager.getInstance(context)),
                createDozeTriggers(context, sensorManager, host, alarmManager, config, params,
                        handler, screenBrightness, wakeLock, machine),
                        handler, wakeLock, machine),
                createDozeUi(context, host, wakeLock, machine, handler, alarmManager),
                new DozeScreenState(wrappedService, handler),
                screenBrightness,
                createDozeScreenBrightness(context, wrappedService, sensorManager, host, handler),
        });

        return machine;
    }

    private DozeScreenBrightness createDozeScreenBrightness(Context context,
    private DozeMachine.Part createDozeScreenBrightness(Context context,
            DozeMachine.Service service, SensorManager sensorManager, DozeHost host,
            Handler handler) {
        Sensor sensor = DozeSensors.findSensorWithType(sensorManager,
@@ -84,11 +82,10 @@ public class DozeFactory {

    private DozeTriggers createDozeTriggers(Context context, SensorManager sensorManager,
            DozeHost host, AlarmManager alarmManager, AmbientDisplayConfiguration config,
            DozeParameters params, Handler handler, DozeScreenBrightness screenBrightness,
            WakeLock wakeLock, DozeMachine machine) {
            DozeParameters params, Handler handler, WakeLock wakeLock, DozeMachine machine) {
        boolean allowPulseTriggers = true;
        return new DozeTriggers(context, machine, host, alarmManager, config, params,
                sensorManager, handler, screenBrightness, wakeLock, allowPulseTriggers);
                sensorManager, handler, wakeLock, allowPulseTriggers);
    }

    private DozeMachine.Part createDozeUi(Context context, DozeHost host, WakeLock wakeLock,
+34 −36
Original line number Diff line number Diff line
@@ -37,10 +37,11 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen
    private final Sensor mLightSensor;
    private final int[] mSensorToBrightness;
    private final int[] mSensorToScrimOpacity;

    private boolean mRegistered;
    private boolean mReady = true;
    private ReadyListener mReadyListener;
    private int mDefaultDozeBrightness;
    private boolean mPaused = false;
    private int mLastSensorValue = -1;

    public DozeScreenBrightness(Context context, DozeMachine.Service service,
            SensorManager sensorManager, Sensor lightSensor, DozeHost host,
@@ -86,22 +87,38 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen
                setLightSensorEnabled(false);
                break;
        }
        if (newState != DozeMachine.State.FINISH) {
            setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED);
        }
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (mRegistered) {
            int sensorValue = (int) event.values[0];
            int brightness = computeBrightness(sensorValue);
            if (brightness > 0) {
            mLastSensorValue = (int) event.values[0];
            updateBrightnessAndReady();
        }
    }

    private void updateBrightnessAndReady() {
        if (mRegistered) {
            int brightness = computeBrightness(mLastSensorValue);
            boolean brightnessReady = brightness > 0;
            if (brightnessReady) {
                mDozeService.setDozeScreenBrightness(brightness);
            }
            // If the brightness is zero or negative, this indicates that the brightness sensor is
            // covered or reports that the screen should be off, therefore we're not ready to turn
            // on the screen yet.
            setReady(brightness > 0);

            int scrimOpacity = computeScrimOpacity(sensorValue);
            int scrimOpacity = -1;
            if (mPaused) {
                // If AOD is paused, force the screen black until the
                // sensor reports a new brightness. This ensures that when the screen comes on
                // again, it will only show after the brightness sensor has stabilized,
                // avoiding a potential flicker.
                scrimOpacity = 255;
            } else if (brightnessReady) {
                // Only unblank scrim once brightness is ready.
                scrimOpacity = computeScrimOpacity(mLastSensorValue);
            }
            if (scrimOpacity >= 0) {
                mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
            }
@@ -128,47 +145,28 @@ public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListen

    private void resetBrightnessToDefault() {
        mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness);
        mDozeHost.setAodDimmingScrim(0f);
    }

    private void setLightSensorEnabled(boolean enabled) {
        if (enabled && !mRegistered && mLightSensor != null) {
            // Wait until we get an event from the sensor until indicating ready.
            setReady(false);
            mRegistered = mSensorManager.registerListener(this, mLightSensor,
                    SensorManager.SENSOR_DELAY_NORMAL, mHandler);
            mLastSensorValue = -1;
        } else if (!enabled && mRegistered) {
            mSensorManager.unregisterListener(this);
            mRegistered = false;
            mLastSensorValue = -1;
            // Sensor is not enabled, hence we use the default brightness and are always ready.
            setReady(true);
        }
    }

    private void setReady(boolean ready) {
        if (ready != mReady) {
            mReady = ready;
            if (mReadyListener != null) {
                mReadyListener.onBrightnessReadyChanged(mReady);
            }
        }
    }

    public void setBrightnessReadyListener(ReadyListener l) {
        mReadyListener = l;
        l.onBrightnessReadyChanged(mReady);
    private void setPaused(boolean paused) {
        if (mPaused != paused) {
            mPaused = paused;
            updateBrightnessAndReady();
        }

    /**
     * @return true if the screen brightness is properly calculated.
     *
     * Can be used to wait for transitioning out of the paused state, such that we don't turn the
     * display on before the display brightness is properly calculated.
     */
    public boolean isReady() {
        return mReady;
    }

    public interface ReadyListener {
        void onBrightnessReadyChanged(boolean ready);
    }
}
+5 −34
Original line number Diff line number Diff line
@@ -33,7 +33,6 @@ import android.os.UserHandle;
import android.text.format.Formatter;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.hardware.AmbientDisplayConfiguration;
import com.android.internal.util.Preconditions;
import com.android.systemui.statusbar.phone.DozeParameters;
@@ -66,7 +65,6 @@ public class DozeTriggers implements DozeMachine.Part {
    private final boolean mAllowPulseTriggers;
    private final UiModeManager mUiModeManager;
    private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
    private final DozeScreenBrightness mDozeScreenBrightness;

    private long mNotificationPulseTime;
    private boolean mPulsePending;
@@ -75,7 +73,7 @@ public class DozeTriggers implements DozeMachine.Part {
    public DozeTriggers(Context context, DozeMachine machine, DozeHost dozeHost,
            AlarmManager alarmManager, AmbientDisplayConfiguration config,
            DozeParameters dozeParameters, SensorManager sensorManager, Handler handler,
            DozeScreenBrightness brightness, WakeLock wakeLock, boolean allowPulseTriggers) {
            WakeLock wakeLock, boolean allowPulseTriggers) {
        mContext = context;
        mMachine = machine;
        mDozeHost = dozeHost;
@@ -89,7 +87,6 @@ public class DozeTriggers implements DozeMachine.Part {
                config, wakeLock, this::onSensor, this::onProximityFar,
                new AlwaysOnDisplayPolicy(context));
        mUiModeManager = mContext.getSystemService(UiModeManager.class);
        mDozeScreenBrightness = brightness;
    }

    private void onNotification() {
@@ -162,41 +159,16 @@ public class DozeTriggers implements DozeMachine.Part {
    private void onProximityFar(boolean far) {
        final boolean near = !far;
        final DozeMachine.State state = mMachine.getState();
        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
        final boolean aod = (state == DozeMachine.State.DOZE_AOD);

        if (state == DozeMachine.State.DOZE_PULSING) {
            boolean ignoreTouch = near;
            if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
            mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
        }

        recalculatePausing();
    }

    private void onBrightnessReady(boolean brightnessReady) {
        // Post because this is sometimes called during state transitions and we cannot query
        // the machine's state while it's transitioning.
        mHandler.post(this::recalculatePausing);
    }

    private void recalculatePausing() {
        boolean brightnessReady = mDozeScreenBrightness.isReady();
        Boolean proxCurrentlyFar = mDozeSensors.isProximityCurrentlyFar();

        // Treat UNKNOWN the same as FAR, such that we don't pause the display just because
        // the prox has unknown state.
        boolean proximityFar = proxCurrentlyFar == null || proxCurrentlyFar;
        recalculatePausing(proximityFar, brightnessReady);
    }

    @VisibleForTesting
    void recalculatePausing(boolean proximityFar, boolean brightnessReady) {
        final boolean near = !proximityFar;
        final DozeMachine.State state = mMachine.getState();
        final boolean paused = (state == DozeMachine.State.DOZE_AOD_PAUSED);
        final boolean pausing = (state == DozeMachine.State.DOZE_AOD_PAUSING);
        final boolean aod = (state == DozeMachine.State.DOZE_AOD);

        if (proximityFar && (pausing || paused && brightnessReady)) {
        if (far && (paused || pausing)) {
            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
            mMachine.requestState(DozeMachine.State.DOZE_AOD);
        } else if (near && aod) {
@@ -211,7 +183,6 @@ public class DozeTriggers implements DozeMachine.Part {
            case INITIALIZED:
                mBroadcastReceiver.register(mContext);
                mDozeHost.addCallback(mHostCallback);
                mDozeScreenBrightness.setBrightnessReadyListener(this::onBrightnessReady);
                checkTriggersAtInit();
                break;
            case DOZE:
+6 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ class DozeHostFake implements DozeHost {
    boolean dozing;
    float doubleTapX;
    float doubleTapY;
    float aodDimmingScrimOpacity;

    @Override
    public void addCallback(@NonNull Callback callback) {
@@ -114,4 +115,9 @@ class DozeHostFake implements DozeHost {
    @Override
    public void setDozeScreenBrightness(int value) {
    }

    @Override
    public void setAodDimmingScrim(float scrimOpacity) {
        aodDimmingScrimOpacity = scrimOpacity;
    }
}
+35 −46
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.systemui.doze.DozeMachine.State.UNINITIALIZED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import android.os.PowerManager;
@@ -149,8 +150,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);

        assertTrue(mScreen.isReady());
    }

    @Test
@@ -165,87 +164,77 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
    }

    @Test
    public void testNonPositiveBrightness_keepsPreviousBrightness() throws Exception {
    public void testNonPositiveBrightness_keepsPreviousBrightnessAndScrim() throws Exception {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);

        mSensor.sendSensorEvent(2);
        mSensor.sendSensorEvent(1);
        mSensor.sendSensorEvent(0);

        assertEquals(2, mServiceFake.screenBrightness);
    }

    @Test
    public void readyWhenNotInitialized() {
        assertTrue(mScreen.isReady());
    }

    @Test
    public void readyWhenNotRegistered() {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE);

        assertTrue(mScreen.isReady());
        assertEquals(1, mServiceFake.screenBrightness);
        assertEquals(10/255f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
    }

    @Test
    public void notReadyWhenRegistered_butNoEventYet() {
    public void pausingAod_softBlanks() throws Exception {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);

        assertFalse(mScreen.isReady());
    }
        mSensor.sendSensorEvent(2);

    @Test
    public void notReady_afterZeroBrightness() {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);

        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);

        mSensor.sendSensorEvent(0);
        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);

        assertFalse(mScreen.isReady());
        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);
        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
    }

    @Test
    public void ready_afterNonZeroBrightness() {
    public void pausingAod_softBlanks_withSpuriousSensorDuringPause() throws Exception {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);
        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);

        mSensor.sendSensorEvent(1);

        assertTrue(mScreen.isReady());
        assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
    }

    @Test
    public void notReady_nonZeroThenZeroBrightness() {
    public void pausingAod_unblanksAfterSensor() throws Exception {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);

        mSensor.sendSensorEvent(1);
        mSensor.sendSensorEvent(0);
        mSensor.sendSensorEvent(2);

        assertFalse(mScreen.isReady());
    }
        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);

    @Test
    public void readyListener_getsCalled_whenRegistering() throws Exception {
        Boolean[] ready = new Boolean[1];
        mSensor.sendSensorEvent(0);

        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);

        mScreen.setBrightnessReadyListener((x) -> ready[0] = true);
        mSensor.sendSensorEvent(2);

        assertTrue(ready[0]);
        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
    }

    @Test
    public void readyListener_getsCalled_whenReadyChanges() throws Exception {
        Boolean[] ready = new Boolean[1];
        mScreen.setBrightnessReadyListener((x) -> ready[0] = true);

    public void pausingAod_unblanksIfSensorWasAlwaysReady() throws Exception {
        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
        mScreen.transitionTo(INITIALIZED, DOZE_AOD);

        ready[0] = null;
        mSensor.sendSensorEvent(1);
        assertTrue(ready[0]);
        mSensor.sendSensorEvent(2);

        mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
        mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
        mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD);

        assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */);
    }
}
 No newline at end of file
Loading