Merge "Delay the transition to AOD1 if udfps is activated" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-09-17 13:54:05 +00:00
committed by Android (Google) Code Review
5 changed files with 151 additions and 8 deletions

View File

@@ -786,7 +786,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
.build(sensorIds, credentialAllowed, mFpProps, mFaceProps); .build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
} }
interface Callback { public interface Callback {
/** /**
* Called when authenticators are registered. If authenticators are already * Called when authenticators are registered. If authenticators are already
* registered before this call, this callback will never be triggered. * registered before this call, this callback will never be triggered.

View File

@@ -213,6 +213,14 @@ public class DozeLog implements Dumpable {
mLogger.logStateChangedSent(state); mLogger.logStateChangedSent(state);
} }
/**
* Appends display state delayed by UDFPS event to the logs
* @param delayedDisplayState the display screen state that was delayed
*/
public void traceDisplayStateDelayedByUdfps(int delayedDisplayState) {
mLogger.logDisplayStateDelayedByUdfps(delayedDisplayState);
}
/** /**
* Appends display state changed event to the logs * Appends display state changed event to the logs
* @param displayState new DozeMachine state * @param displayState new DozeMachine state

View File

@@ -160,6 +160,14 @@ class DozeLogger @Inject constructor(
}) })
} }
fun logDisplayStateDelayedByUdfps(delayedDisplayState: Int) {
buffer.log(TAG, INFO, {
str1 = Display.stateToString(delayedDisplayState)
}, {
"Delaying display state change to: $str1 due to UDFPS activity"
})
}
fun logDisplayStateChanged(displayState: Int) { fun logDisplayStateChanged(displayState: Int) {
buffer.log(TAG, INFO, { buffer.log(TAG, INFO, {
str1 = Display.stateToString(displayState) str1 = Display.stateToString(displayState)

View File

@@ -26,6 +26,11 @@ import android.os.Handler;
import android.util.Log; import android.util.Log;
import android.view.Display; import android.view.Display;
import androidx.annotation.Nullable;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.dagger.DozeScope; import com.android.systemui.doze.dagger.DozeScope;
import com.android.systemui.doze.dagger.WrappedService; import com.android.systemui.doze.dagger.WrappedService;
@@ -34,6 +39,7 @@ import com.android.systemui.util.wakelock.SettableWakeLock;
import com.android.systemui.util.wakelock.WakeLock; import com.android.systemui.util.wakelock.WakeLock;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Provider;
/** /**
* Controls the screen when dozing. * Controls the screen when dozing.
@@ -56,23 +62,61 @@ public class DozeScreenState implements DozeMachine.Part {
*/ */
public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2500; public static final int ENTER_DOZE_HIDE_WALLPAPER_DELAY = 2500;
/**
* Add an extra delay to the transition to DOZE when udfps is current activated before
* the display state transitions from ON => DOZE.
*/
public static final int UDFPS_DISPLAY_STATE_DELAY = 1200;
private final DozeMachine.Service mDozeService; private final DozeMachine.Service mDozeService;
private final Handler mHandler; private final Handler mHandler;
private final Runnable mApplyPendingScreenState = this::applyPendingScreenState; private final Runnable mApplyPendingScreenState = this::applyPendingScreenState;
private final DozeParameters mParameters; private final DozeParameters mParameters;
private final DozeHost mDozeHost; private final DozeHost mDozeHost;
private final AuthController mAuthController;
private final Provider<UdfpsController> mUdfpsControllerProvider;
@Nullable private UdfpsController mUdfpsController;
private final DozeLog mDozeLog;
private int mPendingScreenState = Display.STATE_UNKNOWN; private int mPendingScreenState = Display.STATE_UNKNOWN;
private SettableWakeLock mWakeLock; private SettableWakeLock mWakeLock;
@Inject @Inject
public DozeScreenState(@WrappedService DozeMachine.Service service, @Main Handler handler, public DozeScreenState(
DozeHost host, DozeParameters parameters, WakeLock wakeLock) { @WrappedService DozeMachine.Service service,
@Main Handler handler,
DozeHost host,
DozeParameters parameters,
WakeLock wakeLock,
AuthController authController,
Provider<UdfpsController> udfpsControllerProvider,
DozeLog dozeLog) {
mDozeService = service; mDozeService = service;
mHandler = handler; mHandler = handler;
mParameters = parameters; mParameters = parameters;
mDozeHost = host; mDozeHost = host;
mWakeLock = new SettableWakeLock(wakeLock, TAG); mWakeLock = new SettableWakeLock(wakeLock, TAG);
mAuthController = authController;
mUdfpsControllerProvider = udfpsControllerProvider;
mDozeLog = dozeLog;
updateUdfpsController();
if (mUdfpsController == null) {
mAuthController.addCallback(new AuthController.Callback() {
@Override
public void onAllAuthenticatorsRegistered() {
updateUdfpsController();
}
});
}
}
private void updateUdfpsController() {
if (mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())) {
mUdfpsController = mUdfpsControllerProvider.get();
} else {
mUdfpsController = null;
}
} }
@Override @Override
@@ -110,21 +154,28 @@ public class DozeScreenState implements DozeMachine.Part {
mPendingScreenState = screenState; mPendingScreenState = screenState;
// Delay screen state transitions even longer while animations are running. // Delay screen state transitions even longer while animations are running.
boolean shouldDelayTransition = newState == DOZE_AOD boolean shouldDelayTransitionEnteringDoze = newState == DOZE_AOD
&& mParameters.shouldControlScreenOff() && !turningOn; && mParameters.shouldControlScreenOff() && !turningOn;
if (shouldDelayTransition) { // Delay screen state transition longer if UDFPS is actively authenticating a fp
boolean shouldDelayTransitionForUDFPS = newState == DOZE_AOD
&& mUdfpsController != null && mUdfpsController.isFingerDown();
if (shouldDelayTransitionEnteringDoze || shouldDelayTransitionForUDFPS) {
mWakeLock.setAcquired(true); mWakeLock.setAcquired(true);
} }
if (!messagePending) { if (!messagePending) {
if (DEBUG) { if (DEBUG) {
Log.d(TAG, "Display state changed to " + screenState + " delayed by " Log.d(TAG, "Display state changed to " + screenState + " delayed by "
+ (shouldDelayTransition ? ENTER_DOZE_DELAY : 1)); + (shouldDelayTransitionEnteringDoze ? ENTER_DOZE_DELAY : 1));
} }
if (shouldDelayTransition) { if (shouldDelayTransitionEnteringDoze) {
mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY); mHandler.postDelayed(mApplyPendingScreenState, ENTER_DOZE_DELAY);
} else if (shouldDelayTransitionForUDFPS) {
mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
mHandler.postDelayed(mApplyPendingScreenState, UDFPS_DISPLAY_STATE_DELAY);
} else { } else {
mHandler.post(mApplyPendingScreenState); mHandler.post(mApplyPendingScreenState);
} }
@@ -139,6 +190,12 @@ public class DozeScreenState implements DozeMachine.Part {
} }
private void applyPendingScreenState() { private void applyPendingScreenState() {
if (mUdfpsController != null && mUdfpsController.isFingerDown()) {
mDozeLog.traceDisplayStateDelayedByUdfps(mPendingScreenState);
mHandler.postDelayed(mApplyPendingScreenState, UDFPS_DISPLAY_STATE_DELAY);
return;
}
applyScreenState(mPendingScreenState); applyScreenState(mPendingScreenState);
mPendingScreenState = Display.STATE_UNKNOWN; mPendingScreenState = Display.STATE_UNKNOWN;
} }

View File

@@ -21,6 +21,7 @@ import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_DOCKED;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED;
import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING;
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE;
import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING; import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSING;
import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE; import static com.android.systemui.doze.DozeMachine.State.DOZE_REQUEST_PULSE;
import static com.android.systemui.doze.DozeMachine.State.FINISH; import static com.android.systemui.doze.DozeMachine.State.FINISH;
@@ -34,6 +35,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -45,6 +47,8 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.util.wakelock.WakeLockFake; import com.android.systemui.util.wakelock.WakeLockFake;
import com.android.systemui.utils.os.FakeHandler; import com.android.systemui.utils.os.FakeHandler;
@@ -56,6 +60,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import javax.inject.Provider;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
@SmallTest @SmallTest
public class DozeScreenStateTest extends SysuiTestCase { public class DozeScreenStateTest extends SysuiTestCase {
@@ -68,17 +74,29 @@ public class DozeScreenStateTest extends SysuiTestCase {
private DozeParameters mDozeParameters; private DozeParameters mDozeParameters;
private WakeLockFake mWakeLock; private WakeLockFake mWakeLock;
private DozeScreenState mScreen; private DozeScreenState mScreen;
@Mock
private Provider<UdfpsController> mUdfpsControllerProvider;
@Mock
private AuthController mAuthController;
@Mock
private UdfpsController mUdfpsController;
@Mock
private DozeLog mDozeLog;
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true); when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
when(mDozeParameters.getAlwaysOn()).thenReturn(true); when(mDozeParameters.getAlwaysOn()).thenReturn(true);
when(mUdfpsControllerProvider.get()).thenReturn(mUdfpsController);
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
when(mUdfpsController.isFingerDown()).thenReturn(false);
mServiceFake = new DozeServiceFake(); mServiceFake = new DozeServiceFake();
mHandlerFake = new FakeHandler(Looper.getMainLooper()); mHandlerFake = new FakeHandler(Looper.getMainLooper());
mWakeLock = new WakeLockFake(); mWakeLock = new WakeLockFake();
mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters, mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
mWakeLock); mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog);
} }
@Test @Test
@@ -233,4 +251,56 @@ public class DozeScreenStateTest extends SysuiTestCase {
assertEquals(Display.STATE_OFF, mServiceFake.screenState); assertEquals(Display.STATE_OFF, mServiceFake.screenState);
} }
@Test
public void testDelayEnterDozeScreenState_whenUdfpsFingerDown() {
// GIVEN AOD is initialized
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mHandlerFake.dispatchQueuedMessages();
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
// WHEN udfps is activated (fingerDown)
when(mUdfpsController.isFingerDown()).thenReturn(true);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state doesn't immediately change
assertEquals(Display.STATE_ON, mServiceFake.screenState);
// WHEN udfpsController finger is no longer down and the queued messages are run
when(mUdfpsController.isFingerDown()).thenReturn(false);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state will change
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
@Test
public void testDelayExitPulsingScreenState_whenUdfpsFingerDown() {
// GIVEN we're pulsing
when(mDozeParameters.shouldControlScreenOff()).thenReturn(true);
mHandlerFake.setMode(QUEUEING);
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE_AOD, DOZE_REQUEST_PULSE);
mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
mHandlerFake.dispatchQueuedMessages();
// WHEN udfps is activated while are transitioning back to DOZE_AOD
mScreen.transitionTo(DOZE_PULSE_DONE, DOZE_AOD);
when(mUdfpsController.isFingerDown()).thenReturn(true);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state doesn't immediately change
assertEquals(Display.STATE_ON, mServiceFake.screenState);
// WHEN udfpsController finger is no longer down and the queued messages are run
when(mUdfpsController.isFingerDown()).thenReturn(false);
mHandlerFake.dispatchQueuedMessages();
// THEN the display screen state will change
assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
}
} }