diff options
9 files changed, 300 insertions, 0 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryImplTest.kt new file mode 100644 index 000000000000..8a0400d092c3 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryImplTest.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2023 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.statusbar.data.repository + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.statusbar.NotificationRemoteInputManager +import com.android.systemui.util.mockito.withArgCaptor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidJUnit4::class) +class RemoteInputRepositoryImplTest : SysuiTestCase() { + @Mock private lateinit var remoteInputManager: NotificationRemoteInputManager + + private lateinit var testScope: TestScope + private lateinit var underTest: RemoteInputRepositoryImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + testScope = TestScope() + underTest = RemoteInputRepositoryImpl(remoteInputManager) + } + + @Test + fun isRemoteInputActive_updatesOnChange() = + testScope.runTest { + val active by collectLastValue(underTest.isRemoteInputActive) + runCurrent() + assertThat(active).isFalse() + + val callback = withArgCaptor { + verify(remoteInputManager).addControllerCallback(capture()) + } + + callback.onRemoteInputActive(true) + runCurrent() + assertThat(active).isTrue() + + callback.onRemoteInputActive(false) + runCurrent() + assertThat(active).isFalse() + } +} diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorTest.kt new file mode 100644 index 000000000000..12469ddcafc2 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorTest.kt @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.statusbar.domain.interactor + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.coroutines.collectLastValue +import com.android.systemui.kosmos.testScope +import com.android.systemui.statusbar.data.repository.fakeRemoteInputRepository +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class RemoteInputInteractorTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val fakeRemoteInputRepository = kosmos.fakeRemoteInputRepository + private val underTest = kosmos.remoteInputInteractor + + @Test + fun isRemoteInputActive_true() = + testScope.runTest { + val active by collectLastValue(underTest.isRemoteInputActive) + + fakeRemoteInputRepository.isRemoteInputActive.value = true + runCurrent() + + assertThat(active).isTrue() + } + + @Test + fun isRemoteInputActive_false() = + testScope.runTest { + val active by collectLastValue(underTest.isRemoteInputActive) + + fakeRemoteInputRepository.isRemoteInputActive.value = false + runCurrent() + + assertThat(active).isFalse() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt index 29d53fc15e8b..9f878b241d73 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.data import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryModule +import com.android.systemui.statusbar.data.repository.RemoteInputRepositoryModule import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryModule import com.android.systemui.statusbar.phone.data.StatusBarPhoneDataLayerModule import dagger.Module @@ -24,6 +25,7 @@ import dagger.Module includes = [ KeyguardStatusBarRepositoryModule::class, + RemoteInputRepositoryModule::class, StatusBarModeRepositoryModule::class, StatusBarPhoneDataLayerModule::class ] diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt new file mode 100644 index 000000000000..c0302bc348b6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/RemoteInputRepository.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2023 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.data.repository + +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.NotificationRemoteInputManager +import com.android.systemui.statusbar.RemoteInputController +import dagger.Binds +import dagger.Module +import javax.inject.Inject +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow + +/** + * Repository used for tracking the state of notification remote input (e.g. when the user presses + * "reply" on a notification and the keyboard opens). + */ +interface RemoteInputRepository { + /** Whether remote input is currently active for any notification. */ + val isRemoteInputActive: Flow<Boolean> +} + +@SysUISingleton +class RemoteInputRepositoryImpl +@Inject +constructor( + private val notificationRemoteInputManager: NotificationRemoteInputManager, +) : RemoteInputRepository { + override val isRemoteInputActive: Flow<Boolean> = conflatedCallbackFlow { + trySend(false) // initial value is false + val callback = + object : RemoteInputController.Callback { + override fun onRemoteInputActive(active: Boolean) { + trySend(active) + } + } + notificationRemoteInputManager.addControllerCallback(callback) + awaitClose { notificationRemoteInputManager.removeControllerCallback(callback) } + } +} + +@Module +interface RemoteInputRepositoryModule { + @Binds fun bindImpl(impl: RemoteInputRepositoryImpl): RemoteInputRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt new file mode 100644 index 000000000000..68f727b046c0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractor.kt @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 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.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.data.repository.RemoteInputRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** + * Interactor used for business logic pertaining to the notification remote input (e.g. when the + * user presses "reply" on a notification and the keyboard opens). + */ +@SysUISingleton +class RemoteInputInteractor @Inject constructor(remoteInputRepository: RemoteInputRepository) { + /** Is remote input currently active for a notification? */ + val isRemoteInputActive: Flow<Boolean> = remoteInputRepository.isRemoteInputActive +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt index f1e6a053643f..f1e6a053643f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeKeyguardStatusBarRepository.kt diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt new file mode 100644 index 000000000000..c416ea1c1b39 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeRemoteInputRepository.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 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.data.repository + +import kotlinx.coroutines.flow.MutableStateFlow + +class FakeRemoteInputRepository : RemoteInputRepository { + override val isRemoteInputActive = MutableStateFlow(false) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryKosmos.kt new file mode 100644 index 000000000000..1684efba2ca2 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/RemoteInputRepositoryKosmos.kt @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2023 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.data.repository + +import com.android.systemui.kosmos.Kosmos + +var Kosmos.remoteInputRepository: RemoteInputRepository by + Kosmos.Fixture { fakeRemoteInputRepository } +val Kosmos.fakeRemoteInputRepository by Kosmos.Fixture { FakeRemoteInputRepository() } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorKosmos.kt new file mode 100644 index 000000000000..07b39dc87a9a --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/domain/interactor/RemoteInputInteractorKosmos.kt @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2023 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.systemui.kosmos.Kosmos +import com.android.systemui.statusbar.data.repository.remoteInputRepository + +val Kosmos.remoteInputInteractor by Kosmos.Fixture { RemoteInputInteractor(remoteInputRepository) } |