Loading packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +1 −1 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ constructor( val dialog = animatedDialog.dialog // Don't animate if the dialog is not showing or if we are locked and going to show the // bouncer. // primary bouncer. if ( !dialog.isShowing || (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock()) Loading packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +7 −0 Original line number Diff line number Diff line Loading @@ -715,6 +715,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateBiometricListeningState(BIOMETRIC_ACTION_STOP, FACE_AUTH_STOPPED_KEYGUARD_GOING_AWAY); } /** * Whether keyguard is going away due to screen off or device entry. */ public boolean isKeyguardGoingAway() { return mKeyguardGoingAway; } /** * Updates KeyguardUpdateMonitor's internal state to know if keyguard is showing and if * its occluded. The keyguard is considered visible if its showing and NOT occluded. Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +47 −13 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; Loading Loading @@ -76,6 +77,7 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.data.repository.BiometricType; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.VibratorHelper; Loading @@ -85,8 +87,10 @@ import com.android.systemui.util.concurrency.Execution; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; Loading Loading @@ -150,6 +154,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, @Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps; @Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps; @NonNull private final Map<Integer, Boolean> mFpEnrolledForUser = new HashMap<>(); @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser; @NonNull private final SparseBooleanArray mSfpsEnrolledForUser; @NonNull private final SensorPrivacyManager mSensorPrivacyManager; Loading @@ -161,7 +166,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, private final @Background DelayableExecutor mBackgroundExecutor; private final DisplayInfo mCachedDisplayInfo = new DisplayInfo(); private final VibratorHelper mVibratorHelper; private void vibrateSuccess(int modality) { Loading Loading @@ -331,27 +335,35 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mExecution.assertIsMainThread(); Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId + ", hasEnrollments: " + hasEnrollments); if (mUdfpsProps == null) { Log.d(TAG, "handleEnrollmentsChanged, mUdfpsProps is null"); } else { for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) { BiometricType sensorBiometricType = BiometricType.UNKNOWN; if (mFpProps != null) { for (FingerprintSensorPropertiesInternal prop: mFpProps) { if (prop.sensorId == sensorId) { mFpEnrolledForUser.put(userId, hasEnrollments); if (prop.isAnyUdfpsType()) { sensorBiometricType = BiometricType.UNDER_DISPLAY_FINGERPRINT; mUdfpsEnrolledForUser.put(userId, hasEnrollments); } else if (prop.isAnySidefpsType()) { sensorBiometricType = BiometricType.SIDE_FINGERPRINT; mSfpsEnrolledForUser.put(userId, hasEnrollments); } else if (prop.sensorType == TYPE_REAR) { sensorBiometricType = BiometricType.REAR_FINGERPRINT; } break; } } if (mSidefpsProps == null) { Log.d(TAG, "handleEnrollmentsChanged, mSidefpsProps is null"); } else { for (FingerprintSensorPropertiesInternal prop : mSidefpsProps) { } if (mFaceProps != null && sensorBiometricType == BiometricType.UNKNOWN) { for (FaceSensorPropertiesInternal prop : mFaceProps) { if (prop.sensorId == sensorId) { mSfpsEnrolledForUser.put(userId, hasEnrollments); sensorBiometricType = BiometricType.FACE; break; } } } for (Callback cb : mCallbacks) { cb.onEnrollmentsChanged(); cb.onEnrollmentsChanged(sensorBiometricType, userId, hasEnrollments); } } Loading Loading @@ -604,6 +616,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, } } /** Get FP sensor properties */ public @Nullable List<FingerprintSensorPropertiesInternal> getFingerprintProperties() { return mFpProps; } /** * @return where the face sensor exists in pixels in the current device orientation. Returns * null if no face sensor exists. Loading Loading @@ -828,7 +845,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, } @Override public void setBiometicContextListener(IBiometricContextListener listener) { public void setBiometricContextListener(IBiometricContextListener listener) { mBiometricContextListener = listener; notifyDozeChanged(mStatusBarStateController.isDozing(), mWakefulnessLifecycle.getWakefulness()); Loading Loading @@ -1081,6 +1098,13 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, return mSfpsEnrolledForUser.get(userId); } /** * Whether the passed userId has enrolled at least one fingerprint. */ public boolean isFingerprintEnrolled(int userId) { return mFpEnrolledForUser.getOrDefault(userId, false); } private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) { mCurrentDialogArgs = args; Loading Loading @@ -1262,6 +1286,16 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, */ default void onEnrollmentsChanged() {} /** * Called when UDFPS enrollments have changed. This is called after boot and on changes to * enrollment. */ default void onEnrollmentsChanged( @NonNull BiometricType biometricType, int userId, boolean hasEnrollments ) {} /** * Called when the biometric prompt starts showing. */ Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt +0 −5 Original line number Diff line number Diff line Loading @@ -189,11 +189,6 @@ abstract class UdfpsAnimationViewController<T : UdfpsAnimationView>( */ open fun listenForTouchesOutsideView(): Boolean = false /** * Called on touches outside of the view if listenForTouchesOutsideView returns true */ open fun onTouchOutsideView() {} /** * Called when a view should announce an accessibility event. */ Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +10 −11 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; Loading Loading @@ -149,6 +150,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator; @NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; @Nullable private final TouchProcessor mTouchProcessor; @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor; // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple // sensors, this, in addition to a lot of the code here, will be updated. Loading Loading @@ -232,12 +234,12 @@ public class UdfpsController implements DozeReceiver, Dumpable { mShadeExpansionStateManager, mKeyguardViewManager, mKeyguardUpdateMonitor, mDialogManager, mDumpManager, mLockscreenShadeTransitionController, mConfigurationController, mSystemClock, mKeyguardStateController, mKeyguardStateController, mUnlockedScreenOffAnimationController, mUdfpsDisplayMode, requestId, reason, callback, (view, event, fromUdfpsView) -> onTouch(requestId, event, fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags, mPrimaryBouncerInteractor))); mPrimaryBouncerInteractor, mAlternateBouncerInteractor))); } @Override Loading Loading @@ -329,13 +331,13 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (!mOverlayParams.equals(overlayParams)) { mOverlayParams = overlayParams; final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer(); final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always necessary to re-create the overlay's window with // new LayoutParams. If the overlay needs to be shown, this will re-create and show the // overlay with the updated LayoutParams. Otherwise, the overlay will remain hidden. redrawOverlay(); if (wasShowingAltAuth) { if (wasShowingAlternateBouncer) { mKeyguardViewManager.showBouncer(true); } } Loading Loading @@ -543,9 +545,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { final UdfpsView udfpsView = mOverlay.getOverlayView(); boolean handled = false; switch (event.getActionMasked()) { case MotionEvent.ACTION_OUTSIDE: udfpsView.onTouchOutsideView(); return true; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_HOVER_ENTER: Trace.beginSection("UdfpsController.onTouch.ACTION_DOWN"); Loading Loading @@ -719,7 +718,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull Optional<Provider<AlternateUdfpsTouchProvider>> alternateTouchProvider, @NonNull @BiometricsBackground Executor biometricsExecutor, @NonNull PrimaryBouncerInteractor primaryBouncerInteractor, @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor) { @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor, @NonNull AlternateBouncerInteractor alternateBouncerInteractor) { mContext = context; mExecution = execution; mVibrator = vibrator; Loading Loading @@ -759,6 +759,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { mBiometricExecutor = biometricsExecutor; mPrimaryBouncerInteractor = primaryBouncerInteractor; mAlternateBouncerInteractor = alternateBouncerInteractor; mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION) ? singlePointerTouchProcessor : null; Loading Loading @@ -853,9 +854,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { onFingerUp(mOverlay.getRequestId(), oldView); } final boolean removed = mOverlay.hide(); if (mKeyguardViewManager.isShowingAlternateBouncer()) { mKeyguardViewManager.hideAlternateBouncer(true); } Log.v(TAG, "hideUdfpsOverlay | removing window: " + removed); } else { Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden"); Loading Loading
packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +1 −1 Original line number Diff line number Diff line Loading @@ -366,7 +366,7 @@ constructor( val dialog = animatedDialog.dialog // Don't animate if the dialog is not showing or if we are locked and going to show the // bouncer. // primary bouncer. if ( !dialog.isShowing || (!callback.isUnlocked() && !callback.isShowingAlternateAuthOnUnlock()) Loading
packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +7 −0 Original line number Diff line number Diff line Loading @@ -715,6 +715,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab updateBiometricListeningState(BIOMETRIC_ACTION_STOP, FACE_AUTH_STOPPED_KEYGUARD_GOING_AWAY); } /** * Whether keyguard is going away due to screen off or device entry. */ public boolean isKeyguardGoingAway() { return mKeyguardGoingAway; } /** * Updates KeyguardUpdateMonitor's internal state to know if keyguard is showing and if * its occluded. The keyguard is considered visible if its showing and NOT occluded. Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +47 −13 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.biometrics; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; Loading Loading @@ -76,6 +77,7 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.doze.DozeReceiver; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.keyguard.data.repository.BiometricType; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.VibratorHelper; Loading @@ -85,8 +87,10 @@ import com.android.systemui.util.concurrency.Execution; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; Loading Loading @@ -150,6 +154,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, @Nullable private List<FingerprintSensorPropertiesInternal> mUdfpsProps; @Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps; @NonNull private final Map<Integer, Boolean> mFpEnrolledForUser = new HashMap<>(); @NonNull private final SparseBooleanArray mUdfpsEnrolledForUser; @NonNull private final SparseBooleanArray mSfpsEnrolledForUser; @NonNull private final SensorPrivacyManager mSensorPrivacyManager; Loading @@ -161,7 +166,6 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, private final @Background DelayableExecutor mBackgroundExecutor; private final DisplayInfo mCachedDisplayInfo = new DisplayInfo(); private final VibratorHelper mVibratorHelper; private void vibrateSuccess(int modality) { Loading Loading @@ -331,27 +335,35 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mExecution.assertIsMainThread(); Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId + ", hasEnrollments: " + hasEnrollments); if (mUdfpsProps == null) { Log.d(TAG, "handleEnrollmentsChanged, mUdfpsProps is null"); } else { for (FingerprintSensorPropertiesInternal prop : mUdfpsProps) { BiometricType sensorBiometricType = BiometricType.UNKNOWN; if (mFpProps != null) { for (FingerprintSensorPropertiesInternal prop: mFpProps) { if (prop.sensorId == sensorId) { mFpEnrolledForUser.put(userId, hasEnrollments); if (prop.isAnyUdfpsType()) { sensorBiometricType = BiometricType.UNDER_DISPLAY_FINGERPRINT; mUdfpsEnrolledForUser.put(userId, hasEnrollments); } else if (prop.isAnySidefpsType()) { sensorBiometricType = BiometricType.SIDE_FINGERPRINT; mSfpsEnrolledForUser.put(userId, hasEnrollments); } else if (prop.sensorType == TYPE_REAR) { sensorBiometricType = BiometricType.REAR_FINGERPRINT; } break; } } if (mSidefpsProps == null) { Log.d(TAG, "handleEnrollmentsChanged, mSidefpsProps is null"); } else { for (FingerprintSensorPropertiesInternal prop : mSidefpsProps) { } if (mFaceProps != null && sensorBiometricType == BiometricType.UNKNOWN) { for (FaceSensorPropertiesInternal prop : mFaceProps) { if (prop.sensorId == sensorId) { mSfpsEnrolledForUser.put(userId, hasEnrollments); sensorBiometricType = BiometricType.FACE; break; } } } for (Callback cb : mCallbacks) { cb.onEnrollmentsChanged(); cb.onEnrollmentsChanged(sensorBiometricType, userId, hasEnrollments); } } Loading Loading @@ -604,6 +616,11 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, } } /** Get FP sensor properties */ public @Nullable List<FingerprintSensorPropertiesInternal> getFingerprintProperties() { return mFpProps; } /** * @return where the face sensor exists in pixels in the current device orientation. Returns * null if no face sensor exists. Loading Loading @@ -828,7 +845,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, } @Override public void setBiometicContextListener(IBiometricContextListener listener) { public void setBiometricContextListener(IBiometricContextListener listener) { mBiometricContextListener = listener; notifyDozeChanged(mStatusBarStateController.isDozing(), mWakefulnessLifecycle.getWakefulness()); Loading Loading @@ -1081,6 +1098,13 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, return mSfpsEnrolledForUser.get(userId); } /** * Whether the passed userId has enrolled at least one fingerprint. */ public boolean isFingerprintEnrolled(int userId) { return mFpEnrolledForUser.getOrDefault(userId, false); } private void showDialog(SomeArgs args, boolean skipAnimation, Bundle savedState) { mCurrentDialogArgs = args; Loading Loading @@ -1262,6 +1286,16 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, */ default void onEnrollmentsChanged() {} /** * Called when UDFPS enrollments have changed. This is called after boot and on changes to * enrollment. */ default void onEnrollmentsChanged( @NonNull BiometricType biometricType, int userId, boolean hasEnrollments ) {} /** * Called when the biometric prompt starts showing. */ Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.kt +0 −5 Original line number Diff line number Diff line Loading @@ -189,11 +189,6 @@ abstract class UdfpsAnimationViewController<T : UdfpsAnimationView>( */ open fun listenForTouchesOutsideView(): Boolean = false /** * Called on touches outside of the view if listenForTouchesOutsideView returns true */ open fun onTouchOutsideView() {} /** * Called when a view should announce an accessibility event. */ Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +10 −11 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor; import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; Loading Loading @@ -149,6 +150,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull private final ActivityLaunchAnimator mActivityLaunchAnimator; @NonNull private final PrimaryBouncerInteractor mPrimaryBouncerInteractor; @Nullable private final TouchProcessor mTouchProcessor; @NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor; // Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple // sensors, this, in addition to a lot of the code here, will be updated. Loading Loading @@ -232,12 +234,12 @@ public class UdfpsController implements DozeReceiver, Dumpable { mShadeExpansionStateManager, mKeyguardViewManager, mKeyguardUpdateMonitor, mDialogManager, mDumpManager, mLockscreenShadeTransitionController, mConfigurationController, mSystemClock, mKeyguardStateController, mKeyguardStateController, mUnlockedScreenOffAnimationController, mUdfpsDisplayMode, requestId, reason, callback, (view, event, fromUdfpsView) -> onTouch(requestId, event, fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags, mPrimaryBouncerInteractor))); mPrimaryBouncerInteractor, mAlternateBouncerInteractor))); } @Override Loading Loading @@ -329,13 +331,13 @@ public class UdfpsController implements DozeReceiver, Dumpable { if (!mOverlayParams.equals(overlayParams)) { mOverlayParams = overlayParams; final boolean wasShowingAltAuth = mKeyguardViewManager.isShowingAlternateBouncer(); final boolean wasShowingAlternateBouncer = mAlternateBouncerInteractor.isVisibleState(); // When the bounds change it's always necessary to re-create the overlay's window with // new LayoutParams. If the overlay needs to be shown, this will re-create and show the // overlay with the updated LayoutParams. Otherwise, the overlay will remain hidden. redrawOverlay(); if (wasShowingAltAuth) { if (wasShowingAlternateBouncer) { mKeyguardViewManager.showBouncer(true); } } Loading Loading @@ -543,9 +545,6 @@ public class UdfpsController implements DozeReceiver, Dumpable { final UdfpsView udfpsView = mOverlay.getOverlayView(); boolean handled = false; switch (event.getActionMasked()) { case MotionEvent.ACTION_OUTSIDE: udfpsView.onTouchOutsideView(); return true; case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_HOVER_ENTER: Trace.beginSection("UdfpsController.onTouch.ACTION_DOWN"); Loading Loading @@ -719,7 +718,8 @@ public class UdfpsController implements DozeReceiver, Dumpable { @NonNull Optional<Provider<AlternateUdfpsTouchProvider>> alternateTouchProvider, @NonNull @BiometricsBackground Executor biometricsExecutor, @NonNull PrimaryBouncerInteractor primaryBouncerInteractor, @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor) { @NonNull SinglePointerTouchProcessor singlePointerTouchProcessor, @NonNull AlternateBouncerInteractor alternateBouncerInteractor) { mContext = context; mExecution = execution; mVibrator = vibrator; Loading Loading @@ -759,6 +759,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { mBiometricExecutor = biometricsExecutor; mPrimaryBouncerInteractor = primaryBouncerInteractor; mAlternateBouncerInteractor = alternateBouncerInteractor; mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION) ? singlePointerTouchProcessor : null; Loading Loading @@ -853,9 +854,7 @@ public class UdfpsController implements DozeReceiver, Dumpable { onFingerUp(mOverlay.getRequestId(), oldView); } final boolean removed = mOverlay.hide(); if (mKeyguardViewManager.isShowingAlternateBouncer()) { mKeyguardViewManager.hideAlternateBouncer(true); } Log.v(TAG, "hideUdfpsOverlay | removing window: " + removed); } else { Log.v(TAG, "hideUdfpsOverlay | the overlay is already hidden"); Loading