summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Beverly <beverlyt@google.com> 2024-04-22 17:21:44 +0000
committer Beverly <beverlyt@google.com> 2024-04-22 18:36:52 +0000
commit4d351aa2cde6b200673bb49b103ad68e7df61069 (patch)
tree48dd01d95e36c9d593af69a198879df0c1ae5a5f
parenta8c826925c9e2db3b8a242cc88bbb6997b87cb85 (diff)
Add additional support for FromAlternateBouncer transitions
ALTERNATE_BOUNCER => GONE: When the alternate bouncer is showing over an occluding app, isKeyguardGoingAway does not update to true. Therefore, we need to manually check if biometric authentication has been handling to trigger the ALT_BOUNCER => GONE transition when the alt bouncer is showing over an occluding app. ALTERNATE_BOUNCER => OCCLUDED When the alternate bouncer is showing over an occluding app, it's possible to navigate back to the occluding application. Add support for this transition in the AlternateBouncerTransitionInteractor Test: Launch camera app over a locked lockscreen. Press gallery icon to view photos. Observe alternate bouncer. Authenticate with FP. Observe alternate bouncer animates away. Test: atest FromAlternateBouncerInteractorTest Test: Launch camera app over a locked lockscreen. Press gallery icon to view photos. Observe alternate bouncer. Navigate back. Observe KeyguardTransition log back to OCCLUDED Fixes: 336305546 Flag: None Change-Id: Iadbbf8c28a350047a94797c18cbca2f4f4ddd833
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt144
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt4
3 files changed, 175 insertions, 6 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index dfe56c839283..39aa6152f983 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -32,14 +33,21 @@ import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.emptyFlow
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
+@ExperimentalCoroutinesApi
@SysUISingleton
class FromAlternateBouncerTransitionInteractor
@Inject
@@ -53,6 +61,7 @@ constructor(
private val communalInteractor: CommunalInteractor,
powerInteractor: PowerInteractor,
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
+ private val primaryBouncerInteractor: PrimaryBouncerInteractor,
) :
TransitionInteractor(
fromState = KeyguardState.ALTERNATE_BOUNCER,
@@ -102,13 +111,14 @@ constructor(
keyguardInteractor.primaryBouncerShowing,
powerInteractor.isAwake,
keyguardInteractor.isAodAvailable,
- communalInteractor.isIdleOnCommunal
+ communalInteractor.isIdleOnCommunal,
+ keyguardInteractor.isKeyguardOccluded,
)
.filterRelevantKeyguardStateAnd {
(isAlternateBouncerShowing, isPrimaryBouncerShowing, _, _, _) ->
!isAlternateBouncerShowing && !isPrimaryBouncerShowing
}
- .collect { (_, _, isAwake, isAodAvailable, isIdleOnCommunal) ->
+ .collect { (_, _, isAwake, isAodAvailable, isIdleOnCommunal, isOccluded) ->
val to =
if (!isAwake) {
if (isAodAvailable) {
@@ -119,6 +129,8 @@ constructor(
} else {
if (isIdleOnCommunal) {
KeyguardState.GLANCEABLE_HUB
+ } else if (isOccluded) {
+ KeyguardState.OCCLUDED
} else {
KeyguardState.LOCKSCREEN
}
@@ -135,10 +147,19 @@ constructor(
}
scope.launch {
- keyguardInteractor.isKeyguardGoingAway
- .sampleUtil(finishedKeyguardState, ::Pair)
- .collect { (isKeyguardGoingAway, keyguardState) ->
- if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
+ merge(
+ keyguardInteractor.isKeyguardGoingAway.filter { it }.map {}, // map to Unit
+ keyguardInteractor.isKeyguardOccluded.flatMapLatest { keyguardOccluded ->
+ if (keyguardOccluded) {
+ primaryBouncerInteractor.keyguardAuthenticatedBiometricsHandled
+ } else {
+ emptyFlow()
+ }
+ }
+ )
+ .sampleUtil(finishedKeyguardState)
+ .collect { keyguardState ->
+ if (keyguardState == KeyguardState.ALTERNATE_BOUNCER) {
startTransitionTo(KeyguardState.GONE)
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
new file mode 100644
index 000000000000..52bdf0eeb1c6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorTest.kt
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.domain.interactor
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.util.KeyguardTransitionRepositorySpySubject.Companion.assertThat
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.shared.model.WakeSleepReason
+import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.testKosmos
+import kotlin.test.Test
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.mockito.Mockito
+import org.mockito.Mockito.reset
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class FromAlternateBouncerTransitionInteractorTest : SysuiTestCase() {
+ private val kosmos =
+ testKosmos().apply {
+ this.fakeKeyguardTransitionRepository = Mockito.spy(FakeKeyguardTransitionRepository())
+ }
+ private val testScope = kosmos.testScope
+ private lateinit var underTest: FromAlternateBouncerTransitionInteractor
+ private lateinit var transitionRepository: FakeKeyguardTransitionRepository
+
+ @Before
+ fun setup() {
+ transitionRepository = kosmos.fakeKeyguardTransitionRepository
+ underTest = kosmos.fromAlternateBouncerTransitionInteractor
+ underTest.start()
+ }
+
+ @Test
+ fun transitionToGone_keyguardOccluded_biometricAuthenticated() =
+ testScope.runTest {
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope
+ )
+ reset(transitionRepository)
+
+ kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
+ runCurrent()
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null)
+ runCurrent()
+
+ assertThat(transitionRepository)
+ .startedTransition(from = KeyguardState.ALTERNATE_BOUNCER, to = KeyguardState.GONE)
+ }
+
+ @Test
+ fun noTransition_keyguardNotOccluded_biometricAuthenticated() =
+ testScope.runTest {
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope
+ )
+ reset(transitionRepository)
+
+ kosmos.fakeKeyguardRepository.setKeyguardOccluded(false)
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(true)
+ runCurrent()
+ kosmos.fakeKeyguardBouncerRepository.setKeyguardAuthenticatedBiometrics(null)
+ runCurrent()
+
+ assertThat(transitionRepository).noTransitionsStarted()
+ }
+
+ @Test
+ fun transitionToOccluded() =
+ testScope.runTest {
+ kosmos.fakePowerRepository.updateWakefulness(
+ WakefulnessState.AWAKE,
+ WakeSleepReason.POWER_BUTTON,
+ WakeSleepReason.POWER_BUTTON,
+ false,
+ )
+ kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
+ kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(true)
+ transitionRepository.sendTransitionSteps(
+ from = KeyguardState.OCCLUDED,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope
+ )
+ reset(transitionRepository)
+
+ kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(false)
+ runCurrent()
+ testScope.testScheduler.advanceTimeBy(200) // advance past delay
+
+ assertThat(transitionRepository)
+ .startedTransition(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.OCCLUDED
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
index 530cbedbdd0c..78a419f92495 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractorKosmos.kt
@@ -16,6 +16,7 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
import com.android.systemui.kosmos.Kosmos
@@ -23,7 +24,9 @@ import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+@ExperimentalCoroutinesApi
val Kosmos.fromAlternateBouncerTransitionInteractor by
Kosmos.Fixture {
FromAlternateBouncerTransitionInteractor(
@@ -36,5 +39,6 @@ val Kosmos.fromAlternateBouncerTransitionInteractor by
communalInteractor = communalInteractor,
powerInteractor = powerInteractor,
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
+ primaryBouncerInteractor = primaryBouncerInteractor,
)
}