summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Beverly Tai <beverlyt@google.com> 2024-06-20 19:38:46 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-06-20 19:38:46 +0000
commitb20088f23654f883876706b14d40cf4c1e74b2f0 (patch)
tree65c20c601e23367a5c10f5abbf95be2b65f03c02
parent2d71ada13e77c5ee02fec79023bc7bcf75496c5d (diff)
parent73ca0f6cfa3ef941d39133ae401b6d84a6d5a59d (diff)
Merge "Ensure alt bouncer view is removed" into main
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt30
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt142
-rw-r--r--packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt2
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt81
6 files changed, 274 insertions, 20 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
index 303548131788..68cfa28dabd7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorTest.kt
@@ -29,7 +29,6 @@ import com.android.systemui.biometrics.data.repository.fingerprintPropertyReposi
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
-import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
@@ -223,23 +222,14 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
}
private fun givenAlternateBouncerSupported() {
- if (DeviceEntryUdfpsRefactor.isEnabled) {
- kosmos.fingerprintPropertyRepository.supportsUdfps()
- } else {
- kosmos.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true)
- }
+ kosmos.givenAlternateBouncerSupported()
}
private fun givenCanShowAlternateBouncer() {
- givenAlternateBouncerSupported()
- kosmos.keyguardBouncerRepository.setPrimaryShow(false)
- kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
- kosmos.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
- whenever(kosmos.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
- whenever(kosmos.keyguardStateController.isUnlocked).thenReturn(false)
+ kosmos.givenCanShowAlternateBouncer()
}
private fun givenCannotShowAlternateBouncer() {
- kosmos.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+ kosmos.givenCannotShowAlternateBouncer()
}
}
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 f8063c92124d..db33acb93dc6 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
@@ -115,13 +115,28 @@ constructor(
}
private fun removeViewFromWindowManager() {
- if (alternateBouncerView == null || !alternateBouncerView!!.isAttachedToWindow) {
- return
- }
+ alternateBouncerView?.let {
+ alternateBouncerView = null
+ if (it.isAttachedToWindow) {
+ it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
+ Log.d(TAG, "Removing alternate bouncer view immediately")
+ windowManager.get().removeView(it)
+ } else {
+ // once the view is attached, remove it
+ it.addOnAttachStateChangeListener(
+ object : View.OnAttachStateChangeListener {
+ override fun onViewAttachedToWindow(view: View) {
+ it.removeOnAttachStateChangeListener(this)
+ it.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
+ Log.d(TAG, "Removing alternate bouncer view on attached")
+ windowManager.get().removeView(it)
+ }
- windowManager.get().removeView(alternateBouncerView)
- alternateBouncerView!!.removeOnAttachStateChangeListener(onAttachAddBackGestureHandler)
- alternateBouncerView = null
+ override fun onViewDetachedFromWindow(view: View) {}
+ }
+ )
+ }
+ }
}
private val onAttachAddBackGestureHandler =
@@ -151,7 +166,7 @@ constructor(
}
private fun addViewToWindowManager() {
- if (alternateBouncerView?.isAttachedToWindow == true) {
+ if (alternateBouncerView != null) {
return
}
@@ -159,6 +174,7 @@ constructor(
layoutInflater.get().inflate(R.layout.alternate_bouncer, null, false)
as ConstraintLayout
+ Log.d(TAG, "Adding alternate bouncer view")
windowManager.get().addView(alternateBouncerView, layoutParams)
alternateBouncerView!!.addOnAttachStateChangeListener(onAttachAddBackGestureHandler)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt
new file mode 100644
index 000000000000..c4eabd84e031
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderTest.kt
@@ -0,0 +1,142 @@
+/*
+ * 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.ui.binder
+
+import android.platform.test.annotations.EnableFlags
+import android.testing.TestableLooper
+import android.view.View
+import android.view.layoutInflater
+import android.view.mockedLayoutInflater
+import android.view.windowManager
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.bouncer.domain.interactor.givenCanShowAlternateBouncer
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.testKosmos
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.verify
+import org.mockito.kotlin.isNull
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class AlternateBouncerViewBinderTest : SysuiTestCase() {
+ private val kosmos = testKosmos()
+ private val testScope = kosmos.testScope
+
+ private val mockedAltBouncerView =
+ spy(kosmos.layoutInflater.inflate(R.layout.alternate_bouncer, null, false))
+
+ @Before
+ fun setup() {
+ whenever(
+ kosmos.mockedLayoutInflater.inflate(
+ eq(R.layout.alternate_bouncer),
+ isNull(),
+ anyBoolean()
+ )
+ )
+ .thenReturn(mockedAltBouncerView)
+ kosmos.alternateBouncerViewBinder.start()
+ }
+
+ @Test
+ @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+ fun addViewToWindowManager() {
+ testScope.runTest {
+ kosmos.givenCanShowAlternateBouncer()
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope,
+ )
+ verify(kosmos.windowManager).addView(any(), any())
+ }
+ }
+
+ @Test
+ @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+ fun viewRemovedImmediatelyIfAlreadyAttachedToWindow() {
+ testScope.runTest {
+ kosmos.givenCanShowAlternateBouncer()
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope,
+ )
+ verify(kosmos.windowManager).addView(any(), any())
+ whenever(mockedAltBouncerView.isAttachedToWindow).thenReturn(true)
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.LOCKSCREEN,
+ testScope,
+ )
+ verify(kosmos.windowManager).removeView(any())
+ }
+ }
+
+ @Test
+ @EnableFlags(FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
+ fun viewNotRemovedUntilAttachedToWindow() {
+ testScope.runTest {
+ kosmos.givenCanShowAlternateBouncer()
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.ALTERNATE_BOUNCER,
+ testScope,
+ )
+ verify(kosmos.windowManager).addView(any(), any())
+
+ kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.LOCKSCREEN,
+ testScope,
+ )
+
+ verify(kosmos.windowManager, never()).removeView(any())
+ givenAltBouncerViewAttachedToWindow()
+ verify(kosmos.windowManager).removeView(any())
+ }
+ }
+
+ private fun givenAltBouncerViewAttachedToWindow() {
+ val attachStateChangeListenerCaptor =
+ ArgumentCaptor.forClass(View.OnAttachStateChangeListener::class.java)
+ verify(mockedAltBouncerView, atLeastOnce())
+ .addOnAttachStateChangeListener(attachStateChangeListenerCaptor.capture())
+ attachStateChangeListenerCaptor.allValues.onEach {
+ it.onViewAttachedToWindow(mockedAltBouncerView)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
index 21dea6b1cbd0..2ee289bd026d 100644
--- a/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/android/view/LayoutInflaterKosmos.kt
@@ -18,6 +18,8 @@ package android.view
import android.content.applicationContext
import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.util.mockito.mock
var Kosmos.layoutInflater: LayoutInflater by
Kosmos.Fixture { LayoutInflater.from(applicationContext) }
+var Kosmos.mockedLayoutInflater: LayoutInflater by Kosmos.Fixture { mock<LayoutInflater>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
index f75cdd4d3bbc..9236bd2a2a8b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/domain/interactor/AlternateBouncerInteractorKosmos.kt
@@ -20,6 +20,7 @@ import com.android.keyguard.keyguardUpdateMonitor
import com.android.systemui.biometrics.data.repository.fingerprintPropertyRepository
import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
+import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
@@ -28,6 +29,7 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.policy.keyguardStateController
+import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.systemClock
val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by
@@ -47,3 +49,24 @@ val Kosmos.alternateBouncerInteractor: AlternateBouncerInteractor by
sceneInteractor = { sceneInteractor },
)
}
+
+fun Kosmos.givenCanShowAlternateBouncer() {
+ this.givenAlternateBouncerSupported()
+ this.keyguardBouncerRepository.setPrimaryShow(false)
+ this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
+ this.biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
+ whenever(this.keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
+ whenever(this.keyguardStateController.isUnlocked).thenReturn(false)
+}
+
+fun Kosmos.givenAlternateBouncerSupported() {
+ if (DeviceEntryUdfpsRefactor.isEnabled) {
+ this.fingerprintPropertyRepository.supportsUdfps()
+ } else {
+ this.keyguardBouncerRepository.setAlternateBouncerUIAvailable(true)
+ }
+}
+
+fun Kosmos.givenCannotShowAlternateBouncer() {
+ this.biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
new file mode 100644
index 000000000000..6eb8a4925082
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinderKosmos.kt
@@ -0,0 +1,81 @@
+/*
+ * 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.ui.binder
+
+import android.content.applicationContext
+import android.view.layoutInflater
+import android.view.mockedLayoutInflater
+import android.view.windowManager
+import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor
+import com.android.systemui.biometrics.domain.interactor.udfpsOverlayInteractor
+import com.android.systemui.common.ui.domain.interactor.configurationInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryUdfpsInteractor
+import com.android.systemui.deviceentry.ui.viewmodel.AlternateBouncerUdfpsAccessibilityOverlayViewModel
+import com.android.systemui.keyguard.ui.SwipeUpAnywhereGestureHandler
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.DeviceEntryBackgroundViewModel
+import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerViewModel
+import com.android.systemui.keyguard.ui.viewmodel.alternateBouncerWindowViewModel
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.statusbar.gesture.TapGestureDetector
+import com.android.systemui.util.mockito.mock
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+@OptIn(ExperimentalCoroutinesApi::class)
+val Kosmos.alternateBouncerViewBinder by
+ Kosmos.Fixture {
+ AlternateBouncerViewBinder(
+ applicationScope = applicationCoroutineScope,
+ alternateBouncerWindowViewModel = { alternateBouncerWindowViewModel },
+ alternateBouncerDependencies = { alternateBouncerDependencies },
+ windowManager = { windowManager },
+ layoutInflater = { mockedLayoutInflater },
+ )
+ }
+
+private val Kosmos.alternateBouncerDependencies by
+ Kosmos.Fixture {
+ AlternateBouncerDependencies(
+ viewModel = mock<AlternateBouncerViewModel>(),
+ swipeUpAnywhereGestureHandler = mock<SwipeUpAnywhereGestureHandler>(),
+ tapGestureDetector = mock<TapGestureDetector>(),
+ udfpsIconViewModel = alternateBouncerUdfpsIconViewModel,
+ udfpsAccessibilityOverlayViewModel = {
+ mock<AlternateBouncerUdfpsAccessibilityOverlayViewModel>()
+ },
+ messageAreaViewModel = mock<AlternateBouncerMessageAreaViewModel>(),
+ powerInteractor = powerInteractor,
+ )
+ }
+
+private val Kosmos.alternateBouncerUdfpsIconViewModel by
+ Kosmos.Fixture {
+ AlternateBouncerUdfpsIconViewModel(
+ context = applicationContext,
+ configurationInteractor = configurationInteractor,
+ deviceEntryUdfpsInteractor = deviceEntryUdfpsInteractor,
+ deviceEntryBackgroundViewModel = mock<DeviceEntryBackgroundViewModel>(),
+ fingerprintPropertyInteractor = fingerprintPropertyInteractor,
+ udfpsOverlayInteractor = udfpsOverlayInteractor,
+ alternateBouncerViewModel = alternateBouncerViewModel,
+ )
+ }