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