Merge "RESTRICT AUTOMERGE SFPS: Don't play auth haptics if power button pressed" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2023-01-11 18:01:11 +00:00
committed by Android (Google) Code Review
5 changed files with 146 additions and 12 deletions

View File

@@ -33,6 +33,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@@ -63,6 +64,7 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
private final Context mContext; private final Context mContext;
private final DisplayMetrics mDisplayMetrics; private final DisplayMetrics mDisplayMetrics;
private final SystemClock mSystemClock;
@Nullable @Nullable
private final IWallpaperManager mWallpaperManagerService; private final IWallpaperManager mWallpaperManagerService;
@@ -71,6 +73,9 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
private @PowerManager.WakeReason int mLastWakeReason = PowerManager.WAKE_REASON_UNKNOWN; private @PowerManager.WakeReason int mLastWakeReason = PowerManager.WAKE_REASON_UNKNOWN;
public static final long UNKNOWN_LAST_WAKE_TIME = -1;
private long mLastWakeTime = UNKNOWN_LAST_WAKE_TIME;
@Nullable @Nullable
private Point mLastWakeOriginLocation = null; private Point mLastWakeOriginLocation = null;
@@ -84,10 +89,12 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
public WakefulnessLifecycle( public WakefulnessLifecycle(
Context context, Context context,
@Nullable IWallpaperManager wallpaperManagerService, @Nullable IWallpaperManager wallpaperManagerService,
SystemClock systemClock,
DumpManager dumpManager) { DumpManager dumpManager) {
mContext = context; mContext = context;
mDisplayMetrics = context.getResources().getDisplayMetrics(); mDisplayMetrics = context.getResources().getDisplayMetrics();
mWallpaperManagerService = wallpaperManagerService; mWallpaperManagerService = wallpaperManagerService;
mSystemClock = systemClock;
dumpManager.registerDumpable(getClass().getSimpleName(), this); dumpManager.registerDumpable(getClass().getSimpleName(), this);
} }
@@ -103,6 +110,14 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
return mLastWakeReason; return mLastWakeReason;
} }
/**
* Returns the most recent time (in device uptimeMillis) the display woke up.
* Returns {@link UNKNOWN_LAST_WAKE_TIME} if there hasn't been a wakeup yet.
*/
public long getLastWakeTime() {
return mLastWakeTime;
}
/** /**
* Returns the most recent reason the device went to sleep up. This is one of * Returns the most recent reason the device went to sleep up. This is one of
* PowerManager.GO_TO_SLEEP_REASON_*. * PowerManager.GO_TO_SLEEP_REASON_*.
@@ -117,6 +132,7 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
} }
setWakefulness(WAKEFULNESS_WAKING); setWakefulness(WAKEFULNESS_WAKING);
mLastWakeReason = pmWakeReason; mLastWakeReason = pmWakeReason;
mLastWakeTime = mSystemClock.uptimeMillis();
updateLastWakeOriginLocation(); updateLastWakeOriginLocation();
if (mWallpaperManagerService != null) { if (mWallpaperManagerService != null) {

View File

@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.phone;
import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static com.android.systemui.keyguard.WakefulnessLifecycle.UNKNOWN_LAST_WAKE_TIME;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.content.res.Resources; import android.content.res.Resources;
import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFaceConstants;
@@ -27,7 +29,6 @@ import android.hardware.fingerprint.FingerprintManager;
import android.metrics.LogMaker; import android.metrics.LogMaker;
import android.os.Handler; import android.os.Handler;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace; import android.os.Trace;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -62,6 +63,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.time.SystemClock;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
@@ -78,6 +80,7 @@ import javax.inject.Inject;
*/ */
@SysUISingleton @SysUISingleton
public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable { public class BiometricUnlockController extends KeyguardUpdateMonitorCallback implements Dumpable {
private static final long RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS = 400L;
private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000; private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock"; private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl(); private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
@@ -169,9 +172,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private final MetricsLogger mMetricsLogger; private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController; private final AuthController mAuthController;
private final StatusBarStateController mStatusBarStateController; private final StatusBarStateController mStatusBarStateController;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private final LatencyTracker mLatencyTracker; private final LatencyTracker mLatencyTracker;
private final VibratorHelper mVibratorHelper; private final VibratorHelper mVibratorHelper;
private final BiometricUnlockLogger mLogger; private final BiometricUnlockLogger mLogger;
private final SystemClock mSystemClock;
private long mLastFpFailureUptimeMillis; private long mLastFpFailureUptimeMillis;
private int mNumConsecutiveFpFailures; private int mNumConsecutiveFpFailures;
@@ -279,14 +284,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
SessionTracker sessionTracker, SessionTracker sessionTracker,
LatencyTracker latencyTracker, LatencyTracker latencyTracker,
ScreenOffAnimationController screenOffAnimationController, ScreenOffAnimationController screenOffAnimationController,
VibratorHelper vibrator) { VibratorHelper vibrator,
SystemClock systemClock
) {
mPowerManager = powerManager; mPowerManager = powerManager;
mShadeController = shadeController; mShadeController = shadeController;
mUpdateMonitor = keyguardUpdateMonitor; mUpdateMonitor = keyguardUpdateMonitor;
mUpdateMonitor.registerCallback(this); mUpdateMonitor.registerCallback(this);
mMediaManager = notificationMediaManager; mMediaManager = notificationMediaManager;
mLatencyTracker = latencyTracker; mLatencyTracker = latencyTracker;
wakefulnessLifecycle.addObserver(mWakefulnessObserver); mWakefulnessLifecycle = wakefulnessLifecycle;
mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
screenLifecycle.addObserver(mScreenObserver); screenLifecycle.addObserver(mScreenObserver);
mNotificationShadeWindowController = notificationShadeWindowController; mNotificationShadeWindowController = notificationShadeWindowController;
@@ -306,6 +314,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mScreenOffAnimationController = screenOffAnimationController; mScreenOffAnimationController = screenOffAnimationController;
mVibratorHelper = vibrator; mVibratorHelper = vibrator;
mLogger = biometricUnlockLogger; mLogger = biometricUnlockLogger;
mSystemClock = systemClock;
dumpManager.registerDumpable(getClass().getName(), this); dumpManager.registerDumpable(getClass().getName(), this);
} }
@@ -429,8 +438,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
Runnable wakeUp = ()-> { Runnable wakeUp = ()-> {
if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) { if (!wasDeviceInteractive || mUpdateMonitor.isDreaming()) {
mLogger.i("bio wakelock: Authenticated, waking up..."); mLogger.i("bio wakelock: Authenticated, waking up...");
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_BIOMETRIC, mPowerManager.wakeUp(
"android.policy:BIOMETRIC"); mSystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_BIOMETRIC,
"android.policy:BIOMETRIC"
);
} }
Trace.beginSection("release wake-and-unlock"); Trace.beginSection("release wake-and-unlock");
releaseBiometricWakeLock(); releaseBiometricWakeLock();
@@ -670,7 +682,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
startWakeAndUnlock(MODE_ONLY_WAKE); startWakeAndUnlock(MODE_ONLY_WAKE);
} else if (biometricSourceType == BiometricSourceType.FINGERPRINT } else if (biometricSourceType == BiometricSourceType.FINGERPRINT
&& mUpdateMonitor.isUdfpsSupported()) { && mUpdateMonitor.isUdfpsSupported()) {
long currUptimeMillis = SystemClock.uptimeMillis(); long currUptimeMillis = mSystemClock.uptimeMillis();
if (currUptimeMillis - mLastFpFailureUptimeMillis < mConsecutiveFpFailureThreshold) { if (currUptimeMillis - mLastFpFailureUptimeMillis < mConsecutiveFpFailureThreshold) {
mNumConsecutiveFpFailures += 1; mNumConsecutiveFpFailures += 1;
} else { } else {
@@ -718,12 +730,26 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
cleanup(); cleanup();
} }
//these haptics are for device-entry only // these haptics are for device-entry only
private void vibrateSuccess(BiometricSourceType type) { private void vibrateSuccess(BiometricSourceType type) {
if (mAuthController.isSfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser())
&& lastWakeupFromPowerButtonWithinHapticThreshold()) {
mLogger.d("Skip auth success haptic. Power button was recently pressed.");
return;
}
mVibratorHelper.vibrateAuthSuccess( mVibratorHelper.vibrateAuthSuccess(
getClass().getSimpleName() + ", type =" + type + "device-entry::success"); getClass().getSimpleName() + ", type =" + type + "device-entry::success");
} }
private boolean lastWakeupFromPowerButtonWithinHapticThreshold() {
final boolean lastWakeupFromPowerButton = mWakefulnessLifecycle.getLastWakeReason()
== PowerManager.WAKE_REASON_POWER_BUTTON;
return lastWakeupFromPowerButton
&& mWakefulnessLifecycle.getLastWakeTime() != UNKNOWN_LAST_WAKE_TIME
&& mSystemClock.uptimeMillis() - mWakefulnessLifecycle.getLastWakeTime()
< RECENT_POWER_BUTTON_PRESS_THRESHOLD_MS;
}
private void vibrateError(BiometricSourceType type) { private void vibrateError(BiometricSourceType type) {
mVibratorHelper.vibrateAuthError( mVibratorHelper.vibrateAuthError(
getClass().getSimpleName() + ", type =" + type + "device-entry::error"); getClass().getSimpleName() + ", type =" + type + "device-entry::error");
@@ -816,7 +842,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
if (mUpdateMonitor.isUdfpsSupported()) { if (mUpdateMonitor.isUdfpsSupported()) {
pw.print(" mNumConsecutiveFpFailures="); pw.println(mNumConsecutiveFpFailures); pw.print(" mNumConsecutiveFpFailures="); pw.println(mNumConsecutiveFpFailures);
pw.print(" time since last failure="); pw.print(" time since last failure=");
pw.println(SystemClock.uptimeMillis() - mLastFpFailureUptimeMillis); pw.println(mSystemClock.uptimeMillis() - mLastFpFailureUptimeMillis);
} }
} }

View File

@@ -30,6 +30,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.DumpManager;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -51,7 +52,12 @@ public class WakefulnessLifecycleTest extends SysuiTestCase {
public void setUp() throws Exception { public void setUp() throws Exception {
mWallpaperManager = mock(IWallpaperManager.class); mWallpaperManager = mock(IWallpaperManager.class);
mWakefulness = mWakefulness =
new WakefulnessLifecycle(mContext, mWallpaperManager, mock(DumpManager.class)); new WakefulnessLifecycle(
mContext,
mWallpaperManager,
new FakeSystemClock(),
mock(DumpManager.class)
);
mWakefulnessObserver = mock(WakefulnessLifecycle.Observer.class); mWakefulnessObserver = mock(WakefulnessLifecycle.Observer.class);
mWakefulness.addObserver(mWakefulnessObserver); mWakefulness.addObserver(mWakefulnessObserver);
} }

View File

@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.phone; package com.android.systemui.statusbar.phone;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -57,6 +59,7 @@ import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShadeWindowController;
import com.android.systemui.statusbar.VibratorHelper; import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.time.FakeSystemClock;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -122,6 +125,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
private VibratorHelper mVibratorHelper; private VibratorHelper mVibratorHelper;
@Mock @Mock
private BiometricUnlockLogger mLogger; private BiometricUnlockLogger mLogger;
private final FakeSystemClock mSystemClock = new FakeSystemClock();
private BiometricUnlockController mBiometricUnlockController; private BiometricUnlockController mBiometricUnlockController;
@Before @Before
@@ -144,7 +148,9 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
mMetricsLogger, mDumpManager, mPowerManager, mLogger, mMetricsLogger, mDumpManager, mPowerManager, mLogger,
mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle, mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController, mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController,
mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper); mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper,
mSystemClock
);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener); mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener);
when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker); when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(mStrongAuthTracker);
@@ -207,7 +213,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
verify(mKeyguardViewMediator).onWakeAndUnlocking(); verify(mKeyguardViewMediator).onWakeAndUnlocking();
assertThat(mBiometricUnlockController.getMode()) assertThat(mBiometricUnlockController.getMode())
.isEqualTo(BiometricUnlockController.MODE_WAKE_AND_UNLOCK); .isEqualTo(MODE_WAKE_AND_UNLOCK);
} }
@Test @Test
@@ -457,4 +463,83 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
// THEN wakeup the device // THEN wakeup the device
verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString()); verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString());
} }
@Test
public void onSideFingerprintSuccess_recentPowerButtonPress_noHaptic() {
// GIVEN side fingerprint enrolled, last wake reason was power button
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
when(mWakefulnessLifecycle.getLastWakeReason())
.thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
// GIVEN last wake time just occurred
when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
// WHEN biometric fingerprint succeeds
givenFingerprintModeUnlockCollapsing();
mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
true);
// THEN DO NOT vibrate the device
verify(mVibratorHelper, never()).vibrateAuthSuccess(anyString());
}
@Test
public void onSideFingerprintSuccess_oldPowerButtonPress_playHaptic() {
// GIVEN side fingerprint enrolled, last wake reason was power button
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
when(mWakefulnessLifecycle.getLastWakeReason())
.thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
// GIVEN last wake time was 500ms ago
when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
mSystemClock.advanceTime(500);
// WHEN biometric fingerprint succeeds
givenFingerprintModeUnlockCollapsing();
mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
true);
// THEN vibrate the device
verify(mVibratorHelper).vibrateAuthSuccess(anyString());
}
@Test
public void onSideFingerprintSuccess_recentGestureWakeUp_playHaptic() {
// GIVEN side fingerprint enrolled, wakeup just happened
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
// GIVEN last wake reason was from a gesture
when(mWakefulnessLifecycle.getLastWakeReason())
.thenReturn(PowerManager.WAKE_REASON_GESTURE);
// WHEN biometric fingerprint succeeds
givenFingerprintModeUnlockCollapsing();
mBiometricUnlockController.startWakeAndUnlock(BiometricSourceType.FINGERPRINT,
true);
// THEN vibrate the device
verify(mVibratorHelper).vibrateAuthSuccess(anyString());
}
@Test
public void onSideFingerprintFail_alwaysPlaysHaptic() {
// GIVEN side fingerprint enrolled, last wake reason was recent power button
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
when(mWakefulnessLifecycle.getLastWakeReason())
.thenReturn(PowerManager.WAKE_REASON_POWER_BUTTON);
when(mWakefulnessLifecycle.getLastWakeTime()).thenReturn(mSystemClock.uptimeMillis());
// WHEN biometric fingerprint fails
mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
// THEN always vibrate the device
verify(mVibratorHelper).vibrateAuthError(anyString());
}
private void givenFingerprintModeUnlockCollapsing() {
when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
when(mKeyguardStateController.isShowing()).thenReturn(true);
}
} }

View File

@@ -380,7 +380,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
}).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any()); }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
mWakefulnessLifecycle = mWakefulnessLifecycle =
new WakefulnessLifecycle(mContext, mIWallpaperManager, mDumpManager); new WakefulnessLifecycle(mContext, mIWallpaperManager, mFakeSystemClock,
mDumpManager);
mWakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN); mWakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNKNOWN);
mWakefulnessLifecycle.dispatchFinishedWakingUp(); mWakefulnessLifecycle.dispatchFinishedWakingUp();