From c7fd69699058e9b7f0601aca9275b597e8f62736 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 6 Sep 2017 16:46:46 +0200 Subject: [PATCH] AOD: Prewarm display while waiting for brightness sensor This partially reverts commit a79ad59d49cdb3ef6f4cf864094063e3e9111586. 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 --- .../android/systemui/doze/DozeFactory.java | 13 +-- .../systemui/doze/DozeScreenBrightness.java | 70 +++++++------ .../android/systemui/doze/DozeTriggers.java | 39 +------- .../android/systemui/doze/DozeHostFake.java | 6 ++ .../doze/DozeScreenBrightnessTest.java | 99 +++++++++---------- .../systemui/doze/DozeTriggersTest.java | 23 +---- 6 files changed, 95 insertions(+), 155 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java index 9b1842a87904c..6f8bcff16a83b 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeFactory.java @@ -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, diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java index 92f8d8ce638a1..03407e2b86e7e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java @@ -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); - } + private void setPaused(boolean paused) { + if (mPaused != paused) { + mPaused = paused; + updateBrightnessAndReady(); } } - public void setBrightnessReadyListener(ReadyListener l) { - mReadyListener = l; - l.onBrightnessReadyChanged(mReady); - } - - /** - * @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); - } } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java index 8d8c55c2df54f..f7a258a2c959d 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java @@ -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: diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java index 333e73dc10f49..b0c9f32873ff6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeHostFake.java @@ -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; + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java index 4f59fc4c6589d..5e12781399e50 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java @@ -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(1); + mSensor.sendSensorEvent(0); + + assertEquals(1, mServiceFake.screenBrightness); + assertEquals(10/255f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */); + } + + @Test + public void pausingAod_softBlanks() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); mSensor.sendSensorEvent(2); + + 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 */); - assertEquals(2, mServiceFake.screenBrightness); + mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD); + assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */); } @Test - public void readyWhenNotInitialized() { - assertTrue(mScreen.isReady()); - } - - @Test - public void readyWhenNotRegistered() { + public void pausingAod_softBlanks_withSpuriousSensorDuringPause() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE); + mScreen.transitionTo(INITIALIZED, DOZE_AOD); + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING); + mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED); - assertTrue(mScreen.isReady()); + mSensor.sendSensorEvent(1); + assertEquals(1f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */); } @Test - public void notReadyWhenRegistered_butNoEventYet() { + public void pausingAod_unblanksAfterSensor() 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); mSensor.sendSensorEvent(0); - assertFalse(mScreen.isReady()); + mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD); + + mSensor.sendSensorEvent(2); + + assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */); } @Test - public void ready_afterNonZeroBrightness() { + public void pausingAod_unblanksIfSensorWasAlwaysReady() throws Exception { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); - mSensor.sendSensorEvent(1); + mSensor.sendSensorEvent(2); - assertTrue(mScreen.isReady()); - } + mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING); + mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED); + mScreen.transitionTo(DOZE_AOD_PAUSED, DOZE_AOD); - @Test - public void notReady_nonZeroThenZeroBrightness() { - mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE_AOD); - - mSensor.sendSensorEvent(1); - mSensor.sendSensorEvent(0); - - assertFalse(mScreen.isReady()); - } - - @Test - public void readyListener_getsCalled_whenRegistering() throws Exception { - Boolean[] ready = new Boolean[1]; - - mScreen.setBrightnessReadyListener((x) -> ready[0] = true); - - assertTrue(ready[0]); - } - - @Test - public void readyListener_getsCalled_whenReadyChanges() throws Exception { - Boolean[] ready = new Boolean[1]; - mScreen.setBrightnessReadyListener((x) -> ready[0] = true); - - mScreen.transitionTo(UNINITIALIZED, INITIALIZED); - mScreen.transitionTo(INITIALIZED, DOZE_AOD); - - ready[0] = null; - mSensor.sendSensorEvent(1); - assertTrue(ready[0]); + assertEquals(0f, mHostFake.aodDimmingScrimOpacity, 0.001f /* delta */); } } \ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java index 6a9dac4cf8c39..a8ea1c0770da8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeTriggersTest.java @@ -58,7 +58,6 @@ public class DozeTriggersTest extends SysuiTestCase { private WakeLock mWakeLock; private Instrumentation mInstrumentation; private AlarmManager mAlarmManager; - private DozeScreenBrightness mDozeScreenBrightness; @BeforeClass public static void setupSuite() { @@ -77,12 +76,10 @@ public class DozeTriggersTest extends SysuiTestCase { mSensors = new FakeSensorManager(mContext); mHandler = new Handler(Looper.getMainLooper()); mWakeLock = new WakeLockFake(); - mDozeScreenBrightness = mock(DozeScreenBrightness.class); mInstrumentation.runOnMainSync(() -> { mTriggers = new DozeTriggers(mContext, mMachine, mHost, mAlarmManager, - mConfig, mParameters, mSensors, mHandler, mDozeScreenBrightness, - mWakeLock, true); + mConfig, mParameters, mSensors, mHandler, mWakeLock, true); }); } @@ -115,22 +112,4 @@ public class DozeTriggersTest extends SysuiTestCase { verify(mMachine).requestPulse(anyInt()); } - @Test - public void unpausing_fromPaused_waitsForBrightnessReady() throws Exception { - when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD_PAUSED); - - mTriggers.recalculatePausing(true /* proxFar */, false /* brightnessReady */); - verify(mMachine, never()).requestState(any()); - - mTriggers.recalculatePausing(true /* proxFar */, true /* brightnessReady */); - verify(mMachine).requestState(DozeMachine.State.DOZE_AOD); - } - - @Test - public void unpausing_fromPausing_doesntWaitForBrightnessReady() throws Exception { - when(mMachine.getState()).thenReturn(DozeMachine.State.DOZE_AOD_PAUSED); - - mTriggers.recalculatePausing(true /* proxFar */, false /* brightnessReady */); - verify(mMachine).requestState(DozeMachine.State.DOZE_AOD); - } }