Merge "Refine biometrics accessibility interactor" into main
diff --git a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
index 761a9c3..50ac3cd 100644
--- a/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/BiometricsEnvironment.kt
@@ -133,11 +133,8 @@
   fun createRenameFingerprintInteractor(): RenameFingerprintInteractor =
     RenameFingerprintsInteractorImpl(fingerprintManager, context.userId, backgroundDispatcher)
 
-  val accessibilityInteractor: AccessibilityInteractor by lazy {
-    AccessibilityInteractorImpl(
-      context.getSystemService(AccessibilityManager::class.java)!!,
-      applicationScope,
-    )
+  fun createAccessibilityInteractor(): AccessibilityInteractor {
+    return AccessibilityInteractorImpl(context.getSystemService(AccessibilityManager::class.java)!!)
   }
 
   val foldStateInteractor: FoldStateInteractor by lazy { FoldStateInteractorImpl(context) }
@@ -157,7 +154,7 @@
   val enrollStageInteractor: EnrollStageInteractor by lazy { EnrollStageInteractorImpl() }
 
   val udfpsEnrollInteractor: UdfpsEnrollInteractor by lazy {
-    UdfpsEnrollInteractorImpl(context, accessibilityInteractor)
+    UdfpsEnrollInteractorImpl(context, createAccessibilityInteractor())
   }
 
   val sensorInteractor: FingerprintSensorInteractor by lazy {
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
index e1a08e6..9f62ed0 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/AccessibilityInteractor.kt
@@ -16,6 +16,8 @@
 
 package com.android.settings.biometrics.fingerprint2.domain.interactor
 
+import android.view.accessibility.AccessibilityEvent
+import android.view.accessibility.AccessibilityEvent.TYPE_ANNOUNCEMENT
 import android.view.accessibility.AccessibilityManager
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
@@ -27,26 +29,38 @@
 /** Represents all of the information on accessibility state. */
 interface AccessibilityInteractor {
   /** A flow that contains whether or not accessibility is enabled */
-  val isAccessibilityEnabled: Flow<Boolean>
+  fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean>
+  val isEnabled: Boolean
+  fun announce(clazz: Class<*>, announcement: CharSequence?)
 }
 
 class AccessibilityInteractorImpl(
-  accessibilityManager: AccessibilityManager,
-  applicationScope: CoroutineScope,
+  private val accessibilityManager: AccessibilityManager,
 ) : AccessibilityInteractor {
   /** A flow that contains whether or not accessibility is enabled */
-  override val isAccessibilityEnabled: Flow<Boolean> =
+  override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> =
     callbackFlow {
-        val listener =
-          AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) }
-        accessibilityManager.addAccessibilityStateChangeListener(listener)
+      val listener =
+        AccessibilityManager.AccessibilityStateChangeListener { enabled -> trySend(enabled) }
+      accessibilityManager.addAccessibilityStateChangeListener(listener)
 
-        // This clause will be called when no one is listening to the flow
-        awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
-      }
+      // This clause will be called when no one is listening to the flow
+      awaitClose { accessibilityManager.removeAccessibilityStateChangeListener(listener) }
+    }
       .stateIn(
-        applicationScope, // This is going to tied to the activity scope
+        scope,
         SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
         false,
       )
+
+  override val isEnabled: Boolean
+    get() = accessibilityManager.isEnabled
+
+  override fun announce(clazz: Class<*>, announcement: CharSequence?) {
+    val event = AccessibilityEvent(TYPE_ANNOUNCEMENT)
+    event.className = clazz.javaClass.name
+    event.packageName = clazz.packageName
+    event.text.add(announcement)
+    accessibilityManager.sendAccessibilityEvent(event)
+  }
 }
diff --git a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
index 006060a..62c51ae 100644
--- a/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/domain/interactor/UdfpsEnrollInteractor.kt
@@ -19,6 +19,7 @@
 import android.content.Context
 import android.graphics.PointF
 import android.util.TypedValue
+import kotlinx.coroutines.MainScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.combine
@@ -87,7 +88,7 @@
   override val guidedEnrollmentOffset: Flow<PointF> =
     combine(
       _guidedEnrollment,
-      accessibilityInteractor.isAccessibilityEnabled,
+      accessibilityInteractor.isEnabledFlow(MainScope()),
       isGuidedEnrollment,
     ) { point, accessibilityEnabled, guidedEnrollmentEnabled ->
       if (accessibilityEnabled || !guidedEnrollmentEnabled) {
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
index 658c6c7..df46aa4 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/udfps/ui/viewmodel/UdfpsViewModel.kt
@@ -179,7 +179,7 @@
 
   /** Indicates if accessibility is enabled */
   val accessibilityEnabled =
-    accessibilityInteractor.isAccessibilityEnabled.shareIn(
+    accessibilityInteractor.isEnabledFlow(viewModelScope).shareIn(
       this.viewModelScope,
       SharingStarted.Eagerly,
       replay = 1,
@@ -425,7 +425,7 @@
           biometricEnvironment.enrollStageInteractor,
           biometricEnvironment.orientationInteractor,
           biometricEnvironment.udfpsEnrollInteractor,
-          biometricEnvironment.accessibilityInteractor,
+          biometricEnvironment.createAccessibilityInteractor(),
           biometricEnvironment.sensorInteractor,
           biometricEnvironment.touchEventInteractor,
           biometricEnvironment.createSensorPropertiesInteractor(),
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
index 9b2cdde..b27cfdd 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollFindSensorViewModel.kt
@@ -84,7 +84,7 @@
 
   /** Represents the stream of showing udfps lottie and whether accessibility is enabled. */
   val udfpsLottieInfo: Flow<Boolean> =
-    _showUdfpsLottie.combine(accessibilityInteractor.isAccessibilityEnabled) {
+    _showUdfpsLottie.combine(accessibilityInteractor.isEnabledFlow(viewModelScope)) {
       _,
       isAccessibilityEnabled ->
       isAccessibilityEnabled
@@ -213,7 +213,7 @@
           provider[FingerprintGatekeeperViewModel::class],
           provider[BackgroundViewModel::class],
           provider[FingerprintFlowViewModel::class],
-          biometricEnvironment.accessibilityInteractor,
+          biometricEnvironment.createAccessibilityInteractor(),
           biometricEnvironment.foldStateInteractor,
           biometricEnvironment.orientationInteractor,
           biometricEnvironment.createSensorPropertiesInteractor(),
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
index e7fc3ed..a5d0461 100644
--- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
@@ -44,6 +44,7 @@
 import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
 import com.android.settings.testutils2.FakeFingerprintManagerInteractor
 import com.android.systemui.biometrics.shared.model.toFingerprintSensor
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -73,7 +74,10 @@
 
   var accessibilityInteractor =
     object : AccessibilityInteractor {
-      override val isAccessibilityEnabled: Flow<Boolean> = flowOf(true)
+      override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
+      override val isEnabled: Boolean
+        get() = true
+      override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
     }
 
   var foldStateInteractor =
diff --git a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
index 04cece8..a8c5e68 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
@@ -39,6 +39,7 @@
 import com.android.settings.testutils2.FakeFingerprintManagerInteractor
 import com.android.systemui.biometrics.shared.model.toFingerprintSensor
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -106,7 +107,10 @@
       )
     accessibilityInteractor =
       object : AccessibilityInteractor {
-        override val isAccessibilityEnabled: Flow<Boolean> = flowOf(false)
+        override fun isEnabledFlow(scope: CoroutineScope): Flow<Boolean> = flowOf(true)
+        override val isEnabled: Boolean
+          get() = true
+        override fun announce(clazz: Class<*>, announcement: CharSequence?) {}
       }
     foldStateInteractor =
       object : FoldStateInteractor {