Merge "Move fingerprint and face haptic form server to sysui(1/3)" into tm-qpr-dev am: b6639e64e3

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20284929

Change-Id: I85871d0906119f72bcbcd381f72cf3bdc06d933f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Vincent Wang
2022-11-03 06:29:31 +00:00
committed by Automerger Merge Worker
10 changed files with 84 additions and 49 deletions

View File

@@ -31,5 +31,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

@@ -4885,6 +4885,4 @@
<java-symbol type="id" name="language_picker_header" /> <java-symbol type="id" name="language_picker_header" />
<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" />
</resources> </resources>

View File

@@ -78,6 +78,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;
@@ -160,6 +161,19 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
private final @Background DelayableExecutor mBackgroundExecutor; private final @Background DelayableExecutor mBackgroundExecutor;
private final DisplayInfo mCachedDisplayInfo = new DisplayInfo(); private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
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
@@ -671,7 +685,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
@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) {
mContext = context; mContext = context;
mExecution = execution; mExecution = execution;
mUserManager = userManager; mUserManager = userManager;
@@ -689,6 +704,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
mInteractionJankMonitor = jankMonitor; mInteractionJankMonitor = jankMonitor;
mUdfpsEnrolledForUser = new SparseBooleanArray(); mUdfpsEnrolledForUser = new SparseBooleanArray();
mSfpsEnrolledForUser = new SparseBooleanArray(); mSfpsEnrolledForUser = new SparseBooleanArray();
mVibratorHelper = vibrator;
mOrientationListener = new BiometricDisplayListener( mOrientationListener = new BiometricDisplayListener(
context, context,
@@ -878,6 +894,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
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 {
@@ -930,6 +948,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
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;
public static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = public 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

@@ -27,11 +27,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;
@@ -87,12 +84,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,
@@ -167,7 +158,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;
@@ -307,8 +297,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;
@@ -423,10 +411,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);
} }
@@ -659,10 +647,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();
@@ -688,24 +677,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

@@ -87,6 +87,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;
@@ -173,6 +174,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);
@@ -221,7 +225,8 @@ public class AuthControllerTest extends SysuiTestCase {
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(
@@ -246,11 +251,13 @@ public class AuthControllerTest extends SysuiTestCase {
// This test is sensitive to prior FingerprintManager interactions. // This test is sensitive to prior FingerprintManager interactions.
reset(mFingerprintManager); reset(mFingerprintManager);
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(
@@ -270,11 +277,13 @@ public class AuthControllerTest extends SysuiTestCase {
// This test is sensitive to prior FingerprintManager interactions. // This test is sensitive to prior FingerprintManager interactions.
reset(mFingerprintManager); reset(mFingerprintManager);
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(
@@ -928,12 +937,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

@@ -135,7 +135,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);