Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 270922b3 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update configurable udfps haptics" into sc-dev

parents e947e2e2 6b0285cc
Loading
Loading
Loading
Loading
+64 −32
Original line number Diff line number Diff line
@@ -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,6 +1340,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab

    private final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
            = new AuthenticationCallback() {
                private boolean mPlayedAcquiredHaptic;

                @Override
                public void onAuthenticationFailed() {
@@ -1345,6 +1352,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                    Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
                    handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
                    Trace.endSection();

                    // on auth success, we sometimes never received an acquired haptic
                    if (!mPlayedAcquiredHaptic) {
                        playAcquiredHaptic();
                    }
                }

                @Override
@@ -1360,17 +1372,33 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                @Override
                public void onAuthenticationAcquired(int acquireInfo) {
                    handleFingerprintAcquired(acquireInfo);
                    if (acquireInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
                        playAcquiredHaptic();
                    }
                }

                @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
@@ -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
+27 −34
Original line number Diff line number Diff line
@@ -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;
        }
    }
+6 −1
Original line number Diff line number Diff line
@@ -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);
        }

+1 −1
Original line number Diff line number Diff line
@@ -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);
    }
}
+8 −6
Original line number Diff line number Diff line
@@ -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);
        }
    }

Loading