• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.biometrics;
18 
19 import static android.app.StatusBarManager.SESSION_BIOMETRIC_PROMPT;
20 import static android.app.StatusBarManager.SESSION_KEYGUARD;
21 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_GOOD;
22 import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
23 import static android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_BP;
24 import static android.hardware.biometrics.BiometricRequestConstants.REASON_AUTH_KEYGUARD;
25 import static android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_ENROLLING;
26 import static android.hardware.biometrics.BiometricRequestConstants.REASON_ENROLL_FIND_SENSOR;
27 
28 import static com.android.internal.util.LatencyTracker.ACTION_UDFPS_ILLUMINATE;
29 import static com.android.internal.util.Preconditions.checkNotNull;
30 import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
31 
32 import android.content.BroadcastReceiver;
33 import android.content.Context;
34 import android.content.Intent;
35 import android.content.IntentFilter;
36 import android.graphics.Rect;
37 import android.hardware.biometrics.BiometricFingerprintConstants;
38 import android.hardware.biometrics.BiometricPrompt;
39 import android.hardware.biometrics.SensorProperties;
40 import android.hardware.display.DisplayManager;
41 import android.hardware.fingerprint.FingerprintManager;
42 import android.hardware.fingerprint.FingerprintSensorProperties;
43 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
44 import android.hardware.fingerprint.IUdfpsOverlayController;
45 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
46 import android.hardware.input.InputManager;
47 import android.os.Build;
48 import android.os.CancellationSignal;
49 import android.os.Handler;
50 import android.os.Looper;
51 import android.os.PowerManager;
52 import android.os.Trace;
53 import android.os.VibrationAttributes;
54 import android.os.VibrationEffect;
55 import android.provider.Settings;
56 import android.util.Log;
57 import android.view.HapticFeedbackConstants;
58 import android.view.LayoutInflater;
59 import android.view.MotionEvent;
60 import android.view.View;
61 import android.view.WindowManager;
62 import android.view.accessibility.AccessibilityManager;
63 
64 import androidx.annotation.NonNull;
65 import androidx.annotation.Nullable;
66 
67 import com.android.internal.R;
68 import com.android.internal.annotations.VisibleForTesting;
69 import com.android.internal.logging.InstanceId;
70 import com.android.internal.util.LatencyTracker;
71 import com.android.keyguard.KeyguardUpdateMonitor;
72 import com.android.keyguard.UserActivityNotifier;
73 import com.android.systemui.Dumpable;
74 import com.android.systemui.Flags;
75 import com.android.systemui.animation.ActivityTransitionAnimator;
76 import com.android.systemui.biometrics.dagger.BiometricsBackground;
77 import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor;
78 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
79 import com.android.systemui.biometrics.udfps.InteractionEvent;
80 import com.android.systemui.biometrics.udfps.NormalizedTouchData;
81 import com.android.systemui.biometrics.udfps.SinglePointerTouchProcessor;
82 import com.android.systemui.biometrics.udfps.TouchProcessor;
83 import com.android.systemui.biometrics.udfps.TouchProcessorResult;
84 import com.android.systemui.biometrics.ui.viewmodel.DefaultUdfpsTouchOverlayViewModel;
85 import com.android.systemui.biometrics.ui.viewmodel.DeviceEntryUdfpsTouchOverlayViewModel;
86 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
87 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
88 import com.android.systemui.dagger.SysUISingleton;
89 import com.android.systemui.dagger.qualifiers.Application;
90 import com.android.systemui.dagger.qualifiers.Main;
91 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
92 import com.android.systemui.doze.DozeReceiver;
93 import com.android.systemui.dump.DumpManager;
94 import com.android.systemui.keyguard.ScreenLifecycle;
95 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
96 import com.android.systemui.log.SessionTracker;
97 import com.android.systemui.plugins.FalsingManager;
98 import com.android.systemui.plugins.statusbar.StatusBarStateController;
99 import com.android.systemui.power.domain.interactor.PowerInteractor;
100 import com.android.systemui.shade.ShadeDisplayAware;
101 import com.android.systemui.shade.domain.interactor.ShadeInteractor;
102 import com.android.systemui.shared.system.SysUiStatsLog;
103 import com.android.systemui.statusbar.VibratorHelper;
104 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
105 import com.android.systemui.statusbar.phone.SystemUIDialogManager;
106 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
107 import com.android.systemui.statusbar.policy.ConfigurationController;
108 import com.android.systemui.statusbar.policy.KeyguardStateController;
109 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
110 import com.android.systemui.util.concurrency.DelayableExecutor;
111 import com.android.systemui.util.concurrency.Execution;
112 import com.android.systemui.util.time.SystemClock;
113 
114 import dagger.Lazy;
115 
116 import kotlin.Unit;
117 
118 import kotlinx.coroutines.CoroutineScope;
119 
120 import java.io.PrintWriter;
121 import java.util.ArrayList;
122 import java.util.HashSet;
123 import java.util.Set;
124 import java.util.concurrent.Executor;
125 
126 import javax.inject.Inject;
127 
128 /**
129  * Shows and hides the under-display fingerprint sensor (UDFPS) overlay, handles UDFPS touch events,
130  * and toggles the UDFPS display mode.
131  *
132  * Note that the current architecture is designed so that a single {@link UdfpsController}
133  * controls/manages all UDFPS sensors. In other words, a single controller is registered with
134  * {@link com.android.server.biometrics.sensors.fingerprint.FingerprintService}, and interfaces such
135  * as {@link FingerprintManager#onPointerDown(long, int, int, int, float, float)} or
136  * {@link IUdfpsOverlayController#showUdfpsOverlay} should all have
137  * {@code sensorId} parameters.
138  */
139 @SuppressWarnings("deprecation")
140 @SysUISingleton
141 public class UdfpsController implements DozeReceiver, Dumpable {
142     private static final String TAG = "UdfpsController";
143     private static final long AOD_SEND_FINGER_UP_DELAY_MILLIS = 1000;
144 
145     private static final long MIN_UNCHANGED_INTERACTION_LOG_INTERVAL = 50;
146 
147     private final Context mContext;
148     private final Execution mExecution;
149     private final FingerprintManager mFingerprintManager;
150     @NonNull private final LayoutInflater mInflater;
151     private final UserActivityNotifier mUserActivityNotifier;
152     private final WindowManager mWindowManager;
153     private final DelayableExecutor mFgExecutor;
154     @NonNull private final Executor mBiometricExecutor;
155     @NonNull private final StatusBarStateController mStatusBarStateController;
156     @NonNull private final KeyguardStateController mKeyguardStateController;
157     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
158     @NonNull private final DumpManager mDumpManager;
159     @NonNull private final SystemUIDialogManager mDialogManager;
160     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
161     @NonNull private final DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
162     @NonNull private final VibratorHelper mVibrator;
163     @NonNull private final FalsingManager mFalsingManager;
164     @NonNull private final PowerManager mPowerManager;
165     @NonNull private final AccessibilityManager mAccessibilityManager;
166     @NonNull private final ConfigurationController mConfigurationController;
167     @NonNull private final SystemClock mSystemClock;
168     @NonNull private final UnlockedScreenOffAnimationController
169             mUnlockedScreenOffAnimationController;
170     @NonNull private final LatencyTracker mLatencyTracker;
171     @VisibleForTesting @NonNull final BiometricDisplayListener mOrientationListener;
172     @NonNull private final ActivityTransitionAnimator mActivityTransitionAnimator;
173     @NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor;
174     @NonNull private final ShadeInteractor mShadeInteractor;
175     @Nullable private final TouchProcessor mTouchProcessor;
176     @NonNull private final SessionTracker mSessionTracker;
177     @NonNull private final Lazy<DeviceEntryUdfpsTouchOverlayViewModel>
178             mDeviceEntryUdfpsTouchOverlayViewModel;
179     @NonNull private final Lazy<DefaultUdfpsTouchOverlayViewModel>
180             mDefaultUdfpsTouchOverlayViewModel;
181     @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
182     @NonNull private final UdfpsOverlayInteractor mUdfpsOverlayInteractor;
183     @NonNull private final PowerInteractor mPowerInteractor;
184     @NonNull private final CoroutineScope mScope;
185     @NonNull private final InputManager mInputManager;
186     @NonNull private final SelectedUserInteractor mSelectedUserInteractor;
187     private final boolean mIgnoreRefreshRate;
188     private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
189 
190     // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
191     // sensors, this, in addition to a lot of the code here, will be updated.
192     @VisibleForTesting @NonNull FingerprintSensorPropertiesInternal mSensorProps;
193     @VisibleForTesting @NonNull UdfpsOverlayParams mOverlayParams = new UdfpsOverlayParams();
194     // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
195     @Nullable private Runnable mAuthControllerUpdateUdfpsLocation;
196     @Nullable private UdfpsDisplayModeProvider mUdfpsDisplayMode;
197 
198     // The ID of the pointer for which ACTION_DOWN has occurred. -1 means no pointer is active.
199     private int mActivePointerId = MotionEvent.INVALID_POINTER_ID;
200     // Whether a pointer has been pilfered for current gesture
201     private boolean mPointerPilfered = false;
202     // The timestamp of the most recent touch log.
203     private long mTouchLogTime;
204     // The timestamp of the most recent log of a touch InteractionEvent.
205     private long mLastTouchInteractionTime;
206     // Sensor has a capture (good or bad) for this touch. No need to enable the UDFPS display mode
207     // anymore for this particular touch event. In other words, do not enable the UDFPS mode until
208     // the user touches the sensor area again.
209     private boolean mAcquiredReceived;
210 
211     // The current request from FingerprintService. Null if no current request.
212     @Nullable UdfpsControllerOverlay mOverlay;
213 
214     // The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
215     // to turn off high brightness mode. To get around this limitation, the state of the AOD
216     // interrupt is being tracked and a timeout is used as a last resort to turn off high brightness
217     // mode.
218     private boolean mIsAodInterruptActive;
219     @Nullable private Runnable mCancelAodFingerUpAction;
220     private boolean mScreenOn;
221     private Runnable mAodInterruptRunnable;
222     private boolean mOnFingerDown;
223     private boolean mAttemptedToDismissKeyguard;
224     private final Set<Callback> mCallbacks = new HashSet<>();
225 
226     @VisibleForTesting
227     public static final VibrationAttributes UDFPS_VIBRATION_ATTRIBUTES =
228             new VibrationAttributes.Builder()
229                     // vibration will bypass battery saver mode:
230                     .setUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST)
231                     .build();
232     @VisibleForTesting
233     public static final VibrationAttributes LOCK_ICON_VIBRATION_ATTRIBUTES =
234             new VibrationAttributes.Builder()
235                     .setUsage(VibrationAttributes.USAGE_TOUCH)
236                     .build();
237 
238     // haptic to use for successful device entry
239     public static final VibrationEffect EFFECT_CLICK =
240             VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
241 
242     public static final int LONG_PRESS = HapticFeedbackConstants.LONG_PRESS;
243 
244     private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
245         @Override
246         public void onScreenTurnedOn() {
247             mScreenOn = true;
248             if (mAodInterruptRunnable != null) {
249                 mAodInterruptRunnable.run();
250                 mAodInterruptRunnable = null;
251             }
252         }
253 
254         @Override
255         public void onScreenTurnedOff() {
256             mScreenOn = false;
257         }
258     };
259 
260     @Override
dump(@onNull PrintWriter pw, @NonNull String[] args)261     public void dump(@NonNull PrintWriter pw, @NonNull String[] args) {
262         final int touchConfigId = mContext.getResources().getInteger(
263                 com.android.internal.R.integer.config_selected_udfps_touch_detection);
264         pw.println("mSensorProps=(" + mSensorProps + ")");
265         pw.println("touchConfigId: " + touchConfigId);
266     }
267 
268     public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
269         @Override
showUdfpsOverlay(long requestId, int sensorId, int reason, @NonNull IUdfpsOverlayControllerCallback callback)270         public void showUdfpsOverlay(long requestId, int sensorId, int reason,
271                 @NonNull IUdfpsOverlayControllerCallback callback) {
272             mUdfpsOverlayInteractor.setRequestId(requestId);
273             mFgExecutor.execute(() -> UdfpsController.this.showUdfpsOverlay(
274                     new UdfpsControllerOverlay(
275                         mContext,
276                         mInflater,
277                         mWindowManager,
278                         mAccessibilityManager,
279                         mStatusBarStateController,
280                         mKeyguardViewManager,
281                         mKeyguardUpdateMonitor,
282                         mDialogManager,
283                         mDumpManager,
284                         mConfigurationController,
285                         mKeyguardStateController,
286                         mUnlockedScreenOffAnimationController,
287                         mUdfpsDisplayMode,
288                         requestId,
289                         reason,
290                         callback,
291                         (view, event) -> onTouch(
292                             requestId,
293                             event
294                         ),
295                             mActivityTransitionAnimator,
296                         mPrimaryBouncerInteractor,
297                         mAlternateBouncerInteractor,
298                         mKeyguardTransitionInteractor,
299                         mSelectedUserInteractor,
300                         mDeviceEntryUdfpsTouchOverlayViewModel,
301                         mDefaultUdfpsTouchOverlayViewModel,
302                         mShadeInteractor,
303                         mUdfpsOverlayInteractor,
304                         mPowerInteractor,
305                         mScope
306                     )));
307         }
308 
309         @Override
hideUdfpsOverlay(int sensorId)310         public void hideUdfpsOverlay(int sensorId) {
311             mFgExecutor.execute(() -> {
312                 if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
313                     // if we get here, we expect keyguardUpdateMonitor's fingerprintRunningState
314                     // to be updated shortly afterwards
315                     Log.d(TAG, "hiding udfps overlay when "
316                             + "mKeyguardUpdateMonitor.isFingerprintDetectionRunning()=true");
317                 }
318 
319                 UdfpsController.this.hideUdfpsOverlay();
320             });
321         }
322 
323         @Override
onAcquired( int sensorId, @BiometricFingerprintConstants.FingerprintAcquired int acquiredInfo )324         public void onAcquired(
325                 int sensorId,
326                 @BiometricFingerprintConstants.FingerprintAcquired int acquiredInfo
327         ) {
328             if (isUltrasonic()) {
329                 if (acquiredInfo == FINGERPRINT_ACQUIRED_START) {
330                     mFgExecutor.execute(() -> {
331                         for (Callback cb : mCallbacks) {
332                             cb.onFingerDown();
333                         }
334                     });
335                 } else {
336                     mFgExecutor.execute(() -> {
337                         for (Callback cb : mCallbacks) {
338                             cb.onFingerUp();
339                         }
340                     });
341                 }
342             }
343 
344             if (BiometricFingerprintConstants.shouldDisableUdfpsDisplayMode(acquiredInfo)) {
345                 boolean acquiredGood = acquiredInfo == FINGERPRINT_ACQUIRED_GOOD;
346                 mFgExecutor.execute(() -> {
347                     if (mOverlay == null) {
348                         Log.e(TAG, "Null request when onAcquired for sensorId: " + sensorId
349                                 + " acquiredInfo=" + acquiredInfo);
350                         return;
351                     }
352                     mAcquiredReceived = true;
353                     final View view = mOverlay.getTouchOverlay();
354                     unconfigureDisplay(view);
355                     tryAodSendFingerUp();
356                 });
357             }
358         }
359 
360         @Override
onEnrollmentProgress(int sensorId, int remaining)361         public void onEnrollmentProgress(int sensorId, int remaining) { }
362 
363         @Override
onEnrollmentHelp(int sensorId)364         public void onEnrollmentHelp(int sensorId) { }
365 
366         @Override
setDebugMessage(int sensorId, String message)367         public void setDebugMessage(int sensorId, String message) {
368             mFgExecutor.execute(() -> {
369                 if (mOverlay == null || mOverlay.isHiding()) {
370                     return;
371                 }
372             });
373         }
374 
getSensorBounds()375         public Rect getSensorBounds() {
376             return mOverlayParams.getSensorBounds();
377         }
378 
379         /**
380          * Passes a mocked MotionEvent to OnTouch.
381          *
382          * @param event MotionEvent to simulate in onTouch
383          */
debugOnTouch(MotionEvent event)384         public void debugOnTouch(MotionEvent event) {
385             final long requestId = (mOverlay != null) ? mOverlay.getRequestId() : 0L;
386             UdfpsController.this.onTouch(requestId, event);
387         }
388 
389         /**
390          * Debug to run onUiReady
391          */
debugOnUiReady(int sensorId)392         public void debugOnUiReady(int sensorId) {
393             final long requestId = (mOverlay != null) ? mOverlay.getRequestId() : 0L;
394             UdfpsController.this.mFingerprintManager.onUdfpsUiEvent(
395                     FingerprintManager.UDFPS_UI_READY, requestId, sensorId);
396         }
397 
398         /**
399          * Debug to show biometric prompt
400          */
debugBiometricPrompt()401         public void debugBiometricPrompt() {
402             final BiometricPrompt.AuthenticationCallback authenticationCallback =
403                     new BiometricPrompt.AuthenticationCallback() {
404                     };
405 
406             final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(mContext)
407                     .setTitle("Test")
408                     .setDeviceCredentialAllowed(true)
409                     .setAllowBackgroundAuthentication(true)
410                     .build();
411             final Handler handler = new Handler(Looper.getMainLooper());
412             biometricPrompt.authenticate(
413                     new CancellationSignal(),
414                     handler::post,
415                     authenticationCallback);
416         }
417 
418         /**
419          * Debug to run setIgnoreDisplayTouches
420          */
debugSetIgnoreDisplayTouches(boolean ignoreTouch)421         public void debugSetIgnoreDisplayTouches(boolean ignoreTouch) {
422             final long requestId = (mOverlay != null) ? mOverlay.getRequestId() : 0L;
423             UdfpsController.this.mFingerprintManager.setIgnoreDisplayTouches(
424                     requestId, mSensorProps.sensorId, ignoreTouch);
425         }
426     }
427 
428     /**
429      * Updates the overlay parameters and reconstructs or redraws the overlay, if necessary.
430      *
431      * @param sensorProps   sensor for which the overlay is getting updated.
432      * @param overlayParams See {@link UdfpsOverlayParams}.
433      */
updateOverlayParams(@onNull FingerprintSensorPropertiesInternal sensorProps, @NonNull UdfpsOverlayParams overlayParams)434     public void updateOverlayParams(@NonNull FingerprintSensorPropertiesInternal sensorProps,
435             @NonNull UdfpsOverlayParams overlayParams) {
436         if (mSensorProps.sensorId != sensorProps.sensorId) {
437             mSensorProps = sensorProps;
438             Log.w(TAG, "updateUdfpsParams | sensorId has changed");
439         }
440 
441         if (!mOverlayParams.equals(overlayParams)) {
442             mOverlayParams = overlayParams;
443 
444             if (mOverlay != null && mOverlay.getRequestReason() == REASON_AUTH_KEYGUARD) {
445                 mOverlay.updateOverlayParams(mOverlayParams);
446             } else {
447                 redrawOverlay();
448             }
449         }
450     }
451 
452     // TODO(b/229290039): UDFPS controller should manage its dimensions on its own. Remove this.
setAuthControllerUpdateUdfpsLocation(@ullable Runnable r)453     public void setAuthControllerUpdateUdfpsLocation(@Nullable Runnable r) {
454         mAuthControllerUpdateUdfpsLocation = r;
455     }
456 
setUdfpsDisplayMode(@onNull UdfpsDisplayModeProvider udfpsDisplayMode)457     public void setUdfpsDisplayMode(@NonNull UdfpsDisplayModeProvider udfpsDisplayMode) {
458         mUdfpsDisplayMode = udfpsDisplayMode;
459     }
460 
461     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
462         @Override
463         public void onReceive(Context context, Intent intent) {
464             if (mOverlay != null
465                     && mOverlay.getRequestReason() != REASON_AUTH_KEYGUARD
466                     && Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
467                 String reason = intent.getStringExtra("reason");
468                 reason = (reason != null) ? reason : "unknown";
469                 Log.d(TAG, "ACTION_CLOSE_SYSTEM_DIALOGS received, reason: " + reason
470                         + ", mRequestReason: " + mOverlay.getRequestReason());
471 
472                 mOverlay.cancel();
473                 hideUdfpsOverlay();
474             }
475         }
476     };
477 
tryDismissingKeyguard()478     private void tryDismissingKeyguard() {
479         if (!mOnFingerDown) {
480             playStartHaptic();
481         }
482         mKeyguardViewManager.notifyKeyguardAuthenticated(false /* primaryAuth */);
483         mAttemptedToDismissKeyguard = true;
484     }
485 
getBiometricSessionType()486     private int getBiometricSessionType() {
487         if (mOverlay == null) {
488             return -1;
489         }
490         switch (mOverlay.getRequestReason()) {
491             case REASON_AUTH_KEYGUARD:
492                 return SESSION_KEYGUARD;
493             case REASON_AUTH_BP:
494                 return SESSION_BIOMETRIC_PROMPT;
495             case REASON_ENROLL_FIND_SENSOR:
496             case REASON_ENROLL_ENROLLING:
497                 // TODO(b/255634916): create a reason for enrollment (or an "unknown" reason).
498                 return SESSION_BIOMETRIC_PROMPT << 1;
499             default:
500                 return -1;
501         }
502     }
503 
toBiometricTouchReportedTouchType(InteractionEvent event)504     private static int toBiometricTouchReportedTouchType(InteractionEvent event) {
505         switch (event) {
506             case DOWN:
507                 return SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED__TOUCH_TYPE__TOUCH_TYPE_DOWN;
508             case UP:
509                 return SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED__TOUCH_TYPE__TOUCH_TYPE_UP;
510             case CANCEL:
511                 return SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED__TOUCH_TYPE__TOUCH_TYPE_CANCEL;
512             default:
513                 return SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED__TOUCH_TYPE__TOUCH_TYPE_UNCHANGED;
514         }
515     }
516 
logBiometricTouch(InteractionEvent event, NormalizedTouchData data)517     private void logBiometricTouch(InteractionEvent event, NormalizedTouchData data) {
518         if (event == InteractionEvent.UNCHANGED) {
519             long sinceLastLog = mSystemClock.elapsedRealtime() - mLastTouchInteractionTime;
520             if (sinceLastLog < MIN_UNCHANGED_INTERACTION_LOG_INTERVAL) {
521                 return;
522             }
523         }
524         mLastTouchInteractionTime = mSystemClock.elapsedRealtime();
525 
526         final int biometricTouchReportedTouchType = toBiometricTouchReportedTouchType(event);
527         final InstanceId sessionIdProvider = mSessionTracker.getSessionId(
528                 getBiometricSessionType());
529         final int sessionId = (sessionIdProvider != null) ? sessionIdProvider.getId() : -1;
530         final int touchConfigId = mContext.getResources().getInteger(
531                 com.android.internal.R.integer.config_selected_udfps_touch_detection);
532 
533         SysUiStatsLog.write(SysUiStatsLog.BIOMETRIC_TOUCH_REPORTED, biometricTouchReportedTouchType,
534                 touchConfigId, sessionId, data.getX(), data.getY(), data.getMinor(),
535                 data.getMajor(), data.getOrientation(), data.getTime(), data.getGestureStart(),
536                 mStatusBarStateController.isDozing());
537 
538         if (Build.isDebuggable()) {
539             Log.d(TAG, data.toPrettyString(event.toString()));
540             Log.d(TAG, "sessionId: " + sessionId
541                     + ", isAod: " + mStatusBarStateController.isDozing()
542                     + ", touchConfigId: " + touchConfigId);
543         }
544     }
545 
onTouch(long requestId, @NonNull MotionEvent event)546     private boolean onTouch(long requestId, @NonNull MotionEvent event) {
547         if (mOverlay == null) {
548             Log.w(TAG, "ignoring onTouch with null overlay");
549             return false;
550         }
551         if (!mOverlay.matchesRequestId(requestId)) {
552             Log.w(TAG, "ignoring stale touch event: " + requestId + " current: "
553                     + mOverlay.getRequestId());
554             return false;
555         }
556         if (event.getAction() == MotionEvent.ACTION_DOWN
557                 || event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
558             // Reset on ACTION_DOWN, start of new gesture
559             mPointerPilfered = false;
560             if (mActivePointerId != MotionEvent.INVALID_POINTER_ID) {
561                 Log.w(TAG, "onTouch down received without a preceding up");
562             }
563             mActivePointerId = MotionEvent.INVALID_POINTER_ID;
564 
565             // It's possible on some devices to get duplicate touches from both doze and the
566             // normal touch listener. Don't reset the down in this case to avoid duplicate downs
567             if (!mIsAodInterruptActive) {
568                 mOnFingerDown = false;
569             }
570         }
571 
572         final TouchProcessorResult result = mTouchProcessor.processTouch(event, mActivePointerId,
573                 mOverlayParams);
574         if (result instanceof TouchProcessorResult.Failure) {
575             Log.w(TAG, ((TouchProcessorResult.Failure) result).getReason());
576             return false;
577         }
578 
579         final TouchProcessorResult.ProcessedTouch processedTouch =
580                 (TouchProcessorResult.ProcessedTouch) result;
581         final NormalizedTouchData data = processedTouch.getTouchData();
582 
583         boolean shouldPilfer = false;
584         mActivePointerId = processedTouch.getPointerOnSensorId();
585         switch (processedTouch.getEvent()) {
586             case DOWN:
587                 if (shouldTryToDismissKeyguard()) {
588                     tryDismissingKeyguard();
589                 }
590                 if (!mOnFingerDown) {
591                     onFingerDown(requestId,
592                             data.getPointerId(),
593                             data.getX(),
594                             data.getY(),
595                             data.getMinor(),
596                             data.getMajor(),
597                             data.getOrientation(),
598                             data.getTime(),
599                             data.getGestureStart(),
600                             mStatusBarStateController.isDozing());
601                 }
602 
603                 // Pilfer if valid overlap, don't allow following events to reach keyguard
604                 shouldPilfer = true;
605 
606                 // Touch is a valid UDFPS touch. Inform the falsing manager so that the touch
607                 // isn't counted against the falsing algorithm as an accidental touch.
608                 // We do this on the DOWN event instead of CANCEL/UP because the CANCEL/UP events
609                 // get sent too late to this receiver (after the actual cancel/up motions occur),
610                 // and therefore wouldn't end up being used as part of the falsing algo.
611                 mFalsingManager.isFalseTouch(UDFPS_AUTHENTICATION);
612                 break;
613 
614             case UP:
615             case CANCEL:
616                 if (InteractionEvent.CANCEL.equals(processedTouch.getEvent())) {
617                     Log.w(TAG, "This is a CANCEL event that's reported as an UP event!");
618                 }
619                 mAttemptedToDismissKeyguard = false;
620                 onFingerUp(requestId,
621                         mOverlay.getTouchOverlay(),
622                         data.getPointerId(),
623                         data.getX(),
624                         data.getY(),
625                         data.getMinor(),
626                         data.getMajor(),
627                         data.getOrientation(),
628                         data.getTime(),
629                         data.getGestureStart(),
630                         mStatusBarStateController.isDozing());
631                 break;
632 
633             default:
634                 break;
635         }
636         logBiometricTouch(processedTouch.getEvent(), data);
637 
638         // Always pilfer pointers that are within sensor area or when alternate bouncer is showing
639         if (mActivePointerId != MotionEvent.INVALID_POINTER_ID) {
640             shouldPilfer = true;
641         }
642 
643         // Pilfer only once per gesture, don't pilfer for BP
644         if (shouldPilfer && !mPointerPilfered
645                 && getBiometricSessionType() != SESSION_BIOMETRIC_PROMPT) {
646             mInputManager.pilferPointers(
647                     mOverlay.getTouchOverlay().getViewRootImpl().getInputToken());
648             mPointerPilfered = true;
649         }
650 
651         return mActivePointerId != MotionEvent.INVALID_POINTER_ID;
652     }
653 
shouldTryToDismissKeyguard()654     private boolean shouldTryToDismissKeyguard() {
655         boolean onKeyguard = mKeyguardStateController.isShowing();
656         return onKeyguard
657                 && mKeyguardStateController.canDismissLockScreen()
658                 && !mAttemptedToDismissKeyguard;
659     }
660 
661     @Inject
UdfpsController(@onNull @ain Context context, @NonNull Execution execution, @NonNull @ShadeDisplayAware LayoutInflater inflater, @Nullable FingerprintManager fingerprintManager, @NonNull @Main WindowManager windowManager, @NonNull StatusBarStateController statusBarStateController, @Main DelayableExecutor fgExecutor, @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, @NonNull ScreenLifecycle screenLifecycle, @NonNull VibratorHelper vibrator, @NonNull UdfpsHapticsSimulator udfpsHapticsSimulator, @NonNull UdfpsShell udfpsShell, @NonNull KeyguardStateController keyguardStateController, @NonNull DisplayManager displayManager, @Main Handler mainHandler, @NonNull @Main ConfigurationController configurationController, @NonNull SystemClock systemClock, @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, @NonNull SystemUIDialogManager dialogManager, @NonNull LatencyTracker latencyTracker, @NonNull ActivityTransitionAnimator activityTransitionAnimator, @NonNull @BiometricsBackground Executor biometricsExecutor, @NonNull PrimaryBouncerInteractor primaryBouncerInteractor, @NonNull ShadeInteractor shadeInteractor, @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor, @NonNull SessionTracker sessionTracker, @NonNull AlternateBouncerInteractor alternateBouncerInteractor, @NonNull InputManager inputManager, @NonNull DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor, @NonNull SelectedUserInteractor selectedUserInteractor, @NonNull KeyguardTransitionInteractor keyguardTransitionInteractor, Lazy<DeviceEntryUdfpsTouchOverlayViewModel> deviceEntryUdfpsTouchOverlayViewModel, Lazy<DefaultUdfpsTouchOverlayViewModel> defaultUdfpsTouchOverlayViewModel, @NonNull UdfpsOverlayInteractor udfpsOverlayInteractor, @NonNull PowerInteractor powerInteractor, @Application CoroutineScope scope, UserActivityNotifier userActivityNotifier)662     public UdfpsController(@NonNull @Main Context context,
663             @NonNull Execution execution,
664             @NonNull @ShadeDisplayAware LayoutInflater inflater,
665             @Nullable FingerprintManager fingerprintManager,
666             @NonNull @Main WindowManager windowManager,
667             @NonNull StatusBarStateController statusBarStateController,
668             @Main DelayableExecutor fgExecutor,
669             @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
670             @NonNull DumpManager dumpManager,
671             @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor,
672             @NonNull FalsingManager falsingManager,
673             @NonNull PowerManager powerManager,
674             @NonNull AccessibilityManager accessibilityManager,
675             @NonNull ScreenLifecycle screenLifecycle,
676             @NonNull VibratorHelper vibrator,
677             @NonNull UdfpsHapticsSimulator udfpsHapticsSimulator,
678             @NonNull UdfpsShell udfpsShell,
679             @NonNull KeyguardStateController keyguardStateController,
680             @NonNull DisplayManager displayManager,
681             @Main Handler mainHandler,
682             @NonNull @Main ConfigurationController configurationController,
683             @NonNull SystemClock systemClock,
684             @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
685             @NonNull SystemUIDialogManager dialogManager,
686             @NonNull LatencyTracker latencyTracker,
687             @NonNull ActivityTransitionAnimator activityTransitionAnimator,
688             @NonNull @BiometricsBackground Executor biometricsExecutor,
689             @NonNull PrimaryBouncerInteractor primaryBouncerInteractor,
690             @NonNull ShadeInteractor shadeInteractor,
691             @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor,
692             @NonNull SessionTracker sessionTracker,
693             @NonNull AlternateBouncerInteractor alternateBouncerInteractor,
694             @NonNull InputManager inputManager,
695             @NonNull DeviceEntryFaceAuthInteractor deviceEntryFaceAuthInteractor,
696             @NonNull SelectedUserInteractor selectedUserInteractor,
697             @NonNull KeyguardTransitionInteractor keyguardTransitionInteractor,
698             Lazy<DeviceEntryUdfpsTouchOverlayViewModel> deviceEntryUdfpsTouchOverlayViewModel,
699             Lazy<DefaultUdfpsTouchOverlayViewModel> defaultUdfpsTouchOverlayViewModel,
700             @NonNull UdfpsOverlayInteractor udfpsOverlayInteractor,
701             @NonNull PowerInteractor powerInteractor,
702             @Application CoroutineScope scope,
703             UserActivityNotifier userActivityNotifier) {
704         mContext = context;
705         mExecution = execution;
706         mVibrator = vibrator;
707         mInflater = inflater;
708         mUserActivityNotifier = userActivityNotifier;
709         mIgnoreRefreshRate = mContext.getResources()
710                     .getBoolean(R.bool.config_ignoreUdfpsVote);
711         // The fingerprint manager is queried for UDFPS before this class is constructed, so the
712         // fingerprint manager should never be null.
713         mFingerprintManager = checkNotNull(fingerprintManager);
714         mWindowManager = windowManager;
715         mFgExecutor = fgExecutor;
716         mStatusBarStateController = statusBarStateController;
717         mKeyguardStateController = keyguardStateController;
718         mKeyguardViewManager = statusBarKeyguardViewManager;
719         mDumpManager = dumpManager;
720         mDialogManager = dialogManager;
721         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
722         mFalsingManager = falsingManager;
723         mPowerManager = powerManager;
724         mAccessibilityManager = accessibilityManager;
725         screenLifecycle.addObserver(mScreenObserver);
726         mScreenOn = screenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
727         mConfigurationController = configurationController;
728         mSystemClock = systemClock;
729         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
730         mLatencyTracker = latencyTracker;
731         mActivityTransitionAnimator = activityTransitionAnimator;
732         mSensorProps = new FingerprintSensorPropertiesInternal(
733                 -1 /* sensorId */,
734                 SensorProperties.STRENGTH_CONVENIENCE,
735                 0 /* maxEnrollmentsPerUser */,
736                 new ArrayList<>() /* componentInfo */,
737                 FingerprintSensorProperties.TYPE_UNKNOWN,
738                 false /* resetLockoutRequiresHardwareAuthToken */);
739 
740         mBiometricExecutor = biometricsExecutor;
741         mPrimaryBouncerInteractor = primaryBouncerInteractor;
742         mShadeInteractor = shadeInteractor;
743         mAlternateBouncerInteractor = alternateBouncerInteractor;
744         mUdfpsOverlayInteractor = udfpsOverlayInteractor;
745         mPowerInteractor = powerInteractor;
746         mScope = scope;
747         mInputManager = inputManager;
748         mSelectedUserInteractor = selectedUserInteractor;
749         mKeyguardTransitionInteractor = keyguardTransitionInteractor;
750 
751         mTouchProcessor = singlePointerTouchProcessor;
752         mSessionTracker = sessionTracker;
753         mDeviceEntryUdfpsTouchOverlayViewModel = deviceEntryUdfpsTouchOverlayViewModel;
754         mDefaultUdfpsTouchOverlayViewModel = defaultUdfpsTouchOverlayViewModel;
755 
756         mDumpManager.registerDumpable(TAG, this);
757 
758         mOrientationListener = new BiometricDisplayListener(
759                 context,
760                 displayManager,
761                 mainHandler,
762                 BiometricDisplayListener.SensorType.UnderDisplayFingerprint.INSTANCE,
763                 () -> {
764                     if (mAuthControllerUpdateUdfpsLocation != null) {
765                         mAuthControllerUpdateUdfpsLocation.run();
766                     }
767                     return Unit.INSTANCE;
768                 });
769         mDeviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor;
770 
771         final UdfpsOverlayController mUdfpsOverlayController = new UdfpsOverlayController();
772         mFingerprintManager.setUdfpsOverlayController(mUdfpsOverlayController);
773 
774         final IntentFilter filter = new IntentFilter();
775         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
776         context.registerReceiver(mBroadcastReceiver, filter,
777                 Context.RECEIVER_EXPORTED_UNAUDITED);
778 
779         udfpsHapticsSimulator.setUdfpsController(this);
780         udfpsShell.setUdfpsOverlayController(mUdfpsOverlayController);
781     }
782 
783     /**
784      * If a11y touchExplorationEnabled, play haptic to signal UDFPS scanning started.
785      */
786     @VisibleForTesting
playStartHaptic()787     public void playStartHaptic() {
788         if (mAccessibilityManager.isTouchExplorationEnabled()) {
789             if (mOverlay != null && mOverlay.getTouchOverlay() != null) {
790                 mVibrator.performHapticFeedback(
791                         mOverlay.getTouchOverlay(),
792                         HapticFeedbackConstants.CONTEXT_CLICK
793                 );
794             } else {
795                 Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
796                         + "vibration. Either the controller overlay is null or has no view");
797             }
798         }
799     }
800 
801     @Override
dozeTimeTick()802     public void dozeTimeTick() {
803 
804     }
805 
redrawOverlay()806     private void redrawOverlay() {
807         UdfpsControllerOverlay overlay = mOverlay;
808         if (overlay != null) {
809             hideUdfpsOverlay();
810             showUdfpsOverlay(overlay);
811         }
812     }
813 
showUdfpsOverlay(@onNull UdfpsControllerOverlay overlay)814     private void showUdfpsOverlay(@NonNull UdfpsControllerOverlay overlay) {
815         mExecution.assertIsMainThread();
816 
817         if (mOverlay != null) {
818             Log.d(TAG, "showUdfpsOverlay | the overlay is already showing");
819             return;
820         }
821 
822         mOverlay = overlay;
823         final int requestReason = overlay.getRequestReason();
824         if (requestReason == REASON_AUTH_KEYGUARD
825                 && !mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
826             Log.d(TAG, "Attempting to showUdfpsOverlay when fingerprint detection"
827                     + " isn't running on keyguard. Skip show.");
828             return;
829         }
830         if (overlay.show(this, mOverlayParams)) {
831             Log.d(TAG, "showUdfpsOverlay | adding window reason=" + requestReason);
832             mOnFingerDown = false;
833             mAttemptedToDismissKeyguard = false;
834             mOrientationListener.enable();
835             if (mFingerprintManager != null) {
836                 mFingerprintManager.onUdfpsUiEvent(FingerprintManager.UDFPS_UI_OVERLAY_SHOWN,
837                         overlay.getRequestId(), mSensorProps.sensorId);
838             }
839         } else {
840             Log.d(TAG, "showUdfpsOverlay | the overlay is already showing");
841         }
842     }
843 
hideUdfpsOverlay()844     private void hideUdfpsOverlay() {
845         mExecution.assertIsMainThread();
846 
847         if (mOverlay != null) {
848             // Reset the controller back to its starting state.
849             final View oldView = mOverlay.getTouchOverlay();
850             if (oldView != null) {
851                 onFingerUp(mOverlay.getRequestId(), oldView);
852             }
853             final boolean removed = mOverlay.hide();
854             mKeyguardViewManager.hideAlternateBouncer(true);
855             Log.v(TAG, "hideUdfpsOverlay | removing window: " + removed);
856         } else {
857             Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden");
858         }
859 
860         mOverlay = null;
861         mOrientationListener.disable();
862     }
863 
unconfigureDisplay(View view)864     private void unconfigureDisplay(View view) {
865         if (!isOptical()) {
866             return;
867         }
868         if (mUdfpsDisplayMode != null) {
869             mUdfpsDisplayMode.disable(null);
870         }
871     }
872 
873     /**
874      * Request fingerprint scan.
875      *
876      * This is intended to be called in response to a sensor that triggers an AOD interrupt for the
877      * fingerprint sensor.
878      */
onAodInterrupt(int screenX, int screenY, float major, float minor)879     void onAodInterrupt(int screenX, int screenY, float major, float minor) {
880         if (mIsAodInterruptActive) {
881             return;
882         }
883 
884         if (!mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
885             if (mFalsingManager.isFalseLongTap(FalsingManager.LOW_PENALTY)) {
886                 Log.v(TAG, "aod lock icon long-press rejected by the falsing manager.");
887                 return;
888             }
889             mKeyguardViewManager.showPrimaryBouncer(true, "UdfpsController#onAodInterrupt");
890 
891             // play the same haptic as the DeviceEntryIcon longpress
892             if (mOverlay != null && mOverlay.getTouchOverlay() != null) {
893                 mVibrator.performHapticFeedback(
894                         mOverlay.getTouchOverlay(),
895                         UdfpsController.LONG_PRESS
896                 );
897             } else {
898                 Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
899                         + "vibration. Either the controller overlay is null or has no view");
900             }
901             return;
902         }
903 
904         // TODO(b/225068271): this may not be correct but there isn't a way to track it
905         final long requestId = mOverlay != null ? mOverlay.getRequestId() : -1;
906         mAodInterruptRunnable = () -> {
907             mIsAodInterruptActive = true;
908             // Since the sensor that triggers the AOD interrupt doesn't provide
909             // ACTION_UP/ACTION_CANCEL,  we need to be careful about not letting the screen
910             // accidentally remain in high brightness mode. As a mitigation, queue a call to
911             // cancel the fingerprint scan.
912             mCancelAodFingerUpAction = mFgExecutor.executeDelayed(this::tryAodSendFingerUp,
913                     AOD_SEND_FINGER_UP_DELAY_MILLIS);
914             // using a hard-coded value for orientation, time and gestureStart until they are
915             // available from the sensor.
916             onFingerDown(
917                     requestId,
918                     MotionEvent.INVALID_POINTER_ID /* pointerId */,
919                     screenX,
920                     screenY,
921                     minor,
922                     major,
923                     0f /* orientation */,
924                     0L /* time */,
925                     0L /* gestureStart */,
926                     true /* isAod */);
927         };
928 
929         if (isScreenOffUnlockEnabled() || mScreenOn) {
930             mAodInterruptRunnable.run();
931             mAodInterruptRunnable = null;
932         }
933     }
934 
isScreenOffUnlockEnabled()935     private boolean isScreenOffUnlockEnabled() {
936         return mContext.getResources().getBoolean(R.bool.config_screen_off_udfps_enabled)
937                 && Settings.Secure.getIntForUser(
938                         mContext.getContentResolver(),
939                         Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
940                         0,
941                         mContext.getUserId()) != 0;
942     }
943 
944     /**
945      * Add a callback for fingerUp and fingerDown events
946      */
addCallback(Callback cb)947     public void addCallback(Callback cb) {
948         mCallbacks.add(cb);
949     }
950 
951     /**
952      * Remove callback
953      */
removeCallback(Callback cb)954     public void removeCallback(Callback cb) {
955         mCallbacks.remove(cb);
956     }
957 
958     /**
959      * The sensor that triggers {@link #onAodInterrupt} doesn't emit ACTION_UP or ACTION_CANCEL
960      * events, which means the fingerprint gesture created by the AOD interrupt needs to be
961      * cancelled manually.
962      * This should be called when authentication either succeeds or fails. Failing to cancel the
963      * scan will leave the display in the UDFPS mode until the user lifts their finger. On optical
964      * sensors, this can result in illumination persisting for longer than necessary.
965      */
966     @VisibleForTesting
tryAodSendFingerUp()967     void tryAodSendFingerUp() {
968         if (!mIsAodInterruptActive) {
969             return;
970         }
971         cancelAodSendFingerUpAction();
972         if (mOverlay != null && mOverlay.getTouchOverlay() != null) {
973             onFingerUp(mOverlay.getRequestId(), mOverlay.getTouchOverlay());
974         }
975     }
976 
977     /**
978      * Cancels any scheduled AoD finger-up actions without triggered the finger-up action. Only
979      * call this method if the finger-up event has been guaranteed to have already occurred.
980      */
981     @VisibleForTesting
cancelAodSendFingerUpAction()982     void cancelAodSendFingerUpAction() {
983         mIsAodInterruptActive = false;
984         if (mCancelAodFingerUpAction != null) {
985             mCancelAodFingerUpAction.run();
986             mCancelAodFingerUpAction = null;
987         }
988     }
989 
isOptical()990     private boolean isOptical() {
991         return mSensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
992     }
993 
isUltrasonic()994     private boolean isUltrasonic() {
995         return mSensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
996     }
997 
isFingerDown()998     public boolean isFingerDown() {
999         return mOnFingerDown;
1000     }
1001 
dispatchOnUiReady(long requestId)1002     private void dispatchOnUiReady(long requestId) {
1003         mFingerprintManager.onUdfpsUiEvent(FingerprintManager.UDFPS_UI_READY, requestId,
1004                 mSensorProps.sensorId);
1005         mLatencyTracker.onActionEnd(LatencyTracker.ACTION_UDFPS_ILLUMINATE);
1006     }
1007 
onFingerDown( long requestId, int x, int y, float minor, float major)1008     private void onFingerDown(
1009             long requestId,
1010             int x,
1011             int y,
1012             float minor,
1013             float major) {
1014         onFingerDown(
1015                 requestId,
1016                 MotionEvent.INVALID_POINTER_ID /* pointerId */,
1017                 x,
1018                 y,
1019                 minor,
1020                 major,
1021                 0f /* orientation */,
1022                 0L /* time */,
1023                 0L /* gestureStart */,
1024                 false /* isAod */);
1025     }
1026 
onFingerDown( long requestId, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)1027     private void onFingerDown(
1028             long requestId,
1029             int pointerId,
1030             float x,
1031             float y,
1032             float minor,
1033             float major,
1034             float orientation,
1035             long time,
1036             long gestureStart,
1037             boolean isAod) {
1038         mExecution.assertIsMainThread();
1039 
1040         if (mOverlay == null) {
1041             Log.w(TAG, "Null request in onFingerDown");
1042             return;
1043         }
1044         if (!mOverlay.matchesRequestId(requestId)) {
1045             Log.w(TAG, "Mismatched fingerDown: " + requestId
1046                     + " current: " + mOverlay.getRequestId());
1047             return;
1048         }
1049         if (isOptical()) {
1050             mLatencyTracker.onActionStart(ACTION_UDFPS_ILLUMINATE);
1051         }
1052         // Refresh screen timeout and boost process priority if possible.
1053         if (Flags.bouncerUiRevamp()) {
1054             mUserActivityNotifier.notifyUserActivity(mSystemClock.uptimeMillis(),
1055                     PowerManager.USER_ACTIVITY_EVENT_TOUCH);
1056         } else {
1057             mPowerManager.userActivity(mSystemClock.uptimeMillis(),
1058                     PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
1059         }
1060 
1061         if (!mOnFingerDown) {
1062             playStartHaptic();
1063 
1064             mDeviceEntryFaceAuthInteractor.onUdfpsSensorTouched();
1065         }
1066         mOnFingerDown = true;
1067         mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, pointerId, x, y,
1068                 minor, major, orientation, time, gestureStart, isAod);
1069         Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0);
1070 
1071         final View view = mOverlay.getTouchOverlay();
1072         if (view != null && isOptical()) {
1073             if (mIgnoreRefreshRate) {
1074                 dispatchOnUiReady(requestId);
1075             } else {
1076                     mUdfpsDisplayMode.enable(() -> dispatchOnUiReady(requestId));
1077             }
1078         }
1079 
1080         if (isOptical()) {
1081             for (Callback cb : mCallbacks) {
1082                 cb.onFingerDown();
1083             }
1084         }
1085     }
1086 
onFingerUp(long requestId, @NonNull View view)1087     private void onFingerUp(long requestId, @NonNull View view) {
1088         onFingerUp(
1089                 requestId,
1090                 view,
1091                 MotionEvent.INVALID_POINTER_ID /* pointerId */,
1092                 0f /* x */,
1093                 0f /* y */,
1094                 0f /* minor */,
1095                 0f /* major */,
1096                 0f /* orientation */,
1097                 0L /* time */,
1098                 0L /* gestureStart */,
1099                 false /* isAod */);
1100     }
1101 
onFingerUp( long requestId, View view, int pointerId, float x, float y, float minor, float major, float orientation, long time, long gestureStart, boolean isAod)1102     private void onFingerUp(
1103             long requestId,
1104             View view,
1105             int pointerId,
1106             float x,
1107             float y,
1108             float minor,
1109             float major,
1110             float orientation,
1111             long time,
1112             long gestureStart,
1113             boolean isAod) {
1114         mExecution.assertIsMainThread();
1115         mActivePointerId = MotionEvent.INVALID_POINTER_ID;
1116         mAcquiredReceived = false;
1117         if (mOnFingerDown) {
1118             mFingerprintManager.onPointerUp(requestId, mSensorProps.sensorId, pointerId, x,
1119                     y, minor, major, orientation, time, gestureStart, isAod);
1120             if (isOptical()) {
1121                 for (Callback cb : mCallbacks) {
1122                     cb.onFingerUp();
1123                 }
1124             }
1125         }
1126         mOnFingerDown = false;
1127         unconfigureDisplay(view);
1128         cancelAodSendFingerUpAction();
1129     }
1130 
1131     /**
1132      * Callback for fingerUp and fingerDown events.
1133      */
1134     public interface Callback {
1135         /**
1136          * Called onFingerUp events. Will only be called if the finger was previously down.
1137          */
onFingerUp()1138         void onFingerUp();
1139 
1140         /**
1141          * Called onFingerDown events.
1142          */
onFingerDown()1143         void onFingerDown();
1144     }
1145 }
1146