Merge "Tie KeyguardStateCallbackInteractor state to WmLockscreenVisibility + add dismiss callback notifications." into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractorTest.kt
new file mode 100644
index 0000000..2558d58
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractorTest.kt
@@ -0,0 +1,139 @@
+/*
+ * 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 android.platform.test.annotations.EnableFlags
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.policy.IKeyguardDismissCallback
+import com.android.internal.policy.IKeyguardStateCallback
+import com.android.keyguard.trustManager
+import com.android.systemui.Flags
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.dismissCallbackRegistry
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.statusbar.domain.interactor.keyguardStateCallbackInteractor
+import com.android.systemui.testKosmos
+import com.android.systemui.util.time.FakeSystemClock
+import com.android.systemui.util.time.fakeSystemClock
+import kotlin.test.Test
+import kotlinx.coroutines.test.currentTime
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mockito
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.anyInt
+import org.mockito.kotlin.atLeast
+import org.mockito.kotlin.atLeastOnce
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class KeyguardStateCallbackInteractorTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+
+    private lateinit var underTest: KeyguardStateCallbackInteractor
+    private lateinit var callback: IKeyguardStateCallback
+    private lateinit var systemClock: FakeSystemClock
+
+    @Before
+    fun setUp() {
+        systemClock = kosmos.fakeSystemClock
+        systemClock.setCurrentTimeMillis(testScope.currentTime)
+
+        underTest = kosmos.keyguardStateCallbackInteractor
+        underTest.start()
+
+        callback = mock<IKeyguardStateCallback>()
+    }
+
+    @Test
+    fun test_addCallback_passesInitialValues() =
+        testScope.runTest {
+            underTest.addCallback(callback)
+
+            verify(callback).onShowingStateChanged(anyBoolean(), anyInt())
+            verify(callback).onInputRestrictedStateChanged(anyBoolean())
+            verify(callback).onTrustedChanged(anyBoolean())
+            verify(callback).onSimSecureStateChanged(anyBoolean())
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
+    fun test_lockscreenVisibility_notifyDismissSucceeded_ifNotVisible() =
+        testScope.runTest {
+            underTest.addCallback(callback)
+
+            val dismissCallback = mock<IKeyguardDismissCallback>()
+            kosmos.dismissCallbackRegistry.addCallback(dismissCallback)
+            runCurrent()
+
+            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.GONE,
+                testScope = testScope,
+            )
+
+            systemClock.advanceTime(1) // Required for DismissCallbackRegistry's bgExecutor
+            verify(dismissCallback).onDismissSucceeded()
+
+            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.GONE,
+                to = KeyguardState.LOCKSCREEN,
+                testScope = testScope,
+            )
+
+            Mockito.verifyNoMoreInteractions(dismissCallback)
+        }
+
+    @Test
+    @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
+    fun test_lockscreenVisibility_reportsKeyguardShowingChanged() =
+        testScope.runTest {
+            underTest.addCallback(callback)
+
+            Mockito.clearInvocations(callback)
+            Mockito.clearInvocations(kosmos.trustManager)
+
+            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.LOCKSCREEN,
+                to = KeyguardState.GONE,
+                testScope = testScope,
+            )
+            runCurrent()
+
+            verify(callback, atLeastOnce()).onShowingStateChanged(eq(false), anyInt())
+            verify(kosmos.trustManager, atLeastOnce()).reportKeyguardShowingChanged()
+
+            kosmos.fakeKeyguardTransitionRepository.sendTransitionSteps(
+                from = KeyguardState.GONE,
+                to = KeyguardState.LOCKSCREEN,
+                testScope = testScope,
+            )
+
+            verify(callback, atLeastOnce()).onShowingStateChanged(eq(true), anyInt())
+            verify(kosmos.trustManager, atLeast(2)).reportKeyguardShowingChanged()
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ba23eb3..0a38ce0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -3314,7 +3314,11 @@
 
         setShowingLocked(false, "onKeyguardExitFinished: " + reason);
         mWakeAndUnlocking = false;
-        mDismissCallbackRegistry.notifyDismissSucceeded();
+
+        if (!KeyguardWmStateRefactor.isEnabled()) {
+            mDismissCallbackRegistry.notifyDismissSucceeded();
+        }
+
         resetKeyguardDonePendingLocked();
         mHideAnimationRun = false;
         adjustStatusBarLocked();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
index 4457f1d..9b9bdd1 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractor.kt
@@ -23,12 +23,10 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.DismissCallbackRegistry
-import com.android.systemui.keyguard.KeyguardWmStateRefactor
 import com.android.systemui.keyguard.data.repository.KeyguardRepository
 import com.android.systemui.keyguard.data.repository.TrustRepository
 import com.android.systemui.keyguard.shared.model.DismissAction
 import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.power.domain.interactor.PowerInteractor
 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
 import com.android.systemui.util.kotlin.Utils.Companion.toQuad
@@ -37,7 +35,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.collect
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
@@ -59,7 +56,6 @@
     trustRepository: TrustRepository,
     alternateBouncerInteractor: AlternateBouncerInteractor,
     powerInteractor: PowerInteractor,
-    keyguardTransitionInteractor: KeyguardTransitionInteractor,
 ) {
     /*
      * Updates when a biometric has authenticated the device and is requesting to dismiss
@@ -165,14 +161,4 @@
             }
         }
     }
-
-    init {
-        if (KeyguardWmStateRefactor.isEnabled) {
-            scope.launch {
-                keyguardTransitionInteractor.currentKeyguardState
-                    .filter { it == KeyguardState.GONE }
-                    .collect { dismissCallbackRegistry.notifyDismissSucceeded() }
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
index 7fd348b..6fe4ff5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardStateCallbackInteractor.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.keyguard.domain.interactor
 
+import android.app.trust.TrustManager
 import android.os.DeadObjectException
 import android.os.RemoteException
 import com.android.internal.policy.IKeyguardStateCallback
@@ -24,6 +25,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyguard.DismissCallbackRegistry
 import com.android.systemui.keyguard.KeyguardWmStateRefactor
 import com.android.systemui.keyguard.shared.model.KeyguardState
 import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -32,7 +34,6 @@
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.withContext
 
@@ -53,6 +54,9 @@
     private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
     private val trustInteractor: TrustInteractor,
     private val simBouncerInteractor: SimBouncerInteractor,
+    private val dismissCallbackRegistry: DismissCallbackRegistry,
+    private val wmLockscreenVisibilityInteractor: WindowManagerLockscreenVisibilityInteractor,
+    private val trustManager: TrustManager,
 ) : CoreStartable {
     private val callbacks = mutableListOf<IKeyguardStateCallback>()
 
@@ -62,28 +66,31 @@
         }
 
         applicationScope.launch {
-            combine(
-                    selectedUserInteractor.selectedUser,
-                    keyguardTransitionInteractor.currentKeyguardState,
-                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
-                    ::Triple,
-                )
-                .collectLatest { (selectedUser, _, _) ->
-                    val iterator = callbacks.iterator()
-                    withContext(backgroundDispatcher) {
-                        while (iterator.hasNext()) {
-                            val callback = iterator.next()
-                            try {
-                                callback.onShowingStateChanged(!isIdleInGone(), selectedUser)
-                                callback.onInputRestrictedStateChanged(!isIdleInGone())
-                            } catch (e: RemoteException) {
-                                if (e is DeadObjectException) {
-                                    iterator.remove()
-                                }
+            wmLockscreenVisibilityInteractor.lockscreenVisibility.collectLatest { visible ->
+                val iterator = callbacks.iterator()
+                withContext(backgroundDispatcher) {
+                    while (iterator.hasNext()) {
+                        val callback = iterator.next()
+                        try {
+                            callback.onShowingStateChanged(
+                                visible,
+                                selectedUserInteractor.getSelectedUserId(),
+                            )
+                            callback.onInputRestrictedStateChanged(visible)
+
+                            trustManager.reportKeyguardShowingChanged()
+
+                            if (!visible) {
+                                dismissCallbackRegistry.notifyDismissSucceeded()
+                            }
+                        } catch (e: RemoteException) {
+                            if (e is DeadObjectException) {
+                                iterator.remove()
                             }
                         }
                     }
                 }
+            }
         }
 
         applicationScope.launch {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
index 52416ba..ace1157 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissInteractorKosmos.kt
@@ -41,6 +41,5 @@
             trustRepository = trustRepository,
             alternateBouncerInteractor = alternateBouncerInteractor,
             powerInteractor = powerInteractor,
-            keyguardTransitionInteractor = keyguardTransitionInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStateCallbackInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStateCallbackInteractorKosmos.kt
new file mode 100644
index 0000000..58dd522
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/KeyguardStateCallbackInteractorKosmos.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.statusbar.domain.interactor
+
+import com.android.keyguard.trustManager
+import com.android.systemui.bouncer.domain.interactor.simBouncerInteractor
+import com.android.systemui.keyguard.dismissCallbackRegistry
+import com.android.systemui.keyguard.domain.interactor.KeyguardStateCallbackInteractor
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.domain.interactor.trustInteractor
+import com.android.systemui.keyguard.domain.interactor.windowManagerLockscreenVisibilityInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.user.domain.interactor.selectedUserInteractor
+
+val Kosmos.keyguardStateCallbackInteractor by
+    Kosmos.Fixture {
+        KeyguardStateCallbackInteractor(
+            applicationScope = testScope.backgroundScope,
+            backgroundDispatcher = testDispatcher,
+            selectedUserInteractor = selectedUserInteractor,
+            keyguardTransitionInteractor = keyguardTransitionInteractor,
+            trustInteractor = trustInteractor,
+            simBouncerInteractor = simBouncerInteractor,
+            dismissCallbackRegistry = dismissCallbackRegistry,
+            wmLockscreenVisibilityInteractor = windowManagerLockscreenVisibilityInteractor,
+            trustManager = trustManager,
+        )
+    }