Move fingerprint and face haptic form server to sysui(1/3)

BUG: 237621645
Test: Check the vibrator work normally when using biometric unlock
Change-Id: I16a847358fc0d4a5d486275a76a97a5195b2dddb
This commit is contained in:
Vincent Wang
2022-08-18 14:58:13 +08:00
parent 0ce3d6f92d
commit 794db1b7f7
10 changed files with 85 additions and 48 deletions

View File

@@ -30,5 +30,4 @@
lockscreen, setting this to true should come with customized drawables. --> lockscreen, setting this to true should come with customized drawables. -->
<bool name="use_lock_pattern_drawable">false</bool> <bool name="use_lock_pattern_drawable">false</bool>
<bool name="resolver_landscape_phone">true</bool> <bool name="resolver_landscape_phone">true</bool>
<bool name="system_server_plays_face_haptics">true</bool>
</resources> </resources>

View File

@@ -4847,6 +4847,5 @@
<java-symbol type="dimen" name="status_bar_height_default" /> <java-symbol type="dimen" name="status_bar_height_default" />
<java-symbol type="bool" name="system_server_plays_face_haptics" />
<java-symbol type="string" name="default_card_name"/> <java-symbol type="string" name="default_card_name"/>
</resources> </resources>

View File

@@ -77,6 +77,7 @@ import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution; import com.android.systemui.util.concurrency.Execution;
@@ -152,6 +153,19 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@NonNull private final InteractionJankMonitor mInteractionJankMonitor; @NonNull private final InteractionJankMonitor mInteractionJankMonitor;
private final @Background DelayableExecutor mBackgroundExecutor; private final @Background DelayableExecutor mBackgroundExecutor;
private final VibratorHelper mVibratorHelper;
private void vibrateSuccess(int modality) {
mVibratorHelper.vibrateAuthSuccess(
getClass().getSimpleName() + ", modality = " + modality + "BP::success");
}
private void vibrateError(int modality) {
mVibratorHelper.vibrateAuthError(
getClass().getSimpleName() + ", modality = " + modality + "BP::error");
}
@VisibleForTesting @VisibleForTesting
final TaskStackListener mTaskStackListener = new TaskStackListener() { final TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override @Override
@@ -599,7 +613,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@NonNull StatusBarStateController statusBarStateController, @NonNull StatusBarStateController statusBarStateController,
@NonNull InteractionJankMonitor jankMonitor, @NonNull InteractionJankMonitor jankMonitor,
@Main Handler handler, @Main Handler handler,
@Background DelayableExecutor bgExecutor) { @Background DelayableExecutor bgExecutor,
@NonNull VibratorHelper vibrator) {
super(context); super(context);
mExecution = execution; mExecution = execution;
mUserManager = userManager; mUserManager = userManager;
@@ -616,6 +631,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mWindowManager = windowManager; mWindowManager = windowManager;
mInteractionJankMonitor = jankMonitor; mInteractionJankMonitor = jankMonitor;
mUdfpsEnrolledForUser = new SparseBooleanArray(); mUdfpsEnrolledForUser = new SparseBooleanArray();
mVibratorHelper = vibrator;
mOrientationListener = new BiometricDisplayListener( mOrientationListener = new BiometricDisplayListener(
context, context,
@@ -837,6 +853,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
public void onBiometricAuthenticated(@Modality int modality) { public void onBiometricAuthenticated(@Modality int modality) {
if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: "); if (DEBUG) Log.d(TAG, "onBiometricAuthenticated: ");
vibrateSuccess(modality);
if (mCurrentDialog != null) { if (mCurrentDialog != null) {
mCurrentDialog.onAuthenticationSucceeded(modality); mCurrentDialog.onAuthenticationSucceeded(modality);
} else { } else {
@@ -884,6 +902,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode)); Log.d(TAG, String.format("onBiometricError(%d, %d, %d)", modality, error, vendorCode));
} }
vibrateError(modality);
final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT) final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT)
|| (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT); || (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.media.AudioAttributes; import android.media.AudioAttributes;
import android.os.Process;
import android.os.VibrationAttributes; import android.os.VibrationAttributes;
import android.os.VibrationEffect; import android.os.VibrationEffect;
import android.os.Vibrator; import android.os.Vibrator;
@@ -33,6 +34,7 @@ import java.util.concurrent.Executor;
import javax.inject.Inject; import javax.inject.Inject;
/** /**
*
*/ */
@SysUISingleton @SysUISingleton
public class VibratorHelper { public class VibratorHelper {
@@ -40,9 +42,18 @@ public class VibratorHelper {
private final Vibrator mVibrator; private final Vibrator mVibrator;
private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
private static final VibrationEffect BIOMETRIC_SUCCESS_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private static final VibrationEffect BIOMETRIC_ERROR_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
private final Executor mExecutor; private final Executor mExecutor;
/** /**
*
*/ */
@Inject @Inject
public VibratorHelper(@Nullable Vibrator vibrator, @Background Executor executor) { public VibratorHelper(@Nullable Vibrator vibrator, @Background Executor executor) {
@@ -109,4 +120,23 @@ public class VibratorHelper {
} }
mExecutor.execute(mVibrator::cancel); mExecutor.execute(mVibrator::cancel);
} }
/**
* Perform vibration when biometric authentication success
*/
public void vibrateAuthSuccess(String reason) {
vibrate(Process.myUid(),
"com.android.systemui",
BIOMETRIC_SUCCESS_VIBRATION_EFFECT, reason,
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
/**
* Perform vibration when biometric authentication error
*/
public void vibrateAuthError(String reason) {
vibrate(Process.myUid(), "com.android.systemui",
BIOMETRIC_ERROR_VIBRATION_EFFECT, reason,
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
} }

View File

@@ -28,11 +28,8 @@ 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.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.Trace; import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log; import android.util.Log;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@@ -88,12 +85,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
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();
private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3; private static final int UDFPS_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private static final VibrationEffect ERROR_VIBRATION_EFFECT =
VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
@IntDef(prefix = { "MODE_" }, value = { @IntDef(prefix = { "MODE_" }, value = {
MODE_NONE, MODE_NONE,
@@ -169,7 +160,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private final NotificationShadeWindowController mNotificationShadeWindowController; private final NotificationShadeWindowController mNotificationShadeWindowController;
private final SessionTracker mSessionTracker; private final SessionTracker mSessionTracker;
private final int mConsecutiveFpFailureThreshold; private final int mConsecutiveFpFailureThreshold;
private final boolean mShouldVibrate;
private int mMode; private int mMode;
private BiometricSourceType mBiometricType; private BiometricSourceType mBiometricType;
private KeyguardViewController mKeyguardViewController; private KeyguardViewController mKeyguardViewController;
@@ -311,8 +301,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mHandler = handler; mHandler = handler;
mConsecutiveFpFailureThreshold = resources.getInteger( mConsecutiveFpFailureThreshold = resources.getInteger(
R.integer.fp_consecutive_failure_time_ms); R.integer.fp_consecutive_failure_time_ms);
mShouldVibrate = !(resources.getBoolean(
com.android.internal.R.bool.system_server_plays_face_haptics));
mKeyguardBypassController = keyguardBypassController; mKeyguardBypassController = keyguardBypassController;
mKeyguardBypassController.setUnlockController(this); mKeyguardBypassController.setUnlockController(this);
mMetricsLogger = metricsLogger; mMetricsLogger = metricsLogger;
@@ -427,10 +415,10 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
public void startWakeAndUnlock(BiometricSourceType biometricSourceType, public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
boolean isStrongBiometric) { boolean isStrongBiometric) {
int mode = calculateMode(biometricSourceType, isStrongBiometric); int mode = calculateMode(biometricSourceType, isStrongBiometric);
if (BiometricSourceType.FACE == biometricSourceType && (mode == MODE_WAKE_AND_UNLOCK if (mode == MODE_WAKE_AND_UNLOCK
|| mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING
|| mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER)) { || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
vibrateSuccess(); vibrateSuccess(biometricSourceType);
} }
startWakeAndUnlock(mode); startWakeAndUnlock(mode);
} }
@@ -672,10 +660,11 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
} }
// Suppress all face auth errors if fingerprint can be used to authenticate // Suppress all face auth errors if fingerprint can be used to authenticate
if (biometricSourceType == BiometricSourceType.FACE if ((biometricSourceType == BiometricSourceType.FACE
&& !mUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( && !mUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())) { KeyguardUpdateMonitor.getCurrentUser()))
vibrateError(); || (biometricSourceType == BiometricSourceType.FINGERPRINT)) {
vibrateError(biometricSourceType);
} }
cleanup(); cleanup();
@@ -704,24 +693,15 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
cleanup(); cleanup();
} }
private void vibrateSuccess() { //these haptics are for device-entry only
if (mShouldVibrate) { private void vibrateSuccess(BiometricSourceType type) {
mVibratorHelper.vibrate(Process.myUid(), mVibratorHelper.vibrateAuthSuccess(
"com.android.systemui", getClass().getSimpleName() + ", type =" + type + "device-entry::success");
SUCCESS_VIBRATION_EFFECT,
getClass().getSimpleName() + "::success",
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
} }
private void vibrateError() { private void vibrateError(BiometricSourceType type) {
if (mShouldVibrate) { mVibratorHelper.vibrateAuthError(
mVibratorHelper.vibrate(Process.myUid(), getClass().getSimpleName() + ", type =" + type + "device-entry::error");
"com.android.systemui",
ERROR_VIBRATION_EFFECT,
getClass().getSimpleName() + "::error",
HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
}
} }
private void cleanup() { private void cleanup() {

View File

@@ -88,6 +88,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.util.concurrency.DelayableExecutor; import com.android.systemui.util.concurrency.DelayableExecutor;
import com.android.systemui.util.concurrency.Execution; import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.concurrency.FakeExecution; import com.android.systemui.util.concurrency.FakeExecution;
@@ -176,6 +177,9 @@ public class AuthControllerTest extends SysuiTestCase {
private DelayableExecutor mBackgroundExecutor; private DelayableExecutor mBackgroundExecutor;
private TestableAuthController mAuthController; private TestableAuthController mAuthController;
@Mock
private VibratorHelper mVibratorHelper;
@Before @Before
public void setup() throws RemoteException { public void setup() throws RemoteException {
mContextSpy = spy(mContext); mContextSpy = spy(mContext);
@@ -234,10 +238,12 @@ public class AuthControllerTest extends SysuiTestCase {
true /* supportsSelfIllumination */, true /* supportsSelfIllumination */,
true /* resetLockoutRequireHardwareAuthToken */)); true /* resetLockoutRequireHardwareAuthToken */));
when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps); when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps);
when(mVibratorHelper.hasVibrator()).thenReturn(true);
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue, mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager, mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
() -> mUdfpsController, () -> mSidefpsController, mStatusBarStateController); () -> mUdfpsController, () -> mSidefpsController, mStatusBarStateController,
mVibratorHelper);
mAuthController.start(); mAuthController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
@@ -266,11 +272,13 @@ public class AuthControllerTest extends SysuiTestCase {
reset(mFingerprintManager); reset(mFingerprintManager);
reset(mFaceManager); reset(mFaceManager);
when(mVibratorHelper.hasVibrator()).thenReturn(true);
// This test requires an uninitialized AuthController. // This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution, AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager, mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
mFaceManager, () -> mUdfpsController, () -> mSidefpsController, mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
mStatusBarStateController); mStatusBarStateController, mVibratorHelper);
authController.start(); authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
@@ -296,11 +304,13 @@ public class AuthControllerTest extends SysuiTestCase {
reset(mFingerprintManager); reset(mFingerprintManager);
reset(mFaceManager); reset(mFaceManager);
when(mVibratorHelper.hasVibrator()).thenReturn(true);
// This test requires an uninitialized AuthController. // This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution, AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager, mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
mFaceManager, () -> mUdfpsController, () -> mSidefpsController, mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
mStatusBarStateController); mStatusBarStateController, mVibratorHelper);
authController.start(); authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
@@ -858,12 +868,13 @@ public class AuthControllerTest extends SysuiTestCase {
FaceManager faceManager, FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory, Provider<UdfpsController> udfpsControllerFactory,
Provider<SidefpsController> sidefpsControllerFactory, Provider<SidefpsController> sidefpsControllerFactory,
StatusBarStateController statusBarStateController) { StatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper) {
super(context, execution, commandQueue, activityTaskManager, windowManager, super(context, execution, commandQueue, activityTaskManager, windowManager,
fingerprintManager, faceManager, udfpsControllerFactory, fingerprintManager, faceManager, udfpsControllerFactory,
sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle, sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle,
mUserManager, mLockPatternUtils, statusBarStateController, mUserManager, mLockPatternUtils, statusBarStateController,
mInteractionJankMonitor, mHandler, mBackgroundExecutor); mInteractionJankMonitor, mHandler, mBackgroundExecutor, vibratorHelper);
} }
@Override @Override

View File

@@ -100,9 +100,7 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
owner, cookie, requireConfirmation, sensorId, logger, biometricContext, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */, lockoutCache, isStrongBiometric, null /* taskStackListener */, lockoutCache,
allowBackgroundAuthentication, allowBackgroundAuthentication,
context.getResources().getBoolean( false /* shouldVibrate */,
com.android.internal.R.bool.system_server_plays_face_haptics)
/* shouldVibrate */,
isKeyguardBypassEnabled); isKeyguardBypassEnabled);
setRequestId(requestId); setRequestId(requestId);
mUsageStats = usageStats; mUsageStats = usageStats;

View File

@@ -74,7 +74,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */, isStrongBiometric, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */, lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */,
isKeyguardBypassEnabled); isKeyguardBypassEnabled);
setRequestId(requestId); setRequestId(requestId);
mUsageStats = usageStats; mUsageStats = usageStats;

View File

@@ -131,7 +131,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
taskStackListener, taskStackListener,
lockoutCache, lockoutCache,
allowBackgroundAuthentication, allowBackgroundAuthentication,
true /* shouldVibrate */, false /* shouldVibrate */,
false /* isKeyguardBypassEnabled */); false /* isKeyguardBypassEnabled */);
setRequestId(requestId); setRequestId(requestId);
mLockoutCache = lockoutCache; mLockoutCache = lockoutCache;

View File

@@ -81,7 +81,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication, isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
true /* shouldVibrate */, false /* isKeyguardBypassEnabled */); false /* shouldVibrate */, false /* isKeyguardBypassEnabled */);
setRequestId(requestId); setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker; mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController); mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);