Merge "Update configurable udfps haptics" into sc-dev

This commit is contained in:
TreeHugger Robot
2021-06-25 19:12:17 +00:00
committed by Android (Google) Code Review
7 changed files with 118 additions and 78 deletions

View File

@@ -71,6 +71,7 @@ import android.os.ServiceManager;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
@@ -85,6 +86,7 @@ import android.util.Log;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import com.android.internal.annotations.VisibleForTesting;
@@ -95,6 +97,7 @@ import com.android.systemui.DejankUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.biometrics.UdfpsController;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -282,6 +285,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@VisibleForTesting
protected boolean mTelephonyCapable;
private final boolean mAcquiredHapticEnabled;
@Nullable private final Vibrator mVibrator;
// Device provisioning state
private boolean mDeviceProvisioned;
@@ -1334,44 +1340,66 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
= new AuthenticationCallback() {
private boolean mPlayedAcquiredHaptic;
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
}
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
}
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
Trace.endSection();
}
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
Trace.endSection();
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFingerprintHelp(helpMsgId, helpString.toString());
}
// on auth success, we sometimes never received an acquired haptic
if (!mPlayedAcquiredHaptic) {
playAcquiredHaptic();
}
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFingerprintHelp(helpMsgId, helpString.toString());
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFingerprintAcquired(acquireInfo);
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
}
@Override
public void onUdfpsPointerDown(int sensorId) {
Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId);
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFingerprintAcquired(acquireInfo);
if (acquireInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
playAcquiredHaptic();
}
}
@Override
public void onUdfpsPointerUp(int sensorId) {
Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId);
}
};
@Override
public void onUdfpsPointerDown(int sensorId) {
Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId);
mPlayedAcquiredHaptic = false;
}
@Override
public void onUdfpsPointerUp(int sensorId) {
Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId);
}
private void playAcquiredHaptic() {
if (mAcquiredHapticEnabled && mVibrator != null && isUdfpsEnrolled()) {
mPlayedAcquiredHaptic = true;
String effect = Settings.Global.getString(
mContext.getContentResolver(),
"udfps_acquired_type");
mVibrator.vibrate(UdfpsController.getVibration(effect,
UdfpsController.EFFECT_TICK),
UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
};
private final FaceManager.FaceDetectionCallback mFaceDetectionCallback
= (sensorId, userId, isStrongBiometric) -> {
@@ -1663,7 +1691,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
LockPatternUtils lockPatternUtils,
AuthController authController,
TelephonyListenerManager telephonyListenerManager,
FeatureFlags featureFlags) {
FeatureFlags featureFlags,
@Nullable Vibrator vibrator) {
mContext = context;
mSubscriptionManager = SubscriptionManager.from(context);
mTelephonyListenerManager = telephonyListenerManager;
@@ -1678,6 +1707,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mLockPatternUtils = lockPatternUtils;
mAuthController = authController;
dumpManager.registerDumpable(getClass().getName(), this);
mAcquiredHapticEnabled = Settings.Global.getInt(mContext.getContentResolver(),
"udfps_acquired", 0) == 1;
mVibrator = vibrator;
mHandler = new Handler(mainLooper) {
@Override

View File

@@ -16,6 +16,8 @@
package com.android.systemui.biometrics;
import static android.os.VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
@@ -147,32 +149,22 @@ public class UdfpsController implements DozeReceiver {
private Runnable mAodInterruptRunnable;
@VisibleForTesting
static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
new AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
private final VibrationEffect mEffectTick = VibrationEffect.get(VibrationEffect.EFFECT_TICK);
private final VibrationEffect mEffectTextureTick =
public static final VibrationEffect EFFECT_TICK =
VibrationEffect.get(VibrationEffect.EFFECT_TICK);
private static final VibrationEffect EFFECT_TEXTURE_TICK =
VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK);
@VisibleForTesting
final VibrationEffect mEffectClick = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private final VibrationEffect mEffectHeavy =
static final VibrationEffect EFFECT_CLICK = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
private static final VibrationEffect EFFECT_HEAVY =
VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
private final VibrationEffect mDoubleClick =
private static final VibrationEffect EFFECT_DOUBLE_CLICK =
VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
private final Runnable mAcquiredVibration = new Runnable() {
@Override
public void run() {
if (mVibrator == null) {
return;
}
String effect = Settings.Global.getString(mContext.getContentResolver(),
"udfps_acquired_type");
mVibrator.vibrate(getVibration(effect, mEffectTick), VIBRATION_SONIFICATION_ATTRIBUTES);
}
};
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
@Override
@@ -449,16 +441,7 @@ public class UdfpsController implements DozeReceiver {
String startEffectSetting = Settings.Global.getString(
contentResolver, "udfps_start_type");
mVibrator.vibrate(getVibration(startEffectSetting,
mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES);
}
int acquiredEnabled = Settings.Global.getInt(contentResolver,
"udfps_acquired", 0);
if (acquiredEnabled > 0) {
int delay = Settings.Global.getInt(contentResolver,
"udfps_acquired_delay", 500);
mMainHandler.removeCallbacks(mAcquiredVibration);
mMainHandler.postDelayed(mAcquiredVibration, delay);
EFFECT_CLICK), VIBRATION_SONIFICATION_ATTRIBUTES);
}
}
@@ -843,7 +826,6 @@ public class UdfpsController implements DozeReceiver {
mExecution.assertIsMainThread();
mActivePointerId = -1;
mGoodCaptureReceived = false;
mMainHandler.removeCallbacks(mAcquiredVibration);
if (mView == null) {
Log.w(TAG, "Null view in onFingerUp");
return;
@@ -855,23 +837,34 @@ public class UdfpsController implements DozeReceiver {
}
private VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) {
/**
* get vibration to play given string
* used for testing purposes (b/185124905)
*/
public static VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) {
if (TextUtils.isEmpty(effect)) {
return defaultEffect;
}
switch (effect.toLowerCase()) {
case "click":
return mEffectClick;
return EFFECT_CLICK;
case "heavy":
return mEffectHeavy;
return EFFECT_HEAVY;
case "texture_tick":
return mEffectTextureTick;
return EFFECT_TEXTURE_TICK;
case "tick":
return mEffectTick;
return EFFECT_TICK;
case "double_tap":
return mDoubleClick;
return EFFECT_DOUBLE_CLICK;
default:
try {
int primitive = Integer.parseInt(effect);
if (primitive <= PRIMITIVE_LOW_TICK && primitive > -1) {
return VibrationEffect.startComposition().addPrimitive(primitive).compose();
}
} catch (NumberFormatException e) {
}
return defaultEffect;
}
}

View File

@@ -64,6 +64,7 @@ import android.os.Handler;
import android.os.IRemoteCallback;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -108,6 +109,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@@ -168,6 +170,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
private TelephonyListenerManager mTelephonyListenerManager;
@Mock
private FeatureFlags mFeatureFlags;
@Mock
private Vibrator mVibrator;
@Captor
private ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
// Direct executor
@@ -979,7 +983,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mBroadcastDispatcher, mDumpManager,
mRingerModeTracker, mBackgroundExecutor,
mStatusBarStateController, mLockPatternUtils,
mAuthController, mTelephonyListenerManager, mFeatureFlags);
mAuthController, mTelephonyListenerManager, mFeatureFlags,
mVibrator);
setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker);
}

View File

@@ -344,7 +344,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
moveEvent.recycle();
// THEN click haptic is played
verify(mVibrator).vibrate(mUdfpsController.mEffectClick,
verify(mVibrator).vibrate(mUdfpsController.EFFECT_CLICK,
UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES);
}
}

View File

@@ -192,25 +192,27 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
}
protected @NonNull VibrationEffect getSuccessVibrationEffect() {
protected @Nullable VibrationEffect getSuccessVibrationEffect() {
return mSuccessVibrationEffect;
}
protected @NonNull VibrationEffect getErrorVibrationEffect() {
protected @Nullable VibrationEffect getErrorVibrationEffect() {
return mErrorVibrationEffect;
}
protected final void vibrateSuccess() {
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
if (vibrator != null) {
vibrator.vibrate(getSuccessVibrationEffect(), VIBRATION_SONFICATION_ATTRIBUTES);
VibrationEffect effect = getSuccessVibrationEffect();
if (vibrator != null && effect != null) {
vibrator.vibrate(effect, VIBRATION_SONFICATION_ATTRIBUTES);
}
}
protected final void vibrateError() {
Vibrator vibrator = getContext().getSystemService(Vibrator.class);
if (vibrator != null) {
vibrator.vibrate(getErrorVibrationEffect(), VIBRATION_SONFICATION_ATTRIBUTES);
VibrationEffect effect = getErrorVibrationEffect();
if (vibrator != null && effect != null) {
vibrator.vibrate(effect, VIBRATION_SONFICATION_ATTRIBUTES);
}
}

View File

@@ -344,21 +344,29 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
}
@Override
protected @NonNull VibrationEffect getSuccessVibrationEffect() {
protected @Nullable VibrationEffect getSuccessVibrationEffect() {
if (!mCustomHaptics) {
return super.getSuccessVibrationEffect();
}
if (Settings.Global.getInt(mContentResolver, "fp_success_enabled", 1) == 0) {
return null;
}
return getVibration(Settings.Global.getString(mContentResolver,
"fp_success_type"), super.getSuccessVibrationEffect());
}
@Override
protected @NonNull VibrationEffect getErrorVibrationEffect() {
protected @Nullable VibrationEffect getErrorVibrationEffect() {
if (!mCustomHaptics) {
return super.getErrorVibrationEffect();
}
if (Settings.Global.getInt(mContentResolver, "fp_error_enabled", 1) == 0) {
return null;
}
return getVibration(Settings.Global.getString(mContentResolver,
"fp_error_type"), super.getErrorVibrationEffect());

View File

@@ -264,7 +264,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
@Override
protected @NonNull VibrationEffect getSuccessVibrationEffect() {
protected @Nullable VibrationEffect getSuccessVibrationEffect() {
if (!mCustomHaptics) {
return super.getSuccessVibrationEffect();
}
@@ -274,7 +274,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
}
@Override
protected @NonNull VibrationEffect getErrorVibrationEffect() {
protected @Nullable VibrationEffect getErrorVibrationEffect() {
if (!mCustomHaptics) {
return super.getErrorVibrationEffect();
}