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,
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,
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,
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);
}
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);
- }
}
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;
private final boolean mAllowPulseTriggers;
private final UiModeManager mUiModeManager;
private final TriggerReceiver mBroadcastReceiver = new TriggerReceiver();
- private final DozeScreenBrightness mDozeScreenBrightness;
private long mNotificationPulseTime;
private boolean mPulsePending;
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;
config, wakeLock, this::onSensor, this::onProximityFar,
new AlwaysOnDisplayPolicy(context));
mUiModeManager = mContext.getSystemService(UiModeManager.class);
- mDozeScreenBrightness = brightness;
}
private void onNotification() {
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) {
case INITIALIZED:
mBroadcastReceiver.register(mContext);
mDozeHost.addCallback(mHostCallback);
- mDozeScreenBrightness.setBrightnessReadyListener(this::onBrightnessReady);
checkTriggersAtInit();
break;
case DOZE:
boolean dozing;
float doubleTapX;
float doubleTapY;
+ float aodDimmingScrimOpacity;
@Override
public void addCallback(@NonNull Callback callback) {
@Override
public void setDozeScreenBrightness(int value) {
}
+
+ @Override
+ public void setAodDimmingScrim(float scrimOpacity) {
+ aodDimmingScrimOpacity = scrimOpacity;
+ }
}
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;
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
-
- assertTrue(mScreen.isReady());
}
@Test
}
@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
private WakeLock mWakeLock;
private Instrumentation mInstrumentation;
private AlarmManager mAlarmManager;
- private DozeScreenBrightness mDozeScreenBrightness;
@BeforeClass
public static void setupSuite() {
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);
});
}
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);
- }
}