Loading packages/SystemUI/res/layout/udfps_touch_overlay.xml 0 → 100644 +22 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2023 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/udfps_touch_overlay" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/accessibility_fingerprint_label"> </com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay> packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +56 −36 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; Loading @@ -78,9 +79,9 @@ import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; Loading Loading @@ -150,7 +151,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor; @NonNull private final Provider<UdfpsKeyguardViewModels> mUdfpsKeyguardViewModels; @NonNull private final VibratorHelper mVibrator; @NonNull private final FeatureFlags mFeatureFlags; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @NonNull private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -281,7 +281,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { fromUdfpsView ), mActivityLaunchAnimator, mFeatureFlags, mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsKeyguardAccessibilityDelegate, Loading Loading @@ -318,10 +317,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { return; } mAcquiredReceived = true; final UdfpsView view = mOverlay.getOverlayView(); if (view != null && isOptical()) { final View view = mOverlay.getTouchOverlay(); unconfigureDisplay(view); } tryAodSendFingerUp(); }); } Loading @@ -339,7 +336,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (mOverlay == null || mOverlay.isHiding()) { return; } mOverlay.getOverlayView().setDebugMessage(message); if (!DeviceEntryUdfpsRefactor.isEnabled()) { ((UdfpsView) mOverlay.getTouchOverlay()).setDebugMessage(message); } }); } Loading Loading @@ -506,6 +505,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if ((mLockscreenShadeTransitionController.getQSDragProgress() != 0f && !mAlternateBouncerInteractor.isVisibleState()) || mPrimaryBouncerInteractor.isInTransit()) { Log.w(TAG, "ignoring touch due to qsDragProcess or primaryBouncerInteractor"); return false; } if (event.getAction() == MotionEvent.ACTION_DOWN Loading Loading @@ -563,7 +563,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } mAttemptedToDismissKeyguard = false; onFingerUp(requestId, mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), data.getPointerId(), data.getX(), data.getY(), Loading Loading @@ -597,7 +597,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (shouldPilfer && !mPointerPilfered && getBiometricSessionType() != SESSION_BIOMETRIC_PROMPT) { mInputManager.pilferPointers( mOverlay.getOverlayView().getViewRootImpl().getInputToken()); mOverlay.getTouchOverlay().getViewRootImpl().getInputToken()); mPointerPilfered = true; } Loading @@ -605,9 +605,15 @@ public class UdfpsController implements DozeReceiver, Dumpable { } private boolean shouldTryToDismissKeyguard() { return mOverlay != null boolean onKeyguard = false; if (DeviceEntryUdfpsRefactor.isEnabled()) { onKeyguard = mKeyguardStateController.isShowing(); } else { onKeyguard = mOverlay != null && mOverlay.getAnimationViewController() instanceof UdfpsKeyguardViewControllerAdapter instanceof UdfpsKeyguardViewControllerAdapter; } return onKeyguard && mKeyguardStateController.canDismissLockScreen() && !mAttemptedToDismissKeyguard; } Loading @@ -623,7 +629,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull FeatureFlags featureFlags, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, Loading Loading @@ -670,7 +675,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { mDumpManager = dumpManager; mDialogManager = dialogManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mFeatureFlags = featureFlags; mFalsingManager = falsingManager; mPowerManager = powerManager; mAccessibilityManager = accessibilityManager; Loading Loading @@ -737,9 +741,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { @VisibleForTesting public void playStartHaptic() { if (mAccessibilityManager.isTouchExplorationEnabled()) { if (mOverlay != null && mOverlay.getOverlayView() != null) { if (mOverlay != null && mOverlay.getTouchOverlay() != null) { mVibrator.performHapticFeedback( mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), HapticFeedbackConstants.CONTEXT_CLICK ); } else { Loading @@ -751,10 +755,11 @@ public class UdfpsController implements DozeReceiver, Dumpable { @Override public void dozeTimeTick() { if (mOverlay != null) { final UdfpsView view = mOverlay.getOverlayView(); if (mOverlay != null && mOverlay.getTouchOverlay() instanceof UdfpsView) { DeviceEntryUdfpsRefactor.assertInLegacyMode(); final View view = mOverlay.getTouchOverlay(); if (view != null) { view.dozeTimeTick(); ((UdfpsView) view).dozeTimeTick(); } } } Loading Loading @@ -797,7 +802,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (mOverlay != null) { // Reset the controller back to its starting state. final UdfpsView oldView = mOverlay.getOverlayView(); final View oldView = mOverlay.getTouchOverlay(); if (oldView != null) { onFingerUp(mOverlay.getRequestId(), oldView); } Loading @@ -813,9 +818,21 @@ public class UdfpsController implements DozeReceiver, Dumpable { } private void unconfigureDisplay(@NonNull UdfpsView view) { if (view.isDisplayConfigured()) { view.unconfigureDisplay(); private void unconfigureDisplay(View view) { if (!isOptical()) { return; } if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mUdfpsDisplayMode != null) { mUdfpsDisplayMode.disable(null); // beverlt } } else { if (view != null) { UdfpsView udfpsView = (UdfpsView) view; if (udfpsView.isDisplayConfigured()) { udfpsView.unconfigureDisplay(); } } } } Loading @@ -837,10 +854,10 @@ public class UdfpsController implements DozeReceiver, Dumpable { } mKeyguardViewManager.showPrimaryBouncer(true); // play the same haptic as the LockIconViewController longpress if (mOverlay != null && mOverlay.getOverlayView() != null) { // play the same haptic as the DeviceEntryIcon longpress if (mOverlay != null && mOverlay.getTouchOverlay() != null) { mVibrator.performHapticFeedback( mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), UdfpsController.LONG_PRESS ); } else { Loading Loading @@ -909,8 +926,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { return; } cancelAodSendFingerUpAction(); if (mOverlay != null && mOverlay.getOverlayView() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); if (mOverlay != null && mOverlay.getTouchOverlay() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getTouchOverlay()); } } Loading Loading @@ -1004,12 +1021,17 @@ public class UdfpsController implements DozeReceiver, Dumpable { mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, pointerId, x, y, minor, major, orientation, time, gestureStart, isAod); Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); final UdfpsView view = mOverlay.getOverlayView(); final View view = mOverlay.getTouchOverlay(); if (view != null && isOptical()) { if (mIgnoreRefreshRate) { dispatchOnUiReady(requestId); } else { view.configureDisplay(() -> dispatchOnUiReady(requestId)); if (DeviceEntryUdfpsRefactor.isEnabled()) { mUdfpsDisplayMode.enable(() -> dispatchOnUiReady(requestId)); } else { ((UdfpsView) view).configureDisplay(() -> dispatchOnUiReady(requestId)); } } } Loading @@ -1018,7 +1040,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } private void onFingerUp(long requestId, @NonNull UdfpsView view) { private void onFingerUp(long requestId, @NonNull View view) { onFingerUp( requestId, view, Loading @@ -1035,7 +1057,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { private void onFingerUp( long requestId, @NonNull UdfpsView view, View view, int pointerId, float x, float y, Loading @@ -1056,9 +1078,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } mOnFingerDown = false; if (isOptical()) { unconfigureDisplay(view); } cancelAodSendFingerUpAction(); } Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +98 −62 Original line number Diff line number Diff line Loading @@ -46,11 +46,11 @@ import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.ui.adapter.UdfpsKeyguardViewControllerAdapter import com.android.systemui.plugins.statusbar.StatusBarStateController Loading Loading @@ -96,7 +96,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( private val controllerCallback: IUdfpsOverlayControllerCallback, private val onTouch: (View, MotionEvent, Boolean) -> Boolean, private val activityLaunchAnimator: ActivityLaunchAnimator, private val featureFlags: FeatureFlags, private val primaryBouncerInteractor: PrimaryBouncerInteractor, private val alternateBouncerInteractor: AlternateBouncerInteractor, private val isDebuggable: Boolean = Build.IS_DEBUGGABLE, Loading @@ -104,9 +103,22 @@ class UdfpsControllerOverlay @JvmOverloads constructor( private val transitionInteractor: KeyguardTransitionInteractor, private val selectedUserInteractor: SelectedUserInteractor, ) { /** The view, when [isShowing], or null. */ var overlayView: UdfpsView? = null private var overlayViewLegacy: UdfpsView? = null private set private var overlayTouchView: UdfpsTouchOverlay? = null /** * Get the current UDFPS overlay touch view which is a different View depending on whether * the DeviceEntryUdfpsRefactor flag is enabled or not. * @return The view, when [isShowing], else null */ fun getTouchOverlay(): View? { return if (DeviceEntryUdfpsRefactor.isEnabled) { overlayTouchView } else { overlayViewLegacy } } private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams() private var sensorBounds: Rect = Rect() Loading @@ -132,15 +144,15 @@ class UdfpsControllerOverlay @JvmOverloads constructor( /** If the overlay is currently showing. */ val isShowing: Boolean get() = overlayView != null get() = getTouchOverlay() != null /** Opposite of [isShowing]. */ val isHiding: Boolean get() = overlayView == null get() = getTouchOverlay() == null /** The animation controller if the overlay [isShowing]. */ val animationViewController: UdfpsAnimationViewController<*>? get() = overlayView?.animationViewController get() = overlayViewLegacy?.animationViewController private var touchExplorationEnabled = false Loading @@ -158,11 +170,28 @@ class UdfpsControllerOverlay @JvmOverloads constructor( /** Show the overlay or return false and do nothing if it is already showing. */ @SuppressLint("ClickableViewAccessibility") fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean { if (overlayView == null) { if (getTouchOverlay() == null) { overlayParams = params sensorBounds = Rect(params.sensorBounds) try { overlayView = (inflater.inflate( if (DeviceEntryUdfpsRefactor.isEnabled) { overlayTouchView = (inflater.inflate( R.layout.udfps_touch_overlay, null, false ) as UdfpsTouchOverlay).apply { // This view overlaps the sensor area // prevent it from being selectable during a11y if (requestReason.isImportantForAccessibility()) { importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO } windowManager.addView(this, coreLayoutParams.updateDimensions(null)) } // TODO (b/305234447): Bind view model to UdfpsTouchOverlay here to control // the visibility (sometimes, even if UDFPS is running, the UDFPS UI can be // obscured and we don't want to accept touches. ie: for enrollment don't accept // touches when the shade is expanded and for keyguard: don't accept touches // depending on the keyguard & shade state } else { overlayViewLegacy = (inflater.inflate( R.layout.udfps_view, null, false ) as UdfpsView).apply { overlayParams = params Loading @@ -180,6 +209,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor( windowManager.addView(this, coreLayoutParams.updateDimensions(animation)) sensorRect = sensorBounds } } getTouchOverlay()?.apply { touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled overlayTouchListener = TouchExplorationStateChangeListener { if (accessibilityManager.isTouchExplorationEnabled) { Loading Loading @@ -211,6 +243,8 @@ class UdfpsControllerOverlay @JvmOverloads constructor( view: UdfpsView, controller: UdfpsController ): UdfpsAnimationViewController<*>? { DeviceEntryUdfpsRefactor.assertInLegacyMode() val isEnrollment = when (requestReason) { REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING -> true else -> false Loading @@ -237,17 +271,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( ) } REASON_AUTH_KEYGUARD -> { if (DeviceEntryUdfpsRefactor.isEnabled) { // note: empty controller, currently shows no visual affordance // instead SysUI will show the fingerprint icon in its DeviceEntryIconView UdfpsBpViewController( view.addUdfpsView(R.layout.udfps_bp_view), statusBarStateController, primaryBouncerInteractor, dialogManager, dumpManager ) } else { UdfpsKeyguardViewControllerLegacy( view.addUdfpsView(R.layout.udfps_keyguard_view_legacy) { updateSensorLocation(sensorBounds) Loading @@ -270,7 +293,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( transitionInteractor, ) } } REASON_AUTH_BP -> { // note: empty controller, currently shows no visual affordance UdfpsBpViewController( Loading Loading @@ -302,19 +324,26 @@ class UdfpsControllerOverlay @JvmOverloads constructor( fun hide(): Boolean { val wasShowing = isShowing overlayView?.apply { overlayViewLegacy?.apply { if (isDisplayConfigured) { unconfigureDisplay() } animationViewController = null } if (DeviceEntryUdfpsRefactor.isEnabled) { udfpsDisplayModeProvider.disable(null) } getTouchOverlay()?.apply { windowManager.removeView(this) setOnTouchListener(null) setOnHoverListener(null) animationViewController = null overlayTouchListener?.let { accessibilityManager.removeTouchExplorationStateChangeListener(it) } } overlayView = null overlayViewLegacy = null overlayTouchView = null overlayTouchListener = null return wasShowing Loading Loading @@ -392,7 +421,14 @@ class UdfpsControllerOverlay @JvmOverloads constructor( } private fun shouldRotate(animation: UdfpsAnimationViewController<*>?): Boolean { if (animation !is UdfpsKeyguardViewControllerAdapter) { val keyguardNotShowing = if (DeviceEntryUdfpsRefactor.isEnabled) { !keyguardStateController.isShowing } else { animation !is UdfpsKeyguardViewControllerAdapter } if (keyguardNotShowing) { // always rotate view if we're not on the keyguard return true } Loading packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt 0 → 100644 +26 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.biometrics.ui.view import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout /** * A translucent (not visible to the user) view that receives touches to send to FingerprintManager * for fingerprint authentication. */ class UdfpsTouchOverlay(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs) packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +59 −55 Original line number Diff line number Diff line Loading @@ -36,13 +36,13 @@ import android.view.accessibility.AccessibilityManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.res.R Loading Loading @@ -107,7 +107,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Mock private lateinit var udfpsView: UdfpsView @Mock private lateinit var mUdfpsKeyguardViewLegacy: UdfpsKeyguardViewLegacy @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator @Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor Loading Loading @@ -135,8 +134,14 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun withReason( @ShowReason reason: Int, isDebuggable: Boolean = false, block: () -> Unit enableDeviceEntryUdfpsRefactor: Boolean = false, block: () -> Unit, ) { if (enableDeviceEntryUdfpsRefactor) { mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) } else { mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) } controllerOverlay = UdfpsControllerOverlay( context, inflater, Loading @@ -157,7 +162,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { controllerCallback, onTouch, activityLaunchAnimator, featureFlags, primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, Loading Loading @@ -200,7 +204,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -218,7 +222,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -236,7 +240,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -254,7 +258,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -270,7 +274,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun showUdfpsOverlay() { val didShow = controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView(eq(controllerOverlay.overlayView), any()) verify(windowManager).addView(eq(controllerOverlay.getTouchOverlay()), any()) verify(udfpsView).setUdfpsDisplayModeProvider(eq(udfpsDisplayMode)) verify(udfpsView).animationViewController = any() verify(udfpsView).addView(any()) Loading @@ -278,7 +282,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { assertThat(didShow).isTrue() assertThat(controllerOverlay.isShowing).isTrue() assertThat(controllerOverlay.isHiding).isFalse() assertThat(controllerOverlay.overlayView).isNotNull() assertThat(controllerOverlay.getTouchOverlay()).isNotNull() } @Test Loading @@ -295,14 +299,14 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun hideUdfpsOverlay() { val didShow = controllerOverlay.show(udfpsController, overlayParams) val view = controllerOverlay.overlayView val view = controllerOverlay.getTouchOverlay() val didHide = controllerOverlay.hide() verify(windowManager).removeView(eq(view)) assertThat(didShow).isTrue() assertThat(didHide).isTrue() assertThat(controllerOverlay.overlayView).isNull() assertThat(controllerOverlay.getTouchOverlay()).isNull() assertThat(controllerOverlay.animationViewController).isNull() assertThat(controllerOverlay.isShowing).isFalse() assertThat(controllerOverlay.isHiding).isTrue() Loading Loading @@ -348,7 +352,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading Loading
packages/SystemUI/res/layout/udfps_touch_overlay.xml 0 → 100644 +22 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2023 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/udfps_touch_overlay" android:layout_width="match_parent" android:layout_height="match_parent" android:contentDescription="@string/accessibility_fingerprint_label"> </com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay>
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +56 −36 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.util.Log; import android.view.HapticFeedbackConstants; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowManager; import android.view.accessibility.AccessibilityManager; Loading @@ -78,9 +79,9 @@ import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor; import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor; Loading Loading @@ -150,7 +151,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull private final KeyguardFaceAuthInteractor mKeyguardFaceAuthInteractor; @NonNull private final Provider<UdfpsKeyguardViewModels> mUdfpsKeyguardViewModels; @NonNull private final VibratorHelper mVibrator; @NonNull private final FeatureFlags mFeatureFlags; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @NonNull private final AccessibilityManager mAccessibilityManager; Loading Loading @@ -281,7 +281,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { fromUdfpsView ), mActivityLaunchAnimator, mFeatureFlags, mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsKeyguardAccessibilityDelegate, Loading Loading @@ -318,10 +317,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { return; } mAcquiredReceived = true; final UdfpsView view = mOverlay.getOverlayView(); if (view != null && isOptical()) { final View view = mOverlay.getTouchOverlay(); unconfigureDisplay(view); } tryAodSendFingerUp(); }); } Loading @@ -339,7 +336,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (mOverlay == null || mOverlay.isHiding()) { return; } mOverlay.getOverlayView().setDebugMessage(message); if (!DeviceEntryUdfpsRefactor.isEnabled()) { ((UdfpsView) mOverlay.getTouchOverlay()).setDebugMessage(message); } }); } Loading Loading @@ -506,6 +505,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if ((mLockscreenShadeTransitionController.getQSDragProgress() != 0f && !mAlternateBouncerInteractor.isVisibleState()) || mPrimaryBouncerInteractor.isInTransit()) { Log.w(TAG, "ignoring touch due to qsDragProcess or primaryBouncerInteractor"); return false; } if (event.getAction() == MotionEvent.ACTION_DOWN Loading Loading @@ -563,7 +563,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } mAttemptedToDismissKeyguard = false; onFingerUp(requestId, mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), data.getPointerId(), data.getX(), data.getY(), Loading Loading @@ -597,7 +597,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (shouldPilfer && !mPointerPilfered && getBiometricSessionType() != SESSION_BIOMETRIC_PROMPT) { mInputManager.pilferPointers( mOverlay.getOverlayView().getViewRootImpl().getInputToken()); mOverlay.getTouchOverlay().getViewRootImpl().getInputToken()); mPointerPilfered = true; } Loading @@ -605,9 +605,15 @@ public class UdfpsController implements DozeReceiver, Dumpable { } private boolean shouldTryToDismissKeyguard() { return mOverlay != null boolean onKeyguard = false; if (DeviceEntryUdfpsRefactor.isEnabled()) { onKeyguard = mKeyguardStateController.isShowing(); } else { onKeyguard = mOverlay != null && mOverlay.getAnimationViewController() instanceof UdfpsKeyguardViewControllerAdapter instanceof UdfpsKeyguardViewControllerAdapter; } return onKeyguard && mKeyguardStateController.canDismissLockScreen() && !mAttemptedToDismissKeyguard; } Loading @@ -623,7 +629,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager, @NonNull DumpManager dumpManager, @NonNull KeyguardUpdateMonitor keyguardUpdateMonitor, @NonNull FeatureFlags featureFlags, @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, Loading Loading @@ -670,7 +675,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { mDumpManager = dumpManager; mDialogManager = dialogManager; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mFeatureFlags = featureFlags; mFalsingManager = falsingManager; mPowerManager = powerManager; mAccessibilityManager = accessibilityManager; Loading Loading @@ -737,9 +741,9 @@ public class UdfpsController implements DozeReceiver, Dumpable { @VisibleForTesting public void playStartHaptic() { if (mAccessibilityManager.isTouchExplorationEnabled()) { if (mOverlay != null && mOverlay.getOverlayView() != null) { if (mOverlay != null && mOverlay.getTouchOverlay() != null) { mVibrator.performHapticFeedback( mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), HapticFeedbackConstants.CONTEXT_CLICK ); } else { Loading @@ -751,10 +755,11 @@ public class UdfpsController implements DozeReceiver, Dumpable { @Override public void dozeTimeTick() { if (mOverlay != null) { final UdfpsView view = mOverlay.getOverlayView(); if (mOverlay != null && mOverlay.getTouchOverlay() instanceof UdfpsView) { DeviceEntryUdfpsRefactor.assertInLegacyMode(); final View view = mOverlay.getTouchOverlay(); if (view != null) { view.dozeTimeTick(); ((UdfpsView) view).dozeTimeTick(); } } } Loading Loading @@ -797,7 +802,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (mOverlay != null) { // Reset the controller back to its starting state. final UdfpsView oldView = mOverlay.getOverlayView(); final View oldView = mOverlay.getTouchOverlay(); if (oldView != null) { onFingerUp(mOverlay.getRequestId(), oldView); } Loading @@ -813,9 +818,21 @@ public class UdfpsController implements DozeReceiver, Dumpable { } private void unconfigureDisplay(@NonNull UdfpsView view) { if (view.isDisplayConfigured()) { view.unconfigureDisplay(); private void unconfigureDisplay(View view) { if (!isOptical()) { return; } if (DeviceEntryUdfpsRefactor.isEnabled()) { if (mUdfpsDisplayMode != null) { mUdfpsDisplayMode.disable(null); // beverlt } } else { if (view != null) { UdfpsView udfpsView = (UdfpsView) view; if (udfpsView.isDisplayConfigured()) { udfpsView.unconfigureDisplay(); } } } } Loading @@ -837,10 +854,10 @@ public class UdfpsController implements DozeReceiver, Dumpable { } mKeyguardViewManager.showPrimaryBouncer(true); // play the same haptic as the LockIconViewController longpress if (mOverlay != null && mOverlay.getOverlayView() != null) { // play the same haptic as the DeviceEntryIcon longpress if (mOverlay != null && mOverlay.getTouchOverlay() != null) { mVibrator.performHapticFeedback( mOverlay.getOverlayView(), mOverlay.getTouchOverlay(), UdfpsController.LONG_PRESS ); } else { Loading Loading @@ -909,8 +926,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { return; } cancelAodSendFingerUpAction(); if (mOverlay != null && mOverlay.getOverlayView() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getOverlayView()); if (mOverlay != null && mOverlay.getTouchOverlay() != null) { onFingerUp(mOverlay.getRequestId(), mOverlay.getTouchOverlay()); } } Loading Loading @@ -1004,12 +1021,17 @@ public class UdfpsController implements DozeReceiver, Dumpable { mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, pointerId, x, y, minor, major, orientation, time, gestureStart, isAod); Trace.endAsyncSection("UdfpsController.e2e.onPointerDown", 0); final UdfpsView view = mOverlay.getOverlayView(); final View view = mOverlay.getTouchOverlay(); if (view != null && isOptical()) { if (mIgnoreRefreshRate) { dispatchOnUiReady(requestId); } else { view.configureDisplay(() -> dispatchOnUiReady(requestId)); if (DeviceEntryUdfpsRefactor.isEnabled()) { mUdfpsDisplayMode.enable(() -> dispatchOnUiReady(requestId)); } else { ((UdfpsView) view).configureDisplay(() -> dispatchOnUiReady(requestId)); } } } Loading @@ -1018,7 +1040,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } private void onFingerUp(long requestId, @NonNull UdfpsView view) { private void onFingerUp(long requestId, @NonNull View view) { onFingerUp( requestId, view, Loading @@ -1035,7 +1057,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { private void onFingerUp( long requestId, @NonNull UdfpsView view, View view, int pointerId, float x, float y, Loading @@ -1056,9 +1078,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { } } mOnFingerDown = false; if (isOptical()) { unconfigureDisplay(view); } cancelAodSendFingerUpAction(); } Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsControllerOverlay.kt +98 −62 Original line number Diff line number Diff line Loading @@ -46,11 +46,11 @@ import androidx.annotation.VisibleForTesting import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.biometrics.ui.view.UdfpsTouchOverlay import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.ui.adapter.UdfpsKeyguardViewControllerAdapter import com.android.systemui.plugins.statusbar.StatusBarStateController Loading Loading @@ -96,7 +96,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( private val controllerCallback: IUdfpsOverlayControllerCallback, private val onTouch: (View, MotionEvent, Boolean) -> Boolean, private val activityLaunchAnimator: ActivityLaunchAnimator, private val featureFlags: FeatureFlags, private val primaryBouncerInteractor: PrimaryBouncerInteractor, private val alternateBouncerInteractor: AlternateBouncerInteractor, private val isDebuggable: Boolean = Build.IS_DEBUGGABLE, Loading @@ -104,9 +103,22 @@ class UdfpsControllerOverlay @JvmOverloads constructor( private val transitionInteractor: KeyguardTransitionInteractor, private val selectedUserInteractor: SelectedUserInteractor, ) { /** The view, when [isShowing], or null. */ var overlayView: UdfpsView? = null private var overlayViewLegacy: UdfpsView? = null private set private var overlayTouchView: UdfpsTouchOverlay? = null /** * Get the current UDFPS overlay touch view which is a different View depending on whether * the DeviceEntryUdfpsRefactor flag is enabled or not. * @return The view, when [isShowing], else null */ fun getTouchOverlay(): View? { return if (DeviceEntryUdfpsRefactor.isEnabled) { overlayTouchView } else { overlayViewLegacy } } private var overlayParams: UdfpsOverlayParams = UdfpsOverlayParams() private var sensorBounds: Rect = Rect() Loading @@ -132,15 +144,15 @@ class UdfpsControllerOverlay @JvmOverloads constructor( /** If the overlay is currently showing. */ val isShowing: Boolean get() = overlayView != null get() = getTouchOverlay() != null /** Opposite of [isShowing]. */ val isHiding: Boolean get() = overlayView == null get() = getTouchOverlay() == null /** The animation controller if the overlay [isShowing]. */ val animationViewController: UdfpsAnimationViewController<*>? get() = overlayView?.animationViewController get() = overlayViewLegacy?.animationViewController private var touchExplorationEnabled = false Loading @@ -158,11 +170,28 @@ class UdfpsControllerOverlay @JvmOverloads constructor( /** Show the overlay or return false and do nothing if it is already showing. */ @SuppressLint("ClickableViewAccessibility") fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean { if (overlayView == null) { if (getTouchOverlay() == null) { overlayParams = params sensorBounds = Rect(params.sensorBounds) try { overlayView = (inflater.inflate( if (DeviceEntryUdfpsRefactor.isEnabled) { overlayTouchView = (inflater.inflate( R.layout.udfps_touch_overlay, null, false ) as UdfpsTouchOverlay).apply { // This view overlaps the sensor area // prevent it from being selectable during a11y if (requestReason.isImportantForAccessibility()) { importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO } windowManager.addView(this, coreLayoutParams.updateDimensions(null)) } // TODO (b/305234447): Bind view model to UdfpsTouchOverlay here to control // the visibility (sometimes, even if UDFPS is running, the UDFPS UI can be // obscured and we don't want to accept touches. ie: for enrollment don't accept // touches when the shade is expanded and for keyguard: don't accept touches // depending on the keyguard & shade state } else { overlayViewLegacy = (inflater.inflate( R.layout.udfps_view, null, false ) as UdfpsView).apply { overlayParams = params Loading @@ -180,6 +209,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor( windowManager.addView(this, coreLayoutParams.updateDimensions(animation)) sensorRect = sensorBounds } } getTouchOverlay()?.apply { touchExplorationEnabled = accessibilityManager.isTouchExplorationEnabled overlayTouchListener = TouchExplorationStateChangeListener { if (accessibilityManager.isTouchExplorationEnabled) { Loading Loading @@ -211,6 +243,8 @@ class UdfpsControllerOverlay @JvmOverloads constructor( view: UdfpsView, controller: UdfpsController ): UdfpsAnimationViewController<*>? { DeviceEntryUdfpsRefactor.assertInLegacyMode() val isEnrollment = when (requestReason) { REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING -> true else -> false Loading @@ -237,17 +271,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( ) } REASON_AUTH_KEYGUARD -> { if (DeviceEntryUdfpsRefactor.isEnabled) { // note: empty controller, currently shows no visual affordance // instead SysUI will show the fingerprint icon in its DeviceEntryIconView UdfpsBpViewController( view.addUdfpsView(R.layout.udfps_bp_view), statusBarStateController, primaryBouncerInteractor, dialogManager, dumpManager ) } else { UdfpsKeyguardViewControllerLegacy( view.addUdfpsView(R.layout.udfps_keyguard_view_legacy) { updateSensorLocation(sensorBounds) Loading @@ -270,7 +293,6 @@ class UdfpsControllerOverlay @JvmOverloads constructor( transitionInteractor, ) } } REASON_AUTH_BP -> { // note: empty controller, currently shows no visual affordance UdfpsBpViewController( Loading Loading @@ -302,19 +324,26 @@ class UdfpsControllerOverlay @JvmOverloads constructor( fun hide(): Boolean { val wasShowing = isShowing overlayView?.apply { overlayViewLegacy?.apply { if (isDisplayConfigured) { unconfigureDisplay() } animationViewController = null } if (DeviceEntryUdfpsRefactor.isEnabled) { udfpsDisplayModeProvider.disable(null) } getTouchOverlay()?.apply { windowManager.removeView(this) setOnTouchListener(null) setOnHoverListener(null) animationViewController = null overlayTouchListener?.let { accessibilityManager.removeTouchExplorationStateChangeListener(it) } } overlayView = null overlayViewLegacy = null overlayTouchView = null overlayTouchListener = null return wasShowing Loading Loading @@ -392,7 +421,14 @@ class UdfpsControllerOverlay @JvmOverloads constructor( } private fun shouldRotate(animation: UdfpsAnimationViewController<*>?): Boolean { if (animation !is UdfpsKeyguardViewControllerAdapter) { val keyguardNotShowing = if (DeviceEntryUdfpsRefactor.isEnabled) { !keyguardStateController.isShowing } else { animation !is UdfpsKeyguardViewControllerAdapter } if (keyguardNotShowing) { // always rotate view if we're not on the keyguard return true } Loading
packages/SystemUI/src/com/android/systemui/biometrics/ui/view/UdfpsTouchOverlay.kt 0 → 100644 +26 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.systemui.biometrics.ui.view import android.content.Context import android.util.AttributeSet import android.widget.FrameLayout /** * A translucent (not visible to the user) view that receives touches to send to FingerprintManager * for fingerprint authentication. */ class UdfpsTouchOverlay(context: Context, attrs: AttributeSet?) : FrameLayout(context, attrs)
packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerOverlayTest.kt +59 −55 Original line number Diff line number Diff line Loading @@ -36,13 +36,13 @@ import android.view.accessibility.AccessibilityManager import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.res.R Loading Loading @@ -107,7 +107,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { @Mock private lateinit var udfpsView: UdfpsView @Mock private lateinit var mUdfpsKeyguardViewLegacy: UdfpsKeyguardViewLegacy @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator @Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor @Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor Loading Loading @@ -135,8 +134,14 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun withReason( @ShowReason reason: Int, isDebuggable: Boolean = false, block: () -> Unit enableDeviceEntryUdfpsRefactor: Boolean = false, block: () -> Unit, ) { if (enableDeviceEntryUdfpsRefactor) { mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) } else { mSetFlagsRule.disableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR) } controllerOverlay = UdfpsControllerOverlay( context, inflater, Loading @@ -157,7 +162,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { controllerCallback, onTouch, activityLaunchAnimator, featureFlags, primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, Loading Loading @@ -200,7 +204,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -218,7 +222,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -236,7 +240,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -254,7 +258,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { withReason(REASON_AUTH_BP) { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading @@ -270,7 +274,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun showUdfpsOverlay() { val didShow = controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView(eq(controllerOverlay.overlayView), any()) verify(windowManager).addView(eq(controllerOverlay.getTouchOverlay()), any()) verify(udfpsView).setUdfpsDisplayModeProvider(eq(udfpsDisplayMode)) verify(udfpsView).animationViewController = any() verify(udfpsView).addView(any()) Loading @@ -278,7 +282,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { assertThat(didShow).isTrue() assertThat(controllerOverlay.isShowing).isTrue() assertThat(controllerOverlay.isHiding).isFalse() assertThat(controllerOverlay.overlayView).isNotNull() assertThat(controllerOverlay.getTouchOverlay()).isNotNull() } @Test Loading @@ -295,14 +299,14 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { private fun hideUdfpsOverlay() { val didShow = controllerOverlay.show(udfpsController, overlayParams) val view = controllerOverlay.overlayView val view = controllerOverlay.getTouchOverlay() val didHide = controllerOverlay.hide() verify(windowManager).removeView(eq(view)) assertThat(didShow).isTrue() assertThat(didHide).isTrue() assertThat(controllerOverlay.overlayView).isNull() assertThat(controllerOverlay.getTouchOverlay()).isNull() assertThat(controllerOverlay.animationViewController).isNull() assertThat(controllerOverlay.isShowing).isFalse() assertThat(controllerOverlay.isHiding).isTrue() Loading Loading @@ -348,7 +352,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() { controllerOverlay.show(udfpsController, overlayParams) verify(windowManager).addView( eq(controllerOverlay.overlayView), eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture() ) Loading