Merge "Add a setting to remove UDFPS overlay enrollment UI" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8ee656b95c
@@ -21,13 +21,18 @@ import android.annotation.UiThread
|
||||
import android.content.Context
|
||||
import android.graphics.PixelFormat
|
||||
import android.graphics.Rect
|
||||
import android.hardware.biometrics.BiometricOverlayConstants
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
|
||||
import android.os.Build
|
||||
import android.os.RemoteException
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.util.RotationUtils
|
||||
import android.view.LayoutInflater
|
||||
@@ -38,6 +43,7 @@ import android.view.WindowManager
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||
@@ -54,13 +60,16 @@ import com.android.systemui.util.time.SystemClock
|
||||
|
||||
private const val TAG = "UdfpsControllerOverlay"
|
||||
|
||||
@VisibleForTesting
|
||||
const val SETTING_REMOVE_ENROLLMENT_UI = "udfps_overlay_remove_enrollment_ui"
|
||||
|
||||
/**
|
||||
* Keeps track of the overlay state and UI resources associated with a single FingerprintService
|
||||
* request. This state can persist across configuration changes via the [show] and [hide]
|
||||
* methods.
|
||||
*/
|
||||
@UiThread
|
||||
class UdfpsControllerOverlay(
|
||||
class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
private val context: Context,
|
||||
fingerprintManager: FingerprintManager,
|
||||
private val inflater: LayoutInflater,
|
||||
@@ -82,7 +91,8 @@ class UdfpsControllerOverlay(
|
||||
@ShowReason val requestReason: Int,
|
||||
private val controllerCallback: IUdfpsOverlayControllerCallback,
|
||||
private val onTouch: (View, MotionEvent, Boolean) -> Boolean,
|
||||
private val activityLaunchAnimator: ActivityLaunchAnimator
|
||||
private val activityLaunchAnimator: ActivityLaunchAnimator,
|
||||
private val isDebuggable: Boolean = Build.IS_DEBUGGABLE
|
||||
) {
|
||||
/** The view, when [isShowing], or null. */
|
||||
var overlayView: UdfpsView? = null
|
||||
@@ -102,18 +112,19 @@ class UdfpsControllerOverlay(
|
||||
gravity = android.view.Gravity.TOP or android.view.Gravity.LEFT
|
||||
layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
||||
flags = (Utils.FINGERPRINT_OVERLAY_LAYOUT_PARAM_FLAGS or
|
||||
WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
|
||||
WindowManager.LayoutParams.FLAG_SPLIT_TOUCH)
|
||||
privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY
|
||||
// Avoid announcing window title.
|
||||
accessibilityTitle = " "
|
||||
}
|
||||
|
||||
/** A helper if the [requestReason] was due to enrollment. */
|
||||
val enrollHelper: UdfpsEnrollHelper? = if (requestReason.isEnrollmentReason()) {
|
||||
UdfpsEnrollHelper(context, fingerprintManager, requestReason)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val enrollHelper: UdfpsEnrollHelper? =
|
||||
if (requestReason.isEnrollmentReason() && !shouldRemoveEnrollmentUi()) {
|
||||
UdfpsEnrollHelper(context, fingerprintManager, requestReason)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
/** If the overlay is currently showing. */
|
||||
val isShowing: Boolean
|
||||
@@ -129,6 +140,17 @@ class UdfpsControllerOverlay(
|
||||
|
||||
private var touchExplorationEnabled = false
|
||||
|
||||
private fun shouldRemoveEnrollmentUi(): Boolean {
|
||||
if (isDebuggable) {
|
||||
return Settings.Global.getInt(
|
||||
context.contentResolver,
|
||||
SETTING_REMOVE_ENROLLMENT_UI,
|
||||
0 /* def */
|
||||
) != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/** Show the overlay or return false and do nothing if it is already showing. */
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
fun show(controller: UdfpsController, params: UdfpsOverlayParams): Boolean {
|
||||
@@ -183,7 +205,18 @@ class UdfpsControllerOverlay(
|
||||
view: UdfpsView,
|
||||
controller: UdfpsController
|
||||
): UdfpsAnimationViewController<*>? {
|
||||
return when (requestReason) {
|
||||
val isEnrollment = when (requestReason) {
|
||||
REASON_ENROLL_FIND_SENSOR, REASON_ENROLL_ENROLLING -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
val filteredRequestReason = if (isEnrollment && shouldRemoveEnrollmentUi()) {
|
||||
REASON_AUTH_OTHER
|
||||
} else {
|
||||
requestReason
|
||||
}
|
||||
|
||||
return when (filteredRequestReason) {
|
||||
REASON_ENROLL_FIND_SENSOR,
|
||||
REASON_ENROLL_ENROLLING -> {
|
||||
UdfpsEnrollViewController(
|
||||
@@ -198,7 +231,7 @@ class UdfpsControllerOverlay(
|
||||
overlayParams.scaleFactor
|
||||
)
|
||||
}
|
||||
BiometricOverlayConstants.REASON_AUTH_KEYGUARD -> {
|
||||
REASON_AUTH_KEYGUARD -> {
|
||||
UdfpsKeyguardViewController(
|
||||
view.addUdfpsView(R.layout.udfps_keyguard_view),
|
||||
statusBarStateController,
|
||||
@@ -216,7 +249,7 @@ class UdfpsControllerOverlay(
|
||||
activityLaunchAnimator
|
||||
)
|
||||
}
|
||||
BiometricOverlayConstants.REASON_AUTH_BP -> {
|
||||
REASON_AUTH_BP -> {
|
||||
// note: empty controller, currently shows no visual affordance
|
||||
UdfpsBpViewController(
|
||||
view.addUdfpsView(R.layout.udfps_bp_view),
|
||||
@@ -226,8 +259,8 @@ class UdfpsControllerOverlay(
|
||||
dumpManager
|
||||
)
|
||||
}
|
||||
BiometricOverlayConstants.REASON_AUTH_OTHER,
|
||||
BiometricOverlayConstants.REASON_AUTH_SETTINGS -> {
|
||||
REASON_AUTH_OTHER,
|
||||
REASON_AUTH_SETTINGS -> {
|
||||
UdfpsFpmOtherViewController(
|
||||
view.addUdfpsView(R.layout.udfps_fpm_other_view),
|
||||
statusBarStateController,
|
||||
@@ -440,4 +473,4 @@ private fun Int.isEnrollmentReason() =
|
||||
private fun Int.isImportantForAccessibility() =
|
||||
this == REASON_ENROLL_FIND_SENSOR ||
|
||||
this == REASON_ENROLL_ENROLLING ||
|
||||
this == BiometricOverlayConstants.REASON_AUTH_BP
|
||||
this == REASON_AUTH_BP
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.ShowReason
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
|
||||
import android.provider.Settings
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.view.LayoutInflater
|
||||
@@ -124,14 +125,18 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
whenever(udfpsEnrollView.context).thenReturn(context)
|
||||
}
|
||||
|
||||
private fun withReason(@ShowReason reason: Int, block: () -> Unit) {
|
||||
private fun withReason(
|
||||
@ShowReason reason: Int,
|
||||
isDebuggable: Boolean = false,
|
||||
block: () -> Unit
|
||||
) {
|
||||
controllerOverlay = UdfpsControllerOverlay(
|
||||
context, fingerprintManager, inflater, windowManager, accessibilityManager,
|
||||
statusBarStateController, shadeExpansionStateManager, statusBarKeyguardViewManager,
|
||||
keyguardUpdateMonitor, dialogManager, dumpManager, transitionController,
|
||||
configurationController, systemClock, keyguardStateController,
|
||||
unlockedScreenOffAnimationController, udfpsDisplayMode, REQUEST_ID, reason,
|
||||
controllerCallback, onTouch, activityLaunchAnimator
|
||||
controllerCallback, onTouch, activityLaunchAnimator, isDebuggable
|
||||
)
|
||||
block()
|
||||
}
|
||||
@@ -150,11 +155,29 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
showUdfpsOverlay(isEnrollUseCase = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showUdfpsOverlay_locate_withEnrollmentUiRemoved() {
|
||||
Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1)
|
||||
withReason(REASON_ENROLL_FIND_SENSOR, isDebuggable = true) {
|
||||
showUdfpsOverlay(isEnrollUseCase = false)
|
||||
}
|
||||
Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showUdfpsOverlay_enroll() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
showUdfpsOverlay(isEnrollUseCase = true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showUdfpsOverlay_enroll_withEnrollmentUiRemoved() {
|
||||
Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 1)
|
||||
withReason(REASON_ENROLL_ENROLLING, isDebuggable = true) {
|
||||
showUdfpsOverlay(isEnrollUseCase = false)
|
||||
}
|
||||
Settings.Global.putInt(mContext.contentResolver, SETTING_REMOVE_ENROLLMENT_UI, 0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun showUdfpsOverlay_other() = withReason(REASON_AUTH_OTHER) { showUdfpsOverlay() }
|
||||
|
||||
@@ -372,21 +395,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_0
|
||||
// touch at 0 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[0])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
// touch at 90 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[1])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 180 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[2])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
// touch at 270 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[3])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
}
|
||||
|
||||
fun testTouchOutsideAreaNoRotation90Degrees() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
@@ -394,21 +429,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_90
|
||||
// touch at 0 degrees -> 90 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[1])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 90 degrees -> 180 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[2])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
// touch at 180 degrees -> 270 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[3])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
// touch at 270 degrees -> 0 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[0])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
}
|
||||
|
||||
fun testTouchOutsideAreaNoRotation270Degrees() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
@@ -416,21 +463,33 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_270
|
||||
// touch at 0 degrees -> 270 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[3])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
// touch at 90 degrees -> 0 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[0])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
// touch at 180 degrees -> 90 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[1])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 270 degrees -> 180 degrees
|
||||
assertThat(controllerOverlay.onTouchOutsideOfSensorAreaImpl(0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation))
|
||||
.isEqualTo(touchHints[2])
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user