Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 298f1eb2 authored by Evan Laird's avatar Evan Laird
Browse files

[sb] add areaTint function to home status bar view model

This function returns a flow, based on displayId, which emits a new tint
calculator every time the dark region of the screen changes. The emitted
value is simply a functional interface from Rect (view bounds) -> tint

Test: HomeStatusBarViewModelImplTest
Bug: 364360986
Flag: com.android.systemui.status_bar_root_modernization
Change-Id: I1087f07b995cfda42cf9503ff734f8b4b7856910
parent 91f02d46
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel

import android.graphics.Color
import android.graphics.Rect
import android.view.View
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
@@ -66,4 +69,20 @@ class FakeHomeStatusBarViewModel : HomeStatusBarViewModel {
        )

    override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> = areNotificationLightsOut

    val darkRegions = mutableListOf<Rect>()

    var darkIconTint = Color.BLACK
    var lightIconTint = Color.WHITE

    override fun areaTint(displayId: Int): Flow<StatusBarTintColor> =
        MutableStateFlow(
            StatusBarTintColor { viewBounds ->
                if (DarkIconDispatcher.isInAreas(darkRegions, viewBounds)) {
                    lightIconTint
                } else {
                    darkIconTint
                }
            }
        )
}
+54 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ 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.graphics.Rect
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.view.View
@@ -45,6 +46,7 @@ import com.android.systemui.kosmos.testScope
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.plugins.DarkIconDispatcher
import com.android.systemui.scene.data.repository.sceneContainerRepository
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.screenrecord.data.model.ScreenRecordModel
@@ -73,6 +75,8 @@ import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher
import com.android.systemui.statusbar.phone.data.repository.fakeDarkIconRepository
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.HomeStatusBarViewModel.VisibilityModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -930,6 +934,56 @@ class HomeStatusBarViewModelImplTest : SysuiTestCase() {
            assertThat(systemInfoVisible!!.baseVisibility.visibility).isEqualTo(View.GONE)
        }

    @Test
    fun areaTint_viewIsInDarkBounds_getsDarkTint() =
        kosmos.runTest {
            val displayId = 321
            fakeDarkIconRepository.darkState(displayId).value =
                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)

            val areaTint by collectLastValue(underTest.areaTint(displayId))

            val tint = areaTint?.tint(Rect(1, 1, 3, 3))

            assertThat(tint).isEqualTo(0xAABBCC)
        }

    @Test
    fun areaTint_viewIsNotInDarkBounds_getsDefaultTint() =
        kosmos.runTest {
            val displayId = 321
            fakeDarkIconRepository.darkState(displayId).value =
                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)

            val areaTint by collectLastValue(underTest.areaTint(displayId))

            val tint = areaTint?.tint(Rect(6, 6, 7, 7))

            assertThat(tint).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
        }

    @Test
    fun areaTint_viewIsInDarkBounds_darkBoundsChange_viewUpdates() =
        kosmos.runTest {
            val displayId = 321
            fakeDarkIconRepository.darkState(displayId).value =
                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(0, 0, 5, 5)), 0f, 0xAABBCC)

            val areaTint by collectLastValue(underTest.areaTint(displayId))

            var tint = areaTint?.tint(Rect(1, 1, 3, 3))

            assertThat(tint).isEqualTo(0xAABBCC)

            // Dark region moves 5px to the right
            fakeDarkIconRepository.darkState(displayId).value =
                SysuiDarkIconDispatcher.DarkChange(listOf(Rect(5, 0, 10, 5)), 0f, 0xAABBCC)

            tint = areaTint?.tint(Rect(1, 1, 3, 3))

            assertThat(tint).isEqualTo(DarkIconDispatcher.DEFAULT_ICON_TINT)
        }

    private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
        ActiveNotificationsStore.Builder()
            .apply { notifications.forEach(::addIndividualNotif) }
+32 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel

import android.annotation.ColorInt
import android.graphics.Rect
import android.view.View
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
@@ -27,6 +29,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -43,6 +46,7 @@ import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotif
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.notification.headsup.PinnedStatus
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.phone.domain.interactor.DarkIconInteractor
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.HomeStatusBarViewModel.VisibilityModel
@@ -52,6 +56,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
@@ -119,6 +124,12 @@ interface HomeStatusBarViewModel {
     */
    fun areNotificationsLightsOut(displayId: Int): Flow<Boolean>

    /**
     * Given a displayId, returns a flow of [StatusBarTintColor], a functional interface that will
     * allow a view to calculate its correct tint depending on location
     */
    fun areaTint(displayId: Int): Flow<StatusBarTintColor>

    /** Models the current visibility for a specific child view of status bar. */
    data class VisibilityModel(
        @View.Visibility val visibility: Int,
@@ -140,6 +151,7 @@ constructor(
    collapsedStatusBarInteractor: CollapsedStatusBarInteractor,
    private val lightsOutInteractor: LightsOutInteractor,
    private val notificationsInteractor: ActiveNotificationsInteractor,
    private val darkIconInteractor: DarkIconInteractor,
    headsUpNotificationInteractor: HeadsUpNotificationInteractor,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    keyguardInteractor: KeyguardInteractor,
@@ -192,6 +204,21 @@ constructor(
                .distinctUntilChanged()
        }

    override fun areaTint(displayId: Int): Flow<StatusBarTintColor> =
        darkIconInteractor
            .darkState(displayId)
            .map { (areas: Collection<Rect>, tint: Int) ->
                StatusBarTintColor { viewBounds: Rect ->
                    if (DarkIconDispatcher.isInAreas(areas, viewBounds)) {
                        tint
                    } else {
                        DarkIconDispatcher.DEFAULT_ICON_TINT
                    }
                }
            }
            .conflate()
            .distinctUntilChanged()

    /**
     * True if the current SysUI state can show the home status bar (aka this status bar), and false
     * if we shouldn't be showing any part of the home status bar.
@@ -302,3 +329,8 @@ constructor(
    @View.Visibility
    private fun Boolean.toVisibleOrInvisible(): Int = if (this) View.VISIBLE else View.INVISIBLE
}

/** Lookup the color for a given view in the status bar */
fun interface StatusBarTintColor {
    @ColorInt fun tint(viewBounds: Rect): Int
}
+2 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.systemui.statusbar.chips.ui.viewmodel.ongoingActivityChipsVie
import com.android.systemui.statusbar.events.domain.interactor.systemStatusEventAnimationInteractor
import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
import com.android.systemui.statusbar.notification.stack.domain.interactor.headsUpNotificationInteractor
import com.android.systemui.statusbar.phone.domain.interactor.darkIconInteractor
import com.android.systemui.statusbar.phone.domain.interactor.lightsOutInteractor
import com.android.systemui.statusbar.pipeline.shared.domain.interactor.collapsedStatusBarInteractor

@@ -36,6 +37,7 @@ val Kosmos.homeStatusBarViewModel: HomeStatusBarViewModel by
            collapsedStatusBarInteractor,
            lightsOutInteractor,
            activeNotificationsInteractor,
            darkIconInteractor,
            headsUpNotificationInteractor,
            keyguardTransitionInteractor,
            keyguardInteractor,