diff options
author | 2024-09-18 18:29:04 +0000 | |
---|---|---|
committer | 2024-09-20 13:40:32 +0100 | |
commit | 1a910a9ef0e6c4534f1fb2f14349c9904b0c0717 (patch) | |
tree | 328839b0aa77e8098f900d4581abf7763f595bfc | |
parent | 76136b035ec7e0a7c61371b16dc3bb001dca5dce (diff) |
[SB] Create StatusBarWindowStateRepository.
The equivalent of StatusBarWindowStateController but in repository form.
This will be used in a future CL.
Bug: 364360986
Test: atest StatusBarWindowStateRepositoryTest
Flag: EXEMPT unused
Change-Id: Icad8c3690a15613697c7db19ad88cccf72cceebb
4 files changed, 243 insertions, 14 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt index 8f424b2e251e..fa9c6b2c8151 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt @@ -17,9 +17,9 @@ package com.android.systemui.statusbar.window import android.app.StatusBarManager -import android.app.StatusBarManager.WindowVisibleState import android.app.StatusBarManager.WINDOW_STATE_SHOWING import android.app.StatusBarManager.WINDOW_STATUS_BAR +import android.app.StatusBarManager.WindowVisibleState import android.app.StatusBarManager.windowStateToString import android.util.Log import com.android.systemui.dagger.SysUISingleton @@ -31,23 +31,27 @@ import javax.inject.Inject /** * A centralized class maintaining the state of the status bar window. * + * @deprecated use + * [com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepository] instead. + * * Classes that want to get updates about the status bar window state should subscribe to this class * via [addListener] and should NOT add their own callback on [CommandQueue]. */ @SysUISingleton -class StatusBarWindowStateController @Inject constructor( - @DisplayId private val thisDisplayId: Int, - commandQueue: CommandQueue -) { - private val commandQueueCallback = object : CommandQueue.Callbacks { - override fun setWindowState( - displayId: Int, - @StatusBarManager.WindowType window: Int, - @WindowVisibleState state: Int - ) { - this@StatusBarWindowStateController.setWindowState(displayId, window, state) +@Deprecated("Use StatusBarWindowRepository instead") +class StatusBarWindowStateController +@Inject +constructor(@DisplayId private val thisDisplayId: Int, commandQueue: CommandQueue) { + private val commandQueueCallback = + object : CommandQueue.Callbacks { + override fun setWindowState( + displayId: Int, + @StatusBarManager.WindowType window: Int, + @WindowVisibleState state: Int, + ) { + this@StatusBarWindowStateController.setWindowState(displayId, window, state) + } } - } private val listeners: MutableSet<StatusBarWindowStateListener> = HashSet() @WindowVisibleState private var windowState: Int = WINDOW_STATE_SHOWING @@ -71,7 +75,7 @@ class StatusBarWindowStateController @Inject constructor( private fun setWindowState( displayId: Int, @StatusBarManager.WindowType window: Int, - @WindowVisibleState state: Int + @WindowVisibleState state: Int, ) { if (displayId != thisDisplayId) { return diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepository.kt new file mode 100644 index 000000000000..678576d1b450 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepository.kt @@ -0,0 +1,86 @@ +/* + * 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.window.data.repository + +import android.app.StatusBarManager +import android.app.StatusBarManager.WINDOW_STATE_HIDDEN +import android.app.StatusBarManager.WINDOW_STATE_HIDING +import android.app.StatusBarManager.WINDOW_STATE_SHOWING +import android.app.StatusBarManager.WINDOW_STATUS_BAR +import android.app.StatusBarManager.WindowVisibleState +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dagger.qualifiers.DisplayId +import com.android.systemui.statusbar.CommandQueue +import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.stateIn + +/** + * A centralized class maintaining the state of the status bar window. + * + * Classes that want to get updates about the status bar window state should subscribe to + * [windowState] and should NOT add their own callback on [CommandQueue]. + */ +@SysUISingleton +class StatusBarWindowStateRepository +@Inject +constructor( + private val commandQueue: CommandQueue, + @DisplayId private val thisDisplayId: Int, + @Application private val scope: CoroutineScope, +) { + val windowState: StateFlow<StatusBarWindowState> = + conflatedCallbackFlow { + val callback = + object : CommandQueue.Callbacks { + override fun setWindowState( + displayId: Int, + @StatusBarManager.WindowType window: Int, + @WindowVisibleState state: Int, + ) { + // TODO(b/364360986): Log the window state changes. + if (displayId != thisDisplayId) { + return + } + if (window != WINDOW_STATUS_BAR) { + return + } + trySend(state.toWindowState()) + } + } + commandQueue.addCallback(callback) + awaitClose { commandQueue.removeCallback(callback) } + } + // Use Eagerly because we always need to know about the status bar window state + .stateIn(scope, SharingStarted.Eagerly, StatusBarWindowState.Hidden) + + @WindowVisibleState + private fun Int.toWindowState(): StatusBarWindowState { + return when (this) { + WINDOW_STATE_SHOWING -> StatusBarWindowState.Showing + WINDOW_STATE_HIDING -> StatusBarWindowState.Hiding + WINDOW_STATE_HIDDEN -> StatusBarWindowState.Hidden + else -> StatusBarWindowState.Hidden + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt b/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt new file mode 100644 index 000000000000..a99046ee05e9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/shared/model/StatusBarWindowState.kt @@ -0,0 +1,27 @@ +/* + * 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.window.data.model + +/** + * Represents the state of the status bar *window* as a whole (as opposed to individual views within + * the status bar). + */ +enum class StatusBarWindowState { + Showing, + Hiding, + Hidden, +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryTest.kt new file mode 100644 index 000000000000..38e04bb1d00f --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/window/data/repository/StatusBarWindowStateRepositoryTest.kt @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2021 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.window.data.repository + +import android.app.StatusBarManager.WINDOW_NAVIGATION_BAR +import android.app.StatusBarManager.WINDOW_STATE_HIDDEN +import android.app.StatusBarManager.WINDOW_STATE_HIDING +import android.app.StatusBarManager.WINDOW_STATE_SHOWING +import android.app.StatusBarManager.WINDOW_STATUS_BAR +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.CommandQueue +import com.android.systemui.statusbar.commandQueue +import com.android.systemui.statusbar.window.data.model.StatusBarWindowState +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.mockito.Mockito.verify +import org.mockito.kotlin.argumentCaptor + +@SmallTest +@OptIn(ExperimentalCoroutinesApi::class) +class StatusBarWindowStateRepositoryTest : SysuiTestCase() { + private val kosmos = testKosmos() + private val testScope = kosmos.testScope + private val commandQueue = kosmos.commandQueue + private val underTest = + StatusBarWindowStateRepository(commandQueue, DISPLAY_ID, testScope.backgroundScope) + + private val callback: CommandQueue.Callbacks + get() { + testScope.runCurrent() + val callbackCaptor = argumentCaptor<CommandQueue.Callbacks>() + verify(commandQueue).addCallback(callbackCaptor.capture()) + return callbackCaptor.firstValue + } + + @Test + fun windowState_notSameDisplayId_notUpdated() = + testScope.runTest { + val latest by collectLastValue(underTest.windowState) + assertThat(latest).isEqualTo(StatusBarWindowState.Hidden) + + callback.setWindowState(DISPLAY_ID + 1, WINDOW_STATUS_BAR, WINDOW_STATE_SHOWING) + + assertThat(latest).isEqualTo(StatusBarWindowState.Hidden) + } + + @Test + fun windowState_notStatusBarWindow_notUpdated() = + testScope.runTest { + val latest by collectLastValue(underTest.windowState) + assertThat(latest).isEqualTo(StatusBarWindowState.Hidden) + + callback.setWindowState(DISPLAY_ID, WINDOW_NAVIGATION_BAR, WINDOW_STATE_SHOWING) + + assertThat(latest).isEqualTo(StatusBarWindowState.Hidden) + } + + @Test + fun windowState_showing_updated() = + testScope.runTest { + val latest by collectLastValue(underTest.windowState) + + callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, WINDOW_STATE_SHOWING) + + assertThat(latest).isEqualTo(StatusBarWindowState.Showing) + } + + @Test + fun windowState_hiding_updated() = + testScope.runTest { + val latest by collectLastValue(underTest.windowState) + + callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, WINDOW_STATE_HIDING) + + assertThat(latest).isEqualTo(StatusBarWindowState.Hiding) + } + + @Test + fun windowState_hidden_updated() = + testScope.runTest { + val latest by collectLastValue(underTest.windowState) + callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, WINDOW_STATE_SHOWING) + assertThat(latest).isEqualTo(StatusBarWindowState.Showing) + + callback.setWindowState(DISPLAY_ID, WINDOW_STATUS_BAR, WINDOW_STATE_HIDDEN) + + assertThat(latest).isEqualTo(StatusBarWindowState.Hidden) + } +} + +private const val DISPLAY_ID = 10 |