summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Android Build Coastguard Worker <android-build-coastguard-worker@google.com> 2025-04-04 21:47:16 -0700
committer Android Build Coastguard Worker <android-build-coastguard-worker@google.com> 2025-04-04 21:47:16 -0700
commit92c687d0c0abf5c8c76aaf33476dbe3f1384e677 (patch)
tree8e5f5865f58a7185d8663158759ed57845702947
parenta5f7ff521d9e05a6a1b42eaf2ecee60ad0033ff5 (diff)
parentcfa6ede1c3116cd3ac77470ec67569ecfc938340 (diff)
Merge cherrypicks of ['googleplex-android-review.googlesource.com/32805538', 'googleplex-android-review.googlesource.com/32837056', 'googleplex-android-review.googlesource.com/32837463', 'googleplex-android-review.googlesource.com/32837650', 'googleplex-android-review.googlesource.com/32837464'] into 25Q2-release.
Change-Id: I4d4a35ffb0450990b33c8a1e2792d1be4c66ed60
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt81
-rw-r--r--packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml3
-rw-r--r--packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt60
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt19
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/view/UdfpsAccessibilityOverlay.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt13
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/ui/viewmodel/UdfpsAccessibilityOverlayViewModelKosmos.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt2
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java2
18 files changed, 52 insertions, 323 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
index a7810a69265a..90500839c8ad 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/ui/viewmodel/UdfpsAccessibilityOverlayViewModelTest.kt
@@ -16,17 +16,13 @@
package com.android.systemui.deviceentry.domain.ui.viewmodel
-import android.graphics.Point
import android.platform.test.flag.junit.FlagsParameterization
-import android.view.MotionEvent
-import android.view.View
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.accessibility.data.repository.fakeAccessibilityRepository
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
-import com.android.systemui.biometrics.udfpsUtils
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.data.ui.viewmodel.alternateBouncerUdfpsAccessibilityOverlayViewModel
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
import com.android.systemui.deviceentry.data.ui.viewmodel.deviceEntryUdfpsAccessibilityOverlayViewModel
import com.android.systemui.deviceentry.ui.viewmodel.DeviceEntryUdfpsAccessibilityOverlayViewModel
import com.android.systemui.flags.Flags.FULL_SCREEN_USER_SWITCHER
@@ -38,7 +34,6 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.keyguard.ui.viewmodel.accessibilityActionsViewModelKosmos
import com.android.systemui.keyguard.ui.viewmodel.fakeDeviceEntryIconViewModelTransition
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
@@ -46,22 +41,14 @@ import com.android.systemui.shade.shadeTestUtil
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyBoolean
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.kotlin.any
-import org.mockito.kotlin.eq
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.whenever
import platform.test.runner.parameterized.ParameterizedAndroidJunit4
import platform.test.runner.parameterized.Parameters
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
class UdfpsAccessibilityOverlayViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
@@ -76,6 +63,7 @@ class UdfpsAccessibilityOverlayViewModelTest(flags: FlagsParameterization) : Sys
private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
private val fingerprintPropertyRepository = kosmos.fingerprintPropertyRepository
private val deviceEntryFingerprintAuthRepository = kosmos.deviceEntryFingerprintAuthRepository
+ private val deviceEntryRepository = kosmos.fakeDeviceEntryRepository
private val shadeTestUtil by lazy { kosmos.shadeTestUtil }
@@ -95,22 +83,6 @@ class UdfpsAccessibilityOverlayViewModelTest(flags: FlagsParameterization) : Sys
@Before
fun setup() {
- whenever(kosmos.udfpsUtils.isWithinSensorArea(any(), any(), any())).thenReturn(false)
- whenever(
- kosmos.udfpsUtils.getTouchInNativeCoordinates(anyInt(), any(), any(), anyBoolean())
- )
- .thenReturn(Point(0, 0))
- whenever(
- kosmos.udfpsUtils.onTouchOutsideOfSensorArea(
- anyBoolean(),
- eq(null),
- anyInt(),
- anyInt(),
- any(),
- anyBoolean(),
- )
- )
- .thenReturn("Move left")
underTest = kosmos.deviceEntryUdfpsAccessibilityOverlayViewModel
overrideResource(R.integer.udfps_padding_debounce_duration, 0)
}
@@ -129,55 +101,6 @@ class UdfpsAccessibilityOverlayViewModelTest(flags: FlagsParameterization) : Sys
}
@Test
- fun contentDescription_setOnUdfpsTouchOutsideSensorArea() =
- testScope.runTest {
- val contentDescription by collectLastValue(underTest.contentDescription)
- setupVisibleStateOnLockscreen()
- underTest.onHoverEvent(mock<View>(), mock<MotionEvent>())
- runCurrent()
- assertThat(contentDescription).isEqualTo("Move left")
- }
-
- @Test
- fun clearAccessibilityOverlayMessageReason_updatesWhenFocusChangesFromUdfpsOverlayToLockscreen() =
- testScope.runTest {
- val clearAccessibilityOverlayMessageReason by
- collectLastValue(underTest.clearAccessibilityOverlayMessageReason)
- val contentDescription by collectLastValue(underTest.contentDescription)
- setupVisibleStateOnLockscreen()
- kosmos.accessibilityActionsViewModelKosmos.clearUdfpsAccessibilityOverlayMessage("test")
- runCurrent()
- assertThat(clearAccessibilityOverlayMessageReason).isEqualTo("test")
-
- // UdfpsAccessibilityOverlayViewBinder collects clearAccessibilityOverlayMessageReason
- // and calls
- // viewModel.setContentDescription(null) - mock this here
- underTest.setContentDescription(null)
- runCurrent()
- assertThat(contentDescription).isNull()
- }
-
- @Test
- fun clearAccessibilityOverlayMessageReason_updatesAfterUdfpsOverlayFocusOnAlternateBouncer() =
- testScope.runTest {
- val clearAccessibilityOverlayMessageReason by
- collectLastValue(underTest.clearAccessibilityOverlayMessageReason)
- val contentDescription by collectLastValue(underTest.contentDescription)
- setupVisibleStateOnLockscreen()
- kosmos.alternateBouncerUdfpsAccessibilityOverlayViewModel
- .clearUdfpsAccessibilityOverlayMessage("test")
- runCurrent()
- assertThat(clearAccessibilityOverlayMessageReason).isEqualTo("test")
-
- // UdfpsAccessibilityOverlayViewBinder collects clearAccessibilityOverlayMessageReason
- // and calls
- // viewModel.setContentDescription(null) - mock this here
- underTest.setContentDescription(null)
- runCurrent()
- assertThat(contentDescription).isNull()
- }
-
- @Test
fun touchExplorationNotEnabled_overlayNotVisible() =
testScope.runTest {
val visible by collectLastValue(underTest.visible)
diff --git a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
index 1e4a07f5fc30..43808f215a81 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_one_pane_layout.xml
@@ -21,9 +21,6 @@
style="@style/AuthCredentialPanelStyle"
android:layout_width="0dp"
android:layout_height="0dp"
- android:accessibilityLiveRegion="assertive"
- android:importantForAccessibility="auto"
- android:clickable="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/rightGuideline"
app:layout_constraintStart_toStartOf="@id/leftGuideline"
diff --git a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
index 8234c24a7e17..51117a7845df 100644
--- a/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
+++ b/packages/SystemUI/res/layout/biometric_prompt_two_pane_layout.xml
@@ -22,9 +22,6 @@ android:layout_height="match_parent">
style="@style/AuthCredentialPanelStyle"
android:layout_width="0dp"
android:layout_height="0dp"
- android:accessibilityLiveRegion="assertive"
- android:importantForAccessibility="auto"
- android:clickable="false"
android:paddingHorizontal="16dp"
android:paddingVertical="16dp"
android:visibility="visible"
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
index 2bb9809af30e..8a5e011cd3ce 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/UdfpsOverlayInteractor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.biometrics.domain.interactor
-import android.annotation.SuppressLint
import android.content.Context
import android.hardware.fingerprint.FingerprintManager
import android.util.Log
@@ -33,14 +32,10 @@ import javax.inject.Inject
import kotlin.math.max
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
@@ -136,25 +131,6 @@ constructor(
}
.distinctUntilChanged()
- /**
- * Event flow that emits every time the user taps the screen and a UDFPS guidance message is
- * surfaced and then cleared. Modeled as a SharedFlow because a StateFlow fails to emit every
- * event to the subscriber, causing missed Talkback feedback and incorrect focusability state of
- * the UDFPS accessibility overlay.
- */
- @SuppressLint("SharedFlowCreation")
- private val _clearAccessibilityOverlayMessageReason = MutableSharedFlow<String?>()
-
- /** Indicates the reason for clearing the UDFPS accessibility overlay content description */
- val clearAccessibilityOverlayMessageReason: SharedFlow<String?> =
- _clearAccessibilityOverlayMessageReason.asSharedFlow()
-
- suspend fun clearUdfpsAccessibilityOverlayMessage(reason: String) {
- // Add delay to make sure we read the guidance message before clearing it
- delay(1000)
- _clearAccessibilityOverlayMessageReason.emit(reason)
- }
-
companion object {
private const val TAG = "UdfpsOverlayInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
index 80d06f4a2d37..54c52b533da4 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/binder/BiometricViewBinder.kt
@@ -27,7 +27,6 @@ import android.util.Log
import android.view.MotionEvent
import android.view.View
import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO
-import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES
import android.view.accessibility.AccessibilityManager
import android.widget.Button
import android.widget.ImageView
@@ -44,6 +43,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.airbnb.lottie.LottieAnimationView
import com.airbnb.lottie.LottieCompositionFactory
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.biometrics.Utils.ellipsize
import com.android.systemui.biometrics.shared.model.BiometricModalities
import com.android.systemui.biometrics.shared.model.BiometricModality
@@ -63,7 +63,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
private const val TAG = "BiometricViewBinder"
@@ -124,6 +123,25 @@ object BiometricViewBinder {
val confirmationButton = view.requireViewById<Button>(R.id.button_confirm)
val retryButton = view.requireViewById<Button>(R.id.button_try_again)
+ // Handles custom "Cancel Authentication" talkback action
+ val cancelDelegate: AccessibilityDelegateCompat =
+ object : AccessibilityDelegateCompat() {
+ override fun onInitializeAccessibilityNodeInfo(
+ host: View,
+ info: AccessibilityNodeInfoCompat,
+ ) {
+ super.onInitializeAccessibilityNodeInfo(host, info)
+ info.addAction(
+ AccessibilityActionCompat(
+ AccessibilityNodeInfoCompat.ACTION_CLICK,
+ view.context.getString(R.string.biometric_dialog_cancel_authentication),
+ )
+ )
+ }
+ }
+ ViewCompat.setAccessibilityDelegate(backgroundView, cancelDelegate)
+ ViewCompat.setAccessibilityDelegate(cancelButton, cancelDelegate)
+
// TODO(b/330788871): temporary workaround for the unsafe callbacks & legacy controllers
val adapter =
Spaghetti(
@@ -137,33 +155,6 @@ object BiometricViewBinder {
var boundSize = false
view.repeatWhenAttached {
- // Handles custom "Cancel Authentication" talkback action
- val cancelDelegate: AccessibilityDelegateCompat =
- object : AccessibilityDelegateCompat() {
- override fun onInitializeAccessibilityNodeInfo(
- host: View,
- info: AccessibilityNodeInfoCompat,
- ) {
- super.onInitializeAccessibilityNodeInfo(host, info)
- lifecycleScope.launch {
- // Clears UDFPS guidance hint after focus moves to cancel view
- viewModel.onClearUdfpsGuidanceHint(
- accessibilityManager.isTouchExplorationEnabled
- )
- }
- info.addAction(
- AccessibilityActionCompat(
- AccessibilityNodeInfoCompat.ACTION_CLICK,
- view.context.getString(
- R.string.biometric_dialog_cancel_authentication
- ),
- )
- )
- }
- }
- ViewCompat.setAccessibilityDelegate(backgroundView, cancelDelegate)
- ViewCompat.setAccessibilityDelegate(cancelButton, cancelDelegate)
-
// these do not change and need to be set before any size transitions
val modalities = viewModel.modalities.first()
@@ -406,23 +397,16 @@ object BiometricViewBinder {
// Talkback directional guidance
udfpsGuidanceView.setOnHoverListener { _, event ->
launch {
- viewModel.onUpdateAccessibilityHint(
+ viewModel.onAnnounceAccessibilityHint(
event,
accessibilityManager.isTouchExplorationEnabled,
)
}
false
}
-
launch {
viewModel.accessibilityHint.collect { message ->
- udfpsGuidanceView.importantForAccessibility =
- if (message == null) {
- IMPORTANT_FOR_ACCESSIBILITY_NO
- } else {
- IMPORTANT_FOR_ACCESSIBILITY_YES
- }
- udfpsGuidanceView.contentDescription = message
+ if (message.isNotBlank()) view.announceForAccessibility(message)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
index 27fc1878cc99..0902d19b6787 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModel.kt
@@ -187,10 +187,10 @@ constructor(
}
}
- private val _accessibilityHint = MutableSharedFlow<String?>()
+ private val _accessibilityHint = MutableSharedFlow<String>()
/** Hint for talkback directional guidance */
- val accessibilityHint: Flow<String?> = _accessibilityHint.asSharedFlow()
+ val accessibilityHint: Flow<String> = _accessibilityHint.asSharedFlow()
private val _isAuthenticating: MutableStateFlow<Boolean> = MutableStateFlow(false)
@@ -886,7 +886,7 @@ constructor(
}
/** Sets the message used for UDFPS directional guidance */
- suspend fun onUpdateAccessibilityHint(
+ suspend fun onAnnounceAccessibilityHint(
event: MotionEvent,
touchExplorationEnabled: Boolean,
): Boolean {
@@ -923,19 +923,6 @@ constructor(
return false
}
- /** Clears the message used for UDFPS directional guidance */
- suspend fun onClearUdfpsGuidanceHint(touchExplorationEnabled: Boolean) {
- if (
- modalities.first().hasUdfps &&
- touchExplorationEnabled &&
- !isAuthenticated.first().isAuthenticated
- ) {
- // Add delay to make sure we read the guidance message before clearing it
- delay(1000)
- _accessibilityHint.emit(null)
- }
- }
-
/**
* Switch to the credential view.
*
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
index 3abc260fdcbd..e2172d0773d3 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/binder/UdfpsAccessibilityOverlayBinder.kt
@@ -18,58 +18,27 @@
package com.android.systemui.deviceentry.ui.binder
import android.annotation.SuppressLint
-import android.util.Log
-import android.view.MotionEvent
-import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_NO
-import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES
import androidx.core.view.isInvisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.deviceentry.ui.view.UdfpsAccessibilityOverlay
import com.android.systemui.deviceentry.ui.viewmodel.UdfpsAccessibilityOverlayViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
object UdfpsAccessibilityOverlayBinder {
- private const val TAG = "UdfpsAccessibilityOverlayBinder"
/** Forwards hover events to the view model to make guided announcements for accessibility. */
@SuppressLint("ClickableViewAccessibility")
@JvmStatic
- fun bind(view: UdfpsAccessibilityOverlay, viewModel: UdfpsAccessibilityOverlayViewModel) {
+ fun bind(
+ view: UdfpsAccessibilityOverlay,
+ viewModel: UdfpsAccessibilityOverlayViewModel,
+ ) {
+ view.setOnHoverListener { v, event -> viewModel.onHoverEvent(v, event) }
view.repeatWhenAttached {
// Repeat on CREATED because we update the visibility of the view
repeatOnLifecycle(Lifecycle.State.CREATED) {
- view.setOnHoverListener { v, event ->
- if (event.action == MotionEvent.ACTION_HOVER_ENTER) {
- launch { viewModel.onHoverEvent(v, event) }
- }
- false
- }
-
- launch { viewModel.visible.collect { visible -> view.isInvisible = !visible } }
-
- launch {
- viewModel.contentDescription.collect { contentDescription ->
- if (contentDescription != null) {
- view.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_YES
- view.contentDescription = contentDescription
- }
- }
- }
-
- launch {
- viewModel.clearAccessibilityOverlayMessageReason.collect { reason ->
- Log.d(
- TAG,
- "clearing content description of UDFPS accessibility overlay " +
- "for reason: $reason",
- )
- view.importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_NO
- view.contentDescription = null
- viewModel.setContentDescription(null)
- }
- }
+ viewModel.visible.collect { visible -> view.isInvisible = !visible }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/view/UdfpsAccessibilityOverlay.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/view/UdfpsAccessibilityOverlay.kt
index 0a2d10d10a40..7be323073692 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/view/UdfpsAccessibilityOverlay.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/view/UdfpsAccessibilityOverlay.kt
@@ -20,10 +20,4 @@ import android.content.Context
import android.view.View
/** Overlay to handle under-fingerprint sensor accessibility events. */
-class UdfpsAccessibilityOverlay(context: Context?) : View(context) {
- init {
- accessibilityLiveRegion = ACCESSIBILITY_LIVE_REGION_ASSERTIVE
- importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_AUTO
- isClickable = false
- }
-}
+class UdfpsAccessibilityOverlay(context: Context?) : View(context)
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
index 22ed6da2e5bf..5c7cd5f55942 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/AlternateBouncerUdfpsAccessibilityOverlayViewModel.kt
@@ -17,7 +17,6 @@
package com.android.systemui.deviceentry.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
-import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -27,23 +26,13 @@ import kotlinx.coroutines.flow.flowOf
class AlternateBouncerUdfpsAccessibilityOverlayViewModel
@Inject
constructor(
- private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
+ udfpsOverlayInteractor: UdfpsOverlayInteractor,
accessibilityInteractor: AccessibilityInteractor,
- udfpsUtils: UdfpsUtils,
) :
UdfpsAccessibilityOverlayViewModel(
udfpsOverlayInteractor,
accessibilityInteractor,
- udfpsUtils,
) {
/** Overlay is always visible if touch exploration is enabled on the alternate bouncer. */
override fun isVisibleWhenTouchExplorationEnabled(): Flow<Boolean> = flowOf(true)
-
- /**
- * Clears the content description to prevent the view from storing stale UDFPS directional
- * guidance messages for accessibility.
- */
- suspend fun clearUdfpsAccessibilityOverlayMessage(reason: String) {
- udfpsOverlayInteractor.clearUdfpsAccessibilityOverlayMessage(reason)
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
index 5c86514775de..b84d65a2b430 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/DeviceEntryUdfpsAccessibilityOverlayViewModel.kt
@@ -17,7 +17,6 @@
package com.android.systemui.deviceentry.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
-import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryForegroundViewModel
@@ -34,12 +33,10 @@ constructor(
accessibilityInteractor: AccessibilityInteractor,
private val deviceEntryIconViewModel: DeviceEntryIconViewModel,
private val deviceEntryFgIconViewModel: DeviceEntryForegroundViewModel,
- udfpsUtils: UdfpsUtils,
) :
UdfpsAccessibilityOverlayViewModel(
udfpsOverlayInteractor,
accessibilityInteractor,
- udfpsUtils,
) {
/** Overlay is only visible if the UDFPS icon is visible on the keyguard. */
override fun isVisibleWhenTouchExplorationEnabled(): Flow<Boolean> =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
index a58f3681555c..fa849bf5e413 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/ui/viewmodel/UdfpsAccessibilityOverlayViewModel.kt
@@ -24,10 +24,7 @@ import com.android.systemui.biometrics.UdfpsUtils
import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams
import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
@@ -35,17 +32,8 @@ import kotlinx.coroutines.flow.flowOf
abstract class UdfpsAccessibilityOverlayViewModel(
udfpsOverlayInteractor: UdfpsOverlayInteractor,
accessibilityInteractor: AccessibilityInteractor,
- private val udfpsUtils: UdfpsUtils,
) {
- /** Indicates the reason for clearing the UDFPS accessibility overlay content description */
- val clearAccessibilityOverlayMessageReason: SharedFlow<String?> =
- udfpsOverlayInteractor.clearAccessibilityOverlayMessageReason
-
- private val _contentDescription: MutableStateFlow<CharSequence?> = MutableStateFlow(null)
-
- /** Content description of the UDFPS accessibility overlay */
- val contentDescription: Flow<CharSequence?> = _contentDescription.asStateFlow()
-
+ private val udfpsUtils = UdfpsUtils()
private val udfpsOverlayParams: StateFlow<UdfpsOverlayParams> =
udfpsOverlayInteractor.udfpsOverlayParams
@@ -58,10 +46,6 @@ abstract class UdfpsAccessibilityOverlayViewModel(
}
}
- fun setContentDescription(contentDescription: CharSequence?) {
- _contentDescription.value = contentDescription
- }
-
abstract fun isVisibleWhenTouchExplorationEnabled(): Flow<Boolean>
/** Give directional feedback to help the user authenticate with UDFPS. */
@@ -72,7 +56,7 @@ abstract class UdfpsAccessibilityOverlayViewModel(
event.getPointerId(0),
event,
overlayParams, /* rotateToPortrait */
- false,
+ false
)
if (
@@ -80,7 +64,7 @@ abstract class UdfpsAccessibilityOverlayViewModel(
event.getPointerId(0),
event,
overlayParams,
- /* rotateTouchToPortrait */ false,
+ /* rotateTouchToPortrait */ false
)
) {
// view only receives motionEvents when [visible] which requires touchExplorationEnabled
@@ -91,11 +75,10 @@ abstract class UdfpsAccessibilityOverlayViewModel(
scaledTouch.x,
scaledTouch.y,
overlayParams,
- /* touchRotatedToPortrait */ false,
+ /* touchRotatedToPortrait */ false
)
-
if (announceStr != null) {
- _contentDescription.value = announceStr
+ v.announceForAccessibility(announceStr)
}
}
// always let the motion events go through to underlying views
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt
index c7c54e95a63b..824e0228adca 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AccessibilityActionsViewBinder.kt
@@ -19,19 +19,21 @@ package com.android.systemui.keyguard.ui.binder
import android.os.Bundle
import android.view.View
-import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
import android.view.accessibility.AccessibilityNodeInfo
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
-import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.keyguard.ui.viewmodel.AccessibilityActionsViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import kotlinx.coroutines.DisposableHandle
+import com.android.app.tracing.coroutines.launchTraced as launch
/** View binder for accessibility actions placeholder on keyguard. */
object AccessibilityActionsViewBinder {
- fun bind(view: View, viewModel: AccessibilityActionsViewModel): DisposableHandle {
+ fun bind(
+ view: View,
+ viewModel: AccessibilityActionsViewModel,
+ ): DisposableHandle {
val disposableHandle =
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
@@ -58,10 +60,9 @@ object AccessibilityActionsViewBinder {
object : View.AccessibilityDelegate() {
override fun onInitializeAccessibilityNodeInfo(
host: View,
- info: AccessibilityNodeInfo,
+ info: AccessibilityNodeInfo
) {
super.onInitializeAccessibilityNodeInfo(host, info)
-
// Add custom actions
if (canOpenGlanceableHub) {
val action =
@@ -79,7 +80,7 @@ object AccessibilityActionsViewBinder {
override fun performAccessibilityAction(
host: View,
action: Int,
- args: Bundle?,
+ args: Bundle?
): Boolean {
return if (
action == R.id.accessibility_action_open_communal_hub
@@ -88,20 +89,6 @@ object AccessibilityActionsViewBinder {
true
} else super.performAccessibilityAction(host, action, args)
}
-
- override fun sendAccessibilityEvent(
- host: View,
- eventType: Int,
- ) {
- if (eventType == TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
- launch {
- viewModel.clearUdfpsAccessibilityOverlayMessage(
- "eventType $eventType on view $host"
- )
- }
- }
- super.sendAccessibilityEvent(host, eventType)
- }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
index 00d41d0a7aa7..b8b032719ef8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt
@@ -19,10 +19,8 @@ package com.android.systemui.keyguard.ui.binder
import android.util.Log
import android.view.LayoutInflater
import android.view.View
-import android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO
import android.view.ViewGroup
import android.view.WindowManager
-import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
import android.window.OnBackInvokedCallback
import android.window.OnBackInvokedDispatcher
import androidx.constraintlayout.widget.ConstraintLayout
@@ -49,7 +47,6 @@ import com.android.systemui.scrim.ScrimView
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.launch
/**
* When necessary, adds the alternate bouncer window above most other windows (including the
@@ -238,25 +235,6 @@ constructor(
udfpsA11yOverlay =
UdfpsAccessibilityOverlay(view.context).apply {
id = udfpsA11yOverlayViewId
- importantForAccessibility = IMPORTANT_FOR_ACCESSIBILITY_AUTO
- }
- udfpsA11yOverlay.accessibilityDelegate =
- object : View.AccessibilityDelegate() {
- override fun sendAccessibilityEvent(
- host: View,
- eventType: Int,
- ) {
- if (eventType == TYPE_VIEW_HOVER_EXIT) {
- applicationScope.launch {
- udfpsA11yOverlayViewModel
- .get()
- .clearUdfpsAccessibilityOverlayMessage(
- "$eventType on view $host"
- )
- }
- }
- super.sendAccessibilityEvent(host, eventType)
- }
}
view.addView(udfpsA11yOverlay)
UdfpsAccessibilityOverlayBinder.bind(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
index 678872d0d64d..38f5d3e76c7c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModel.kt
@@ -16,7 +16,6 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.communal.shared.model.CommunalScenes
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -34,8 +33,7 @@ class AccessibilityActionsViewModel
constructor(
private val communalInteractor: CommunalInteractor,
keyguardInteractor: KeyguardInteractor,
- val keyguardTransitionInteractor: KeyguardTransitionInteractor,
- private val udfpsOverlayInteractor: UdfpsOverlayInteractor,
+ keyguardTransitionInteractor: KeyguardTransitionInteractor,
) {
val isCommunalAvailable = communalInteractor.isCommunalAvailable
@@ -46,7 +44,7 @@ constructor(
keyguardTransitionInteractor.transitionValue(KeyguardState.LOCKSCREEN).map {
it == 1f
},
- keyguardInteractor.statusBarState,
+ keyguardInteractor.statusBarState
) { transitionFinishedOnLockscreen, statusBarState ->
transitionFinishedOnLockscreen && statusBarState == StatusBarState.KEYGUARD
}
@@ -57,12 +55,4 @@ constructor(
newScene = CommunalScenes.Communal,
loggingReason = "accessibility",
)
-
- /**
- * Clears the content description to prevent the view from storing stale UDFPS directional
- * guidance messages for accessibility.
- */
- suspend fun clearUdfpsAccessibilityOverlayMessage(reason: String) {
- udfpsOverlayInteractor.clearUdfpsAccessibilityOverlayMessage(reason)
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
index 515a10792c02..2c70249bcb06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/ui/viewmodel/PromptViewModelTest.kt
@@ -1472,7 +1472,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
whenever(kosmos.udfpsUtils.onTouchOutsideOfSensorArea(any(), any(), any(), any(), any()))
.thenReturn("Direction")
- kosmos.promptViewModel.onUpdateAccessibilityHint(
+ kosmos.promptViewModel.onAnnounceAccessibilityHint(
obtainMotionEvent(MotionEvent.ACTION_HOVER_ENTER),
true,
)
@@ -1482,14 +1482,6 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
} else {
assertThat(hint.isNullOrBlank()).isTrue()
}
-
- kosmos.promptViewModel.onClearUdfpsGuidanceHint(true)
-
- if (testCase.modalities.hasUdfps) {
- assertThat(hint).isNull()
- } else {
- assertThat(hint.isNullOrBlank()).isTrue()
- }
}
@Test
@@ -1505,7 +1497,7 @@ internal class PromptViewModelTest(private val testCase: TestCase) : SysuiTestCa
whenever(kosmos.udfpsUtils.onTouchOutsideOfSensorArea(any(), any(), any(), any(), any()))
.thenReturn("Direction")
- kosmos.promptViewModel.onUpdateAccessibilityHint(
+ kosmos.promptViewModel.onAnnounceAccessibilityHint(
obtainMotionEvent(MotionEvent.ACTION_HOVER_ENTER),
true,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/ui/viewmodel/UdfpsAccessibilityOverlayViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/ui/viewmodel/UdfpsAccessibilityOverlayViewModelKosmos.kt
index 2a3bd335bf98..2a46437ed33e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/ui/viewmodel/UdfpsAccessibilityOverlayViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/ui/viewmodel/UdfpsAccessibilityOverlayViewModelKosmos.kt
@@ -18,8 +18,6 @@ package com.android.systemui.deviceentry.data.ui.viewmodel
import com.android.systemui.accessibility.domain.interactor.accessibilityInteractor
import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor
-import com.android.systemui.biometrics.udfpsUtils
-import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
import com.android.systemui.deviceentry.ui.viewmodel.DeviceEntryUdfpsAccessibilityOverlayViewModel
import com.android.systemui.keyguard.ui.viewmodel.deviceEntryForegroundIconViewModel
import com.android.systemui.keyguard.ui.viewmodel.deviceEntryIconViewModel
@@ -32,15 +30,5 @@ val Kosmos.deviceEntryUdfpsAccessibilityOverlayViewModel by
accessibilityInteractor = accessibilityInteractor,
deviceEntryIconViewModel = deviceEntryIconViewModel,
deviceEntryFgIconViewModel = deviceEntryForegroundIconViewModel,
- udfpsUtils = udfpsUtils,
- )
- }
-
-val Kosmos.alternateBouncerUdfpsAccessibilityOverlayViewModel by
- Kosmos.Fixture {
- AlternateBouncerUdfpsAccessibilityOverlayViewModel(
- udfpsOverlayInteractor = udfpsOverlayInteractor,
- accessibilityInteractor = accessibilityInteractor,
- udfpsUtils = udfpsUtils,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt
index be5431c3d0d7..bc35dc8052ec 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AccessibilityActionsViewModelKosmos.kt
@@ -16,7 +16,6 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -28,6 +27,5 @@ val Kosmos.accessibilityActionsViewModelKosmos by Fixture {
communalInteractor = communalInteractor,
keyguardTransitionInteractor = keyguardTransitionInteractor,
keyguardInteractor = keyguardInteractor,
- udfpsOverlayInteractor = udfpsOverlayInteractor,
)
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cc5de3cc01ed..80a120ffbbc1 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -638,7 +638,7 @@ public class NotificationManagerService extends SystemService {
static final long NOTIFICATION_MAX_AGE_AT_POST = Duration.ofDays(14).toMillis();
// Minium number of sparse groups for a package before autogrouping them
- private static final int AUTOGROUP_SPARSE_GROUPS_AT_COUNT = 3;
+ private static final int AUTOGROUP_SPARSE_GROUPS_AT_COUNT = 6;
private static final Duration ZEN_BROADCAST_DELAY = Duration.ofMillis(250);