summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Caitlin Shkuratov <caitlinshk@google.com> 2024-09-16 22:27:19 +0000
committer Caitlin Shkuratov <caitlinshk@google.com> 2024-09-20 14:58:21 +0000
commit190697ffca9de8f313b64e1fe254a2ee03464a02 (patch)
tree00522a2076e5b948fbd06feb7d7d9d47819861fc
parent6010338e52eb79f9634299b39780e0ba00fc4573 (diff)
[SB] Set up is<ChildView>Visible flows in CollapsedStatusBarViewModel.
We want to pull out all the business logic from CollapsedStatusBarFragment and put it in interactors and view models instead. This CL sets up three new flows in CollapsedStatusBarViewModel and populates them based on disable flags: - isClockVisible - areNotificationIconsVisible - isSystemInfoVisible The visibilities of those child views is dependent on a *lot* more than just the disable flags, but this CL adds the scaffolding for filling in those visibilities. Future CLs should *just* touch CollapsedStatusBarInteractor and/or CollapsedStatusBarViewModel to add the visibility nuances. Bug: 364360986 Flag: com.android.systemui.status_bar_simple_fragment Test: atest CollapsedStatusBarInteractorTest CollapsedStatusBarViewModelImplTest Change-Id: I1272d78d4435404272049ddcf7de89bd0290cae0
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/model/DisableFlagsModel.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepository.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/model/StatusBarDisableFlagsVisibilityModel.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt113
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt98
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt23
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt41
12 files changed, 575 insertions, 42 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/model/DisableFlagsModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/model/DisableFlagsModel.kt
index 2bb476523cb8..ce25cf5895c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/model/DisableFlagsModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/model/DisableFlagsModel.kt
@@ -17,8 +17,12 @@ package com.android.systemui.statusbar.disableflags.data.model
import android.app.StatusBarManager.DISABLE2_NONE
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
+import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS
+import android.app.StatusBarManager.DISABLE_CLOCK
import android.app.StatusBarManager.DISABLE_NONE
import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
@@ -27,12 +31,14 @@ import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
* Model for the disable flags that come from [IStatusBar].
*
* For clients of the disable flags: do *not* refer to the disable integers directly. Instead,
- * re-use or define a helper method that internally processes the flags. (We want to hide the
- * bitwise logic here so no one else has to worry about it.)
+ * re-use or define a helper method or property that internally processes the flags. (We want to
+ * hide the bitwise logic here so no one else has to worry about it.)
*/
data class DisableFlagsModel(
private val disable1: Int = DISABLE_NONE,
private val disable2: Int = DISABLE2_NONE,
+ /** True if we should animate any view visibility changes and false otherwise. */
+ val animate: Boolean = false,
) {
/** Returns true if notification alerts are allowed based on the flags. */
fun areNotificationAlertsEnabled(): Boolean {
@@ -49,6 +55,13 @@ data class DisableFlagsModel(
return (disable2 and DISABLE2_QUICK_SETTINGS) == 0
}
+ val isClockEnabled = (disable1 and DISABLE_CLOCK) == 0
+
+ val areNotificationIconsEnabled = (disable1 and DISABLE_NOTIFICATION_ICONS) == 0
+
+ val isSystemInfoEnabled =
+ (disable1 and DISABLE_SYSTEM_INFO) == 0 && (disable2 and DISABLE2_SYSTEM_ICONS) == 0
+
/** Logs the change to the provided buffer. */
fun logChange(buffer: LogBuffer, disableFlagsLogger: DisableFlagsLogger) {
buffer.log(
@@ -60,9 +73,9 @@ data class DisableFlagsModel(
},
{
disableFlagsLogger.getDisableFlagsString(
- new = DisableFlagsLogger.DisableState(int1, int2),
+ new = DisableFlagsLogger.DisableState(int1, int2)
)
- }
+ },
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepository.kt
index 13b74b493905..9004e5d12663 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepository.kt
@@ -72,6 +72,7 @@ constructor(
// [QuickSettingsInteractor]-type class. However, that's out of
// scope for the CentralSurfaces removal project.
remoteInputQuickSettingsDisabler.adjustDisableFlags(state2),
+ animate,
)
)
}
@@ -82,5 +83,5 @@ constructor(
.distinctUntilChanged()
.onEach { it.logChange(logBuffer, disableFlagsLogger) }
// Use Eagerly because we always need to know about disable flags
- .stateIn(scope, SharingStarted.Eagerly, DisableFlagsModel())
+ .stateIn(scope, SharingStarted.Eagerly, DisableFlagsModel(animate = false))
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt
new file mode 100644
index 000000000000..9164da721e3a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractor.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.pipeline.shared.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
+import com.android.systemui.statusbar.pipeline.shared.domain.model.StatusBarDisableFlagsVisibilityModel
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Interactor for the home screen status bar (aka
+ * [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment]).
+ */
+@SysUISingleton
+class CollapsedStatusBarInteractor
+@Inject
+constructor(disableFlagsRepository: DisableFlagsRepository) {
+ /**
+ * The visibilities of various status bar child views, based only on the information we received
+ * from disable flags.
+ */
+ val visibilityViaDisableFlags: Flow<StatusBarDisableFlagsVisibilityModel> =
+ disableFlagsRepository.disableFlags.map {
+ StatusBarDisableFlagsVisibilityModel(
+ isClockAllowed = it.isClockEnabled,
+ areNotificationIconsAllowed = it.areNotificationIconsEnabled,
+ isSystemInfoAllowed = it.isSystemInfoEnabled,
+ animate = it.animate,
+ )
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/model/StatusBarDisableFlagsVisibilityModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/model/StatusBarDisableFlagsVisibilityModel.kt
new file mode 100644
index 000000000000..69e9746ee24f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/domain/model/StatusBarDisableFlagsVisibilityModel.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.pipeline.shared.domain.model
+
+/**
+ * Represents the visibilities of various status bar child views, based only on the information we
+ * received from disable flags.
+ */
+data class StatusBarDisableFlagsVisibilityModel(
+ /** True if the clock is allowed to be shown. */
+ val isClockAllowed: Boolean,
+ /** True if the notification icons are allowed to be shown. */
+ val areNotificationIconsAllowed: Boolean,
+ /** True if the system information (wifi, mobile, etc.) is allowed to be shown. */
+ val isSystemInfoAllowed: Boolean,
+ /** True if we should animate any view visibility changes and false otherwise. */
+ val animate: Boolean,
+)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index 49eabba5c2b0..4cb66c19a0bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.animation.Interpolators
import com.android.systemui.Flags
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -28,7 +29,9 @@ import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.core.StatusBarSimpleFragment
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch
@@ -134,6 +137,29 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa
}
}
}
+
+ if (StatusBarSimpleFragment.isEnabled) {
+ val clockView = view.requireViewById<View>(R.id.clock)
+ launch { viewModel.isClockVisible.collect { clockView.adjustVisibility(it) } }
+
+ val notificationIconsArea = view.requireViewById<View>(R.id.notificationIcons)
+ launch {
+ viewModel.isNotificationIconContainerVisible.collect {
+ notificationIconsArea.adjustVisibility(it)
+ }
+ }
+
+ val systemInfoView =
+ view.requireViewById<View>(R.id.status_bar_end_side_content)
+ // TODO(b/364360986): Also handle operator name view.
+ launch {
+ viewModel.isSystemInfoVisible.collect {
+ systemInfoView.adjustVisibility(it)
+ // TODO(b/364360986): The system info view has a custom alpha controller
+ // in CollapsedStatusBarFragment.
+ }
+ }
+ }
}
}
}
@@ -167,6 +193,54 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa
)
.start()
}
+
+ private fun View.adjustVisibility(model: CollapsedStatusBarViewModel.VisibilityModel) {
+ if (model.visibility == View.VISIBLE) {
+ this.show(model.shouldAnimateChange)
+ } else {
+ this.hide(model.visibility, model.shouldAnimateChange)
+ }
+ }
+
+ // See CollapsedStatusBarFragment#hide.
+ private fun View.hide(state: Int = View.INVISIBLE, shouldAnimateChange: Boolean) {
+ val v = this
+ v.animate().cancel()
+ if (!shouldAnimateChange) {
+ v.alpha = 0f
+ v.visibility = state
+ return
+ }
+
+ v.animate()
+ .alpha(0f)
+ .setDuration(CollapsedStatusBarFragment.FADE_OUT_DURATION.toLong())
+ .setStartDelay(0)
+ .setInterpolator(Interpolators.ALPHA_OUT)
+ .withEndAction { v.visibility = state }
+ }
+
+ // See CollapsedStatusBarFragment#show.
+ private fun View.show(shouldAnimateChange: Boolean) {
+ val v = this
+ v.animate().cancel()
+ v.visibility = View.VISIBLE
+ if (!shouldAnimateChange) {
+ v.alpha = 1f
+ return
+ }
+ v.animate()
+ .alpha(1f)
+ .setDuration(CollapsedStatusBarFragment.FADE_IN_DURATION.toLong())
+ .setInterpolator(Interpolators.ALPHA_IN)
+ .setStartDelay(CollapsedStatusBarFragment.FADE_IN_DELAY.toLong())
+ // We need to clean up any pending end action from animateHide if we call both hide and
+ // show in the same frame before the animation actually gets started.
+ // cancel() doesn't really remove the end action.
+ .withEndAction(null)
+
+ // TODO(b/364360986): Synchronize the motion with the Keyguard fading if necessary.
+ }
}
/** Listener for various events that may affect the status bar's visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
index 9cce2b8fb72b..1c499257bb4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+import android.view.View
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -33,6 +34,8 @@ import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsVie
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.CollapsedStatusBarInteractor
+import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel.VisibilityModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -80,9 +83,18 @@ interface CollapsedStatusBarViewModel {
/**
* True if the current scene can show the home status bar (aka this status bar), and false if
* the current scene should never show the home status bar.
+ *
+ * TODO(b/364360986): Once the is<SomeChildView>Visible flows are fully enabled, we shouldn't
+ * need this flow anymore.
*/
val isHomeStatusBarAllowedByScene: StateFlow<Boolean>
+ val isClockVisible: Flow<VisibilityModel>
+ val isNotificationIconContainerVisible: Flow<VisibilityModel>
+ val isSystemInfoVisible: Flow<VisibilityModel>
+
+ // TODO(b/364360986): Add isOngoingActivityChipVisible: Flow<VisibilityModel>
+
/**
* Apps can request a low profile mode [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE] where
* status bar and navigation icons dim. In this mode, a notification dot appears where the
@@ -93,12 +105,20 @@ interface CollapsedStatusBarViewModel {
* [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE].
*/
fun areNotificationsLightsOut(displayId: Int): Flow<Boolean>
+
+ /** Models the current visibility for a specific child view of status bar. */
+ data class VisibilityModel(
+ @View.Visibility val visibility: Int,
+ /** True if a visibility change should be animated. */
+ val shouldAnimateChange: Boolean,
+ )
}
@SysUISingleton
class CollapsedStatusBarViewModelImpl
@Inject
constructor(
+ collapsedStatusBarInteractor: CollapsedStatusBarInteractor,
private val lightsOutInteractor: LightsOutInteractor,
private val notificationsInteractor: ActiveNotificationsInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
@@ -148,4 +168,26 @@ constructor(
}
.distinctUntilChanged()
}
+
+ // TODO(b/364360986): For all the is<SomeChildView>Visible flows, take other conditions into
+ // account like whether we're on keyguard or shade.
+
+ override val isClockVisible: Flow<VisibilityModel> =
+ collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
+ // TODO(b/364360986): Take CollapsedStatusBarFragment.clockHiddenMode into account.
+ VisibilityModel(it.isClockAllowed.toVisibilityInt(), it.animate)
+ }
+ override val isNotificationIconContainerVisible: Flow<VisibilityModel> =
+ collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
+ VisibilityModel(it.areNotificationIconsAllowed.toVisibilityInt(), it.animate)
+ }
+ override val isSystemInfoVisible: Flow<VisibilityModel> =
+ collapsedStatusBarInteractor.visibilityViaDisableFlags.map {
+ VisibilityModel(it.isSystemInfoAllowed.toVisibilityInt(), it.animate)
+ }
+
+ @View.Visibility
+ private fun Boolean.toVisibilityInt(): Int {
+ return if (this) View.VISIBLE else View.GONE
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
index d2dfc9257e7e..907c68440b55 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/disableflags/data/repository/DisableFlagsRepositoryTest.kt
@@ -17,16 +17,19 @@ package com.android.systemui.statusbar.disableflags.data.repository
import android.app.StatusBarManager.DISABLE2_NONE
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
+import android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS
import android.app.StatusBarManager.DISABLE_CLOCK
import android.app.StatusBarManager.DISABLE_NONE
import android.app.StatusBarManager.DISABLE_NOTIFICATION_ALERTS
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
import android.content.res.Configuration
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
-import com.android.systemui.res.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferFactory
+import com.android.systemui.res.R
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.disableflags.DisableFlagsLogger
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
@@ -82,7 +85,7 @@ class DisableFlagsRepositoryTest : SysuiTestCase() {
@Test
fun disableFlags_initialValue_none() {
assertThat(underTest.disableFlags.value)
- .isEqualTo(DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE))
+ .isEqualTo(DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false))
}
@Test
@@ -182,12 +185,7 @@ class DisableFlagsRepositoryTest : SysuiTestCase() {
fun disableFlags_quickSettingsDisabled_quickSettingsEnabledFalse() =
testScope.runTest {
getCommandQueueCallback()
- .disable(
- DISPLAY_ID,
- DISABLE_NONE,
- DISABLE2_QUICK_SETTINGS,
- /* animate= */ false,
- )
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_QUICK_SETTINGS, /* animate= */ false)
assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse()
}
@@ -217,21 +215,84 @@ class DisableFlagsRepositoryTest : SysuiTestCase() {
configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
mContext.orCreateTestableResources.addOverride(
R.bool.config_use_split_notification_shade,
- /* value= */ false
+ /* value= */ false,
)
remoteInputQuickSettingsDisabler.setRemoteInputActive(true)
remoteInputQuickSettingsDisabler.onConfigChanged(configuration)
getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false)
+
+ // THEN quick settings is disabled (even if the disable flags don't say so)
+ assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse()
+ }
+
+ @Test
+ fun disableFlags_clockDisabled() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_CLOCK, DISABLE2_NONE, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.isClockEnabled).isFalse()
+ }
+
+ @Test
+ fun disableFlags_clockEnabled() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.isClockEnabled).isTrue()
+ }
+
+ @Test
+ fun disableFlags_notificationIconsDisabled() =
+ testScope.runTest {
+ getCommandQueueCallback()
.disable(
DISPLAY_ID,
- DISABLE_NONE,
+ DISABLE_NOTIFICATION_ICONS,
DISABLE2_NONE,
/* animate= */ false,
)
- // THEN quick settings is disabled (even if the disable flags don't say so)
- assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse()
+ assertThat(underTest.disableFlags.value.areNotificationIconsEnabled).isFalse()
+ }
+
+ @Test
+ fun disableFlags_notificationIconsEnabled() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.areNotificationIconsEnabled).isTrue()
+ }
+
+ @Test
+ fun disableFlags_systemInfoDisabled_viaDisable1() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_SYSTEM_INFO, DISABLE2_NONE, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isFalse()
+ }
+
+ @Test
+ fun disableFlags_systemInfoDisabled_viaDisable2() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_SYSTEM_ICONS, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isFalse()
+ }
+
+ @Test
+ fun disableFlags_systemInfoEnabled() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(DISPLAY_ID, DISABLE_NONE, DISABLE2_NONE, /* animate= */ false)
+
+ assertThat(underTest.disableFlags.value.isSystemInfoEnabled).isTrue()
}
@Test
@@ -267,6 +328,34 @@ class DisableFlagsRepositoryTest : SysuiTestCase() {
assertThat(underTest.disableFlags.value.isQuickSettingsEnabled()).isFalse()
}
+ @Test
+ fun disableFlags_animateFalse() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(
+ DISPLAY_ID,
+ DISABLE_NOTIFICATION_ALERTS,
+ DISABLE2_NONE,
+ /* animate= */ false,
+ )
+
+ assertThat(underTest.disableFlags.value.animate).isFalse()
+ }
+
+ @Test
+ fun disableFlags_animateTrue() =
+ testScope.runTest {
+ getCommandQueueCallback()
+ .disable(
+ DISPLAY_ID,
+ DISABLE_NOTIFICATION_ALERTS,
+ DISABLE2_NONE,
+ /* animate= */ true,
+ )
+
+ assertThat(underTest.disableFlags.value.animate).isTrue()
+ }
+
private fun getCommandQueueCallback(): CommandQueue.Callbacks {
val callbackCaptor = argumentCaptor<CommandQueue.Callbacks>()
verify(commandQueue).addCallback(callbackCaptor.capture())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
new file mode 100644
index 000000000000..5036e775211e
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorTest.kt
@@ -0,0 +1,94 @@
+/*
+ * 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.pipeline.shared.domain.interactor
+
+import android.app.StatusBarManager.DISABLE2_NONE
+import android.app.StatusBarManager.DISABLE_CLOCK
+import android.app.StatusBarManager.DISABLE_NONE
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
+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.disableflags.data.model.DisableFlagsModel
+import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlin.test.Test
+import kotlinx.coroutines.test.runTest
+
+@SmallTest
+class CollapsedStatusBarInteractorTest : SysuiTestCase() {
+ val kosmos = testKosmos()
+ val testScope = kosmos.testScope
+ val disableFlagsRepo = kosmos.fakeDisableFlagsRepository
+
+ val underTest = kosmos.collapsedStatusBarInteractor
+
+ @Test
+ fun visibilityViaDisableFlags_allDisabled() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+ disableFlagsRepo.disableFlags.value =
+ DisableFlagsModel(
+ DISABLE_CLOCK or DISABLE_NOTIFICATION_ICONS or DISABLE_SYSTEM_INFO,
+ DISABLE2_NONE,
+ animate = false,
+ )
+
+ assertThat(latest!!.isClockAllowed).isFalse()
+ assertThat(latest!!.areNotificationIconsAllowed).isFalse()
+ assertThat(latest!!.isSystemInfoAllowed).isFalse()
+ }
+
+ @Test
+ fun visibilityViaDisableFlags_allEnabled() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+ disableFlagsRepo.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
+
+ assertThat(latest!!.isClockAllowed).isTrue()
+ assertThat(latest!!.areNotificationIconsAllowed).isTrue()
+ assertThat(latest!!.isSystemInfoAllowed).isTrue()
+ }
+
+ @Test
+ fun visibilityViaDisableFlags_animateFalse() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+ disableFlagsRepo.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = false)
+
+ assertThat(latest!!.animate).isFalse()
+ }
+
+ @Test
+ fun visibilityViaDisableFlags_animateTrue() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.visibilityViaDisableFlags)
+
+ disableFlagsRepo.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE, animate = true)
+
+ assertThat(latest!!.animate).isTrue()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index 7ae6ea51b912..31f06c3f03bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -16,8 +16,14 @@
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+import android.app.StatusBarManager.DISABLE2_NONE
+import android.app.StatusBarManager.DISABLE_CLOCK
+import android.app.StatusBarManager.DISABLE_NONE
+import android.app.StatusBarManager.DISABLE_NOTIFICATION_ICONS
+import android.app.StatusBarManager.DISABLE_SYSTEM_INFO
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
+import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -25,12 +31,10 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardOcclusionRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testCase
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -38,8 +42,6 @@ import com.android.systemui.log.assertLogsWtf
import com.android.systemui.mediaprojection.data.model.MediaProjectionState
import com.android.systemui.mediaprojection.data.repository.fakeMediaProjectionRepository
import com.android.systemui.scene.data.repository.sceneContainerRepository
-import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
-import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
import com.android.systemui.screenrecord.data.repository.screenRecordRepository
@@ -48,17 +50,16 @@ import com.android.systemui.statusbar.chips.mediaprojection.domain.interactor.Me
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.assertIsScreenRecordChip
import com.android.systemui.statusbar.chips.ui.viewmodel.OngoingActivityChipsViewModelTest.Companion.assertIsShareToAppChip
-import com.android.systemui.statusbar.chips.ui.viewmodel.ongoingActivityChipsViewModel
import com.android.systemui.statusbar.data.model.StatusBarMode
import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository.Companion.DISPLAY_ID
import com.android.systemui.statusbar.data.repository.fakeStatusBarModeRepository
+import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
+import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
-import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
-import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.emptyFlow
@@ -83,17 +84,9 @@ class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
private val statusBarModeRepository = kosmos.fakeStatusBarModeRepository
private val activeNotificationListRepository = kosmos.activeNotificationListRepository
private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val disableFlagsRepository = kosmos.fakeDisableFlagsRepository
- private val underTest =
- CollapsedStatusBarViewModelImpl(
- kosmos.lightsOutInteractor,
- kosmos.activeNotificationsInteractor,
- kosmos.keyguardTransitionInteractor,
- kosmos.sceneInteractor,
- kosmos.sceneContainerOcclusionInteractor,
- kosmos.ongoingActivityChipsViewModel,
- kosmos.applicationCoroutineScope,
- )
+ private val underTest = kosmos.collapsedStatusBarViewModel
@Before
fun setUp() {
@@ -495,14 +488,77 @@ class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
assertThat(latest).isTrue()
}
+ @Test
+ fun isClockVisible_allowedByDisableFlags_visible() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isClockVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun isClockVisible_notAllowedByDisableFlags_gone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isClockVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_CLOCK, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.GONE)
+ }
+
+ @Test
+ fun isNotificationIconContainerVisible_allowedByDisableFlags_visible() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isNotificationIconContainerVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun isNotificationIconContainerVisible_notAllowedByDisableFlags_gone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isNotificationIconContainerVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_NOTIFICATION_ICONS, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.GONE)
+ }
+
+ @Test
+ fun isSystemInfoVisible_allowedByDisableFlags_visible() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isSystemInfoVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_NONE, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.VISIBLE)
+ }
+
+ @Test
+ fun isSystemInfoVisible_notAllowedByDisableFlags_gone() =
+ testScope.runTest {
+ val latest by collectLastValue(underTest.isSystemInfoVisible)
+
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(DISABLE_SYSTEM_INFO, DISABLE2_NONE)
+
+ assertThat(latest!!.visibility).isEqualTo(View.GONE)
+ }
+
private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
ActiveNotificationsStore.Builder()
.apply { notifications.forEach(::addIndividualNotif) }
.build()
private val testNotifications =
- listOf(
- activeNotificationModel(key = "notif1"),
- activeNotificationModel(key = "notif2"),
- )
+ listOf(activeNotificationModel(key = "notif1"), activeNotificationModel(key = "notif2"))
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
index 4834d367d4be..cc90c1167ef1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+import android.view.View
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import kotlinx.coroutines.flow.Flow
@@ -36,9 +37,29 @@ class FakeCollapsedStatusBarViewModel : CollapsedStatusBarViewModel {
override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
- override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> = areNotificationLightsOut
+ override val isClockVisible =
+ MutableStateFlow(
+ CollapsedStatusBarViewModel.VisibilityModel(
+ visibility = View.GONE,
+ shouldAnimateChange = false,
+ )
+ )
+
+ override val isNotificationIconContainerVisible =
+ MutableStateFlow(
+ CollapsedStatusBarViewModel.VisibilityModel(
+ visibility = View.GONE,
+ shouldAnimateChange = false,
+ )
+ )
- fun setNotificationLightsOut(lightsOut: Boolean) {
- areNotificationLightsOut.value = lightsOut
- }
+ override val isSystemInfoVisible =
+ MutableStateFlow(
+ CollapsedStatusBarViewModel.VisibilityModel(
+ visibility = View.GONE,
+ shouldAnimateChange = false,
+ )
+ )
+
+ override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> = areNotificationLightsOut
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt
new file mode 100644
index 000000000000..385a813996ff
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/domain/interactor/CollapsedStatusBarInteractorKosmos.kt
@@ -0,0 +1,23 @@
+/*
+ * 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.pipeline.shared.domain.interactor
+
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
+
+val Kosmos.collapsedStatusBarInteractor: CollapsedStatusBarInteractor by
+ Kosmos.Fixture { CollapsedStatusBarInteractor(fakeDisableFlagsRepository) }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt
new file mode 100644
index 000000000000..f47aa2945319
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelKosmos.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.pipeline.shared.ui.viewmodel
+
+import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.statusbar.chips.ui.viewmodel.ongoingActivityChipsViewModel
+import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
+import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
+import com.android.systemui.statusbar.pipeline.shared.domain.interactor.collapsedStatusBarInteractor
+
+val Kosmos.collapsedStatusBarViewModel: CollapsedStatusBarViewModel by
+ Kosmos.Fixture {
+ CollapsedStatusBarViewModelImpl(
+ collapsedStatusBarInteractor,
+ lightsOutInteractor,
+ activeNotificationsInteractor,
+ keyguardTransitionInteractor,
+ sceneInteractor,
+ sceneContainerOcclusionInteractor,
+ ongoingActivityChipsViewModel,
+ applicationCoroutineScope,
+ )
+ }