diff options
author | 2025-04-04 21:47:16 -0700 | |
---|---|---|
committer | 2025-04-04 21:47:16 -0700 | |
commit | 92c687d0c0abf5c8c76aaf33476dbe3f1384e677 (patch) | |
tree | 8e5f5865f58a7185d8663158759ed57845702947 | |
parent | a5f7ff521d9e05a6a1b42eaf2ecee60ad0033ff5 (diff) | |
parent | cfa6ede1c3116cd3ac77470ec67569ecfc938340 (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
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); |