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

Commit 61ce1506 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Add ability to enable extra udfps vibrations" into sc-dev

parents 859ba010 71f63963
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1359,7 +1359,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
                mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
                        "com.android.systemui:AOD_INTERRUPT_END");
            }
            mAuthController.onCancelAodInterrupt();
            mAuthController.onCancelUdfps();
            mIsUdfpsRunningWhileDozing = false;
        }
    };
+6 −8
Original line number Diff line number Diff line
@@ -309,18 +309,14 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
    }

    /**
     * Cancel a fingerprint scan.
     *
     * The sensor that triggers an AOD interrupt for fingerprint doesn't give
     * ACTION_UP/ACTION_CANCEL events, so the scan needs to be cancelled manually. This should be
     * called when authentication either succeeds or fails. Failing to cancel the scan will leave
     * the screen in high brightness mode.
     * Cancel a fingerprint scan manually. This will get rid of the white circle on the udfps
     * sensor area even if the user hasn't explicitly lifted their finger yet.
     */
    public void onCancelAodInterrupt() {
    public void onCancelUdfps() {
        if (mUdfpsController == null) {
            return;
        }
        mUdfpsController.onCancelAodInterrupt();
        mUdfpsController.onCancelUdfps();
    }

    private void sendResultAndCleanUp(@DismissedReason int reason,
@@ -499,6 +495,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
            if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
            mCurrentDialog.onError(errorMessage);
        }

        onCancelUdfps();
    }

    @Override
+92 −9
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,15 +36,23 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
import android.media.AudioAttributes;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
import android.view.View;
import android.view.WindowManager;

import com.android.internal.annotations.VisibleForTesting;
@@ -94,7 +103,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
    @NonNull private final DumpManager mDumpManager;
    @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
    @NonNull private final KeyguardViewMediator mKeyguardViewMediator;
    @NonNull private FalsingManager mFalsingManager;
    @NonNull private final Vibrator mVibrator;
    @NonNull private final Handler mMainHandler;
    @NonNull private final FalsingManager mFalsingManager;
    // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
    // sensors, this, in addition to a lot of the code here, will be updated.
    @VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -118,6 +129,27 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
    private boolean mIsAodInterruptActive;
    @Nullable private Runnable mCancelAodTimeoutAction;

    private 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 =
            VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK);
    private final VibrationEffect mEffectClick = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
    private final VibrationEffect mEffectHeavy =
            VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
    private final Runnable mAcquiredVibration = new Runnable() {
        @Override
        public void run() {
            String effect = Settings.Global.getString(mContext.getContentResolver(),
                    "udfps_acquired_type");
            mVibrator.vibrate(getVibration(effect, mEffectTick), VIBRATION_SONIFICATION_ATTRIBUTES);
        }
    };

    /**
     * Keeps track of state within a single FingerprintService request. Note that this state
     * persists across configuration changes, etc, since it is considered a single request.
@@ -227,7 +259,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
    };

    @SuppressLint("ClickableViewAccessibility")
    private final UdfpsView.OnTouchListener mOnTouchListener = (view, event) -> {
    private final UdfpsView.OnTouchListener mOnTouchListener = this::onTouch;

    private boolean onTouch(View view, MotionEvent event) {
        UdfpsView udfpsView = (UdfpsView) view;
        final boolean isFingerDown = udfpsView.isIlluminationRequested();
        boolean handled = false;
@@ -251,6 +285,27 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
                    // data for many other pointers because of multi-touch support.
                    mActivePointerId = event.getPointerId(0);
                    mVelocityTracker.addMovement(event);

                    // TODO: (b/185124905) these settings are for ux testing purposes and should
                    // be removed (or cached) before going into production
                    final ContentResolver contentResolver = mContext.getContentResolver();
                    int startEnabled = Settings.Global.getInt(contentResolver,
                            "udfps_start", 0);
                    if (startEnabled > 0) {
                        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);
                    }
                    handled = true;
                }
                break;
@@ -307,7 +362,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
                // Do nothing.
        }
        return handled;
    };
    }

    @Inject
    public UdfpsController(@NonNull Context context,
@@ -324,6 +379,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
            @NonNull KeyguardViewMediator keyguardViewMediator,
            @NonNull FalsingManager falsingManager) {
        mContext = context;
        // TODO (b/185124905): inject main handler and vibrator once done prototyping
        mMainHandler = new Handler(Looper.getMainLooper());
        mVibrator = context.getSystemService(Vibrator.class);
        mInflater = inflater;
        // The fingerprint manager is queried for UDFPS before this class is constructed, so the
        // fingerprint manager should never be null.
@@ -559,19 +617,25 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
        // Since the sensor that triggers the AOD interrupt doesn't provide ACTION_UP/ACTION_CANCEL,
        // we need to be careful about not letting the screen accidentally remain in high brightness
        // mode. As a mitigation, queue a call to cancel the fingerprint scan.
        mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelAodInterrupt,
        mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelUdfps,
                AOD_INTERRUPT_TIMEOUT_MILLIS);
        // using a hard-coded value for major and minor until it is available from the sensor
        onFingerDown(screenX, screenY, minor, major);
    }

    /**
     * Cancel fingerprint scan.
     * Cancel updfs scan affordances - ability to hide the HbmSurfaceView (white circle) before
     * user explicitly lifts their finger. Generally, this should be called whenever udfps fails
     * or errors.
     *
     * This is intended to be called after the fingerprint scan triggered by the AOD interrupt
     * either succeeds or fails.
     * The sensor that triggers an AOD fingerprint interrupt (see onAodInterrupt) doesn't give
     * ACTION_UP/ACTION_CANCEL events, so and AOD interrupt scan needs to be cancelled manually.
     * This should be called when authentication either succeeds or fails. Failing to cancel the
     * scan will leave the screen in high brightness mode and will show the HbmSurfaceView until
     * the user lifts their finger.
     */
    void onCancelAodInterrupt() {
    void onCancelUdfps() {
        onFingerUp();
        if (!mIsAodInterruptActive) {
            return;
        }
@@ -580,7 +644,6 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
            mCancelAodTimeoutAction = null;
        }
        mIsAodInterruptActive = false;
        onFingerUp();
    }

    // This method can be called from the UI thread.
@@ -598,6 +661,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {

    // This method can be called from the UI thread.
    private void onFingerUp() {
        mMainHandler.removeCallbacks(mAcquiredVibration);
        if (mView == null) {
            Log.w(TAG, "Null view in onFingerUp");
            return;
@@ -617,4 +681,23 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
        // Do nothing. This method can be implemented for devices that require the high-brightness
        // mode for fingerprint illumination.
    }

    private VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) {
        if (TextUtils.isEmpty(effect)) {
            return defaultEffect;
        }

        switch (effect.toLowerCase()) {
            case "click":
                return mEffectClick;
            case "heavy":
                return mEffectHeavy;
            case "texture_tick":
                return mEffectTextureTick;
            case "tick":
                return mEffectTick;
            default:
                return defaultEffect;
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -537,7 +537,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        authCallback.onAuthenticationFailed();

        // THEN aod interrupt is cancelled
        verify(mAuthController).onCancelAodInterrupt();
        verify(mAuthController).onCancelUdfps();
    }

    @Test
@@ -557,7 +557,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        authCallback.onAuthenticationError(0, "");

        // THEN aod interrupt is cancelled
        verify(mAuthController).onCancelAodInterrupt();
        verify(mAuthController).onCancelUdfps();
    }

    @Test
+1 −1
Original line number Diff line number Diff line
@@ -259,7 +259,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
        mFgExecutor.runAllReady();
        mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
        // WHEN it is cancelled
        mUdfpsController.onCancelAodInterrupt();
        mUdfpsController.onCancelUdfps();
        // THEN the illumination is hidden
        verify(mUdfpsView).stopIllumination();
    }