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

Commit 54e5242e authored by Yining Liu's avatar Yining Liu Committed by Android (Google) Code Review
Browse files

Merge changes I0b30c4b9,I6d46c7a0 into main

* changes:
  Formatting kotlin file
  Fix minimalism feature not responding to settings change
parents b7f09d91 f3ae4e09
Loading
Loading
Loading
Loading
+24 −25
Original line number Diff line number Diff line
@@ -21,16 +21,19 @@ import android.service.notification.StatusBarNotification
import android.view.View.VISIBLE
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.kosmos.testScope
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.nullable
@@ -52,8 +55,11 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
    private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
    @Mock private lateinit var mediaDataManager: MediaDataManager
    @Mock private lateinit var stackLayout: NotificationStackScrollLayout
    @Mock private lateinit var seenNotificationsInteractor: SeenNotificationsInteractor

    private val testableResources = mContext.orCreateTestableResources
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope

    private lateinit var sizeCalculator: NotificationStackSizeCalculator

@@ -72,7 +78,9 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                lockscreenShadeTransitionController = lockscreenShadeTransitionController,
                mediaDataManager = mediaDataManager,
                testableResources.resources,
                    ResourcesSplitShadeStateController()
                ResourcesSplitShadeStateController(),
                seenNotificationsInteractor = seenNotificationsInteractor,
                scope = testScope,
            )
    }

@@ -85,7 +93,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                rows,
                spaceForNotifications = 0f,
                spaceForShelf = 0f,
                shelfHeight = 0f
                shelfHeight = 0f,
            )

        assertThat(maxNotifications).isEqualTo(0)
@@ -101,7 +109,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                rows,
                spaceForNotifications = Float.MAX_VALUE,
                spaceForShelf = Float.MAX_VALUE,
                shelfHeight
                shelfHeight,
            )

        assertThat(maxNotifications).isEqualTo(numberOfRows)
@@ -137,7 +145,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                listOf(row),
                /* spaceForNotifications= */ 5f,
                /* spaceForShelf= */ 0f,
                /* shelfHeight= */ 0f
                /* shelfHeight= */ 0f,
            )

        assertThat(maxNotifications).isEqualTo(1)
@@ -148,11 +156,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
        setGapHeight(gapHeight)
        val shelfHeight = shelfHeight + dividerHeight
        val spaceForNotifications =
            listOf(
                    rowHeight + dividerHeight,
                    gapHeight + rowHeight + dividerHeight,
                )
                .sum()
            listOf(rowHeight + dividerHeight, gapHeight + rowHeight + dividerHeight).sum()
        val spaceForShelf = gapHeight + dividerHeight + shelfHeight
        val rows =
            listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight))
@@ -162,7 +166,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                rows,
                spaceForNotifications + 1,
                spaceForShelf,
                shelfHeight
                shelfHeight,
            )

        assertThat(maxNotifications).isEqualTo(2)
@@ -173,12 +177,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
        // Each row in separate section.
        setGapHeight(gapHeight)

        val notifSpace =
            listOf(
                    rowHeight,
                    dividerHeight + gapHeight + rowHeight,
                )
                .sum()
        val notifSpace = listOf(rowHeight, dividerHeight + gapHeight + rowHeight).sum()

        val shelfSpace = dividerHeight + gapHeight + shelfHeight
        val spaceUsed = notifSpace + shelfSpace
@@ -209,7 +208,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                rows,
                spaceForNotifications + 1,
                spaceForShelf,
                shelfHeight
                shelfHeight,
            )
        assertThat(maxNotifications).isEqualTo(1)

@@ -252,7 +251,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                visibleIndex = 0,
                previousView = null,
                stack = stackLayout,
                onLockscreen = true
                onLockscreen = true,
            )
        assertThat(space.whenEnoughSpace).isEqualTo(10f)
    }
@@ -272,7 +271,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                visibleIndex = 0,
                previousView = null,
                stack = stackLayout,
                onLockscreen = true
                onLockscreen = true,
            )
        assertThat(space.whenEnoughSpace).isEqualTo(5)
    }
@@ -291,7 +290,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                visibleIndex = 0,
                previousView = null,
                stack = stackLayout,
                onLockscreen = true
                onLockscreen = true,
            )
        assertThat(space.whenSavingSpace).isEqualTo(5)
    }
@@ -311,7 +310,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                visibleIndex = 0,
                previousView = null,
                stack = stackLayout,
                onLockscreen = true
                onLockscreen = true,
            )
        assertThat(space.whenSavingSpace).isEqualTo(5)
    }
@@ -330,7 +329,7 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
                visibleIndex = 0,
                previousView = null,
                stack = stackLayout,
                onLockscreen = false
                onLockscreen = false,
            )
        assertThat(space.whenEnoughSpace).isEqualTo(rowHeight)
        assertThat(space.whenSavingSpace).isEqualTo(rowHeight)
@@ -340,14 +339,14 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() {
        rows: List<ExpandableView>,
        spaceForNotifications: Float,
        spaceForShelf: Float,
        shelfHeight: Float = this.shelfHeight
        shelfHeight: Float = this.shelfHeight,
    ): Int {
        setupChildren(rows)
        return sizeCalculator.computeMaxKeyguardNotifications(
            stackLayout,
            spaceForNotifications,
            spaceForShelf,
            shelfHeight
            shelfHeight,
        )
    }

+13 −10
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.collection.coordinator
import android.annotation.SuppressLint
import android.app.NotificationManager
import androidx.annotation.VisibleForTesting
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.Dumpable
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
@@ -50,7 +51,6 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import com.android.app.tracing.coroutines.launchTraced as launch

/**
 * If the setting is enabled, this will track seen notifications and ensure that they only show in
@@ -74,7 +74,7 @@ constructor(

    private val unseenNotifications = mutableSetOf<NotificationEntry>()
    private var isShadeVisible = false
    private var unseenFilterEnabled = false
    private var minimalismEnabled = false

    override fun attach(pipeline: NotifPipeline) {
        if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) {
@@ -83,7 +83,7 @@ constructor(
        pipeline.addPromoter(unseenNotifPromoter)
        pipeline.addOnBeforeTransformGroupsListener(::pickOutTopUnseenNotifs)
        pipeline.addCollectionListener(collectionListener)
        scope.launch { trackUnseenFilterSettingChanges() }
        scope.launch { trackLockScreenNotificationMinimalismSettingChanges() }
        dumpManager.registerDumpable(this)
    }

@@ -136,12 +136,12 @@ constructor(
        return seenNotificationsInteractor.isLockScreenNotificationMinimalismEnabled()
    }

    private suspend fun trackUnseenFilterSettingChanges() {
    private suspend fun trackLockScreenNotificationMinimalismSettingChanges() {
        // Only filter the seen notifs when the lock screen minimalism feature settings is on.
        minimalismFeatureSettingEnabled().collectLatest { isMinimalismSettingEnabled ->
            // update local field and invalidate if necessary
            if (isMinimalismSettingEnabled != unseenFilterEnabled) {
                unseenFilterEnabled = isMinimalismSettingEnabled
            if (isMinimalismSettingEnabled != minimalismEnabled) {
                minimalismEnabled = isMinimalismSettingEnabled
                unseenNotifications.clear()
                unseenNotifPromoter.invalidateList("unseen setting changed")
            }
@@ -156,21 +156,21 @@ constructor(
    private val collectionListener =
        object : NotifCollectionListener {
            override fun onEntryAdded(entry: NotificationEntry) {
                if (unseenFilterEnabled && !isShadeVisible) {
                if (minimalismEnabled && !isShadeVisible) {
                    logger.logUnseenAdded(entry.key)
                    unseenNotifications.add(entry)
                }
            }

            override fun onEntryUpdated(entry: NotificationEntry) {
                if (unseenFilterEnabled && !isShadeVisible) {
                if (minimalismEnabled && !isShadeVisible) {
                    logger.logUnseenUpdated(entry.key)
                    unseenNotifications.add(entry)
                }
            }

            override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
                if (unseenFilterEnabled && unseenNotifications.remove(entry)) {
                if (minimalismEnabled && unseenNotifications.remove(entry)) {
                    logger.logUnseenRemoved(entry.key)
                }
            }
@@ -178,7 +178,7 @@ constructor(

    private fun pickOutTopUnseenNotifs(list: List<ListEntry>) {
        if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return
        if (!unseenFilterEnabled) return
        if (!minimalismEnabled) return
        // Only ever elevate a top unseen notification on keyguard, not even locked shade
        if (statusBarStateController.state != StatusBarState.KEYGUARD) {
            seenNotificationsInteractor.setTopOngoingNotification(null)
@@ -215,6 +215,7 @@ constructor(
            override fun shouldPromoteToTopLevel(child: NotificationEntry): Boolean =
                when {
                    NotificationMinimalism.isUnexpectedlyInLegacyMode() -> false
                    !minimalismEnabled -> false
                    seenNotificationsInteractor.isTopOngoingNotification(child) -> true
                    !NotificationMinimalism.ungroupTopUnseen -> false
                    else -> seenNotificationsInteractor.isTopUnseenNotification(child)
@@ -225,6 +226,7 @@ constructor(
        object : NotifSectioner("TopOngoing", BUCKET_TOP_ONGOING) {
            override fun isInSection(entry: ListEntry): Boolean {
                if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false
                if (!minimalismEnabled) return false
                return entry.anyEntry { notificationEntry ->
                    seenNotificationsInteractor.isTopOngoingNotification(notificationEntry)
                }
@@ -235,6 +237,7 @@ constructor(
        object : NotifSectioner("TopUnseen", BUCKET_TOP_UNSEEN) {
            override fun isInSection(entry: ListEntry): Boolean {
                if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return false
                if (!minimalismEnabled) return false
                return entry.anyEntry { notificationEntry ->
                    seenNotificationsInteractor.isTopUnseenNotification(notificationEntry)
                }
+41 −17
Original line number Diff line number Diff line
@@ -21,12 +21,14 @@ import android.util.Log
import android.view.View.GONE
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.LockscreenShadeTransitionController
import com.android.systemui.statusbar.StatusBarState.KEYGUARD
import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.domain.interactor.SeenNotificationsInteractor
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
import com.android.systemui.statusbar.notification.shared.NotificationMinimalism
@@ -38,6 +40,9 @@ import javax.inject.Inject
import kotlin.math.max
import kotlin.math.min
import kotlin.properties.Delegates.notNull
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

private const val TAG = "NotifStackSizeCalc"
private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG)
@@ -56,7 +61,9 @@ constructor(
    private val lockscreenShadeTransitionController: LockscreenShadeTransitionController,
    private val mediaDataManager: MediaDataManager,
    @Main private val resources: Resources,
    private val splitShadeStateController: SplitShadeStateController
    private val splitShadeStateController: SplitShadeStateController,
    private val seenNotificationsInteractor: SeenNotificationsInteractor,
    @Application private val scope: CoroutineScope,
) {

    /**
@@ -74,7 +81,7 @@ constructor(

    /** Whether we allow keyguard to show less important notifications above the shelf. */
    private val limitLockScreenToOneImportant
        get() = NotificationMinimalism.isEnabled
        get() = NotificationMinimalism.isEnabled && minimalismSettingEnabled

    /** Minimum space between two notifications, see [calculateGapAndDividerHeight]. */
    private var dividerHeight by notNull<Float>()
@@ -85,8 +92,14 @@ constructor(
     */
    private var saveSpaceOnLockscreen = false

    /** True when the lock screen notification minimalism feature setting is enabled */
    private var minimalismSettingEnabled = false

    init {
        updateResources()
        if (NotificationMinimalism.isEnabled) {
            scope.launch { trackLockScreenNotificationMinimalismSettingChanges() }
        }
    }

    private fun allowedByPolicy(stackHeight: StackHeight): Boolean =
@@ -199,7 +212,7 @@ constructor(
                    canStackFitInSpace(
                        heightResult,
                        notifSpace = notifSpace,
                        shelfSpace = shelfSpace
                        shelfSpace = shelfSpace,
                    ) == FitResult.FIT
            }

@@ -229,7 +242,7 @@ constructor(
                        canStackFitInSpace(
                            heightResult,
                            notifSpace = notifSpace,
                            shelfSpace = shelfSpace
                            shelfSpace = shelfSpace,
                        ) != FitResult.NO_FIT
                }
            log { "\t--- maxNotifications=$maxNotifications" }
@@ -277,7 +290,7 @@ constructor(
    fun computeHeight(
        stack: NotificationStackScrollLayout,
        maxNotifs: Int,
        shelfHeight: Float
        shelfHeight: Float,
    ): Float {
        log { "\n" }
        log { "computeHeight ---" }
@@ -311,7 +324,7 @@ constructor(
    private enum class FitResult {
        FIT,
        FIT_IF_SAVE_SPACE,
        NO_FIT
        NO_FIT,
    }

    data class SpaceNeeded(
@@ -319,7 +332,7 @@ constructor(
        val whenEnoughSpace: Float,

        // Float height of space needed when showing collapsed layout for FSI HUNs.
        val whenSavingSpace: Float
        val whenSavingSpace: Float,
    )

    private data class StackHeight(
@@ -335,9 +348,19 @@ constructor(
        val shelfHeightWithSpaceBefore: Float,

        /** Whether the stack should actually be forced into the shelf before this height. */
        val shouldForceIntoShelf: Boolean
        val shouldForceIntoShelf: Boolean,
    )

    private suspend fun trackLockScreenNotificationMinimalismSettingChanges() {
        if (NotificationMinimalism.isUnexpectedlyInLegacyMode()) return
        seenNotificationsInteractor.isLockScreenNotificationMinimalismEnabled().collectLatest {
            if (it != minimalismSettingEnabled) {
                minimalismSettingEnabled = it
            }
            Log.i(TAG, "minimalismSettingEnabled: $minimalismSettingEnabled")
        }
    }

    private fun computeHeightPerNotificationLimit(
        stack: NotificationStackScrollLayout,
        shelfHeight: Float,
@@ -377,7 +400,7 @@ constructor(
                            stack,
                            previous = currentNotification,
                            current = children[firstViewInShelfIndex],
                            currentIndex = firstViewInShelfIndex
                            currentIndex = firstViewInShelfIndex,
                        )
                    spaceBeforeShelf + shelfHeight
                }
@@ -390,14 +413,15 @@ constructor(
            log {
                "\tcomputeHeightPerNotificationLimit i=$i notifs=$notifications " +
                    "notifsHeightSavingSpace=$notifsWithCollapsedHun" +
                    " shelfWithSpaceBefore=$shelfWithSpaceBefore"
                    " shelfWithSpaceBefore=$shelfWithSpaceBefore" +
                    " limitLockScreenToOneImportant: $limitLockScreenToOneImportant"
            }
            yield(
                StackHeight(
                    notifsHeight = notifications,
                    notifsHeightSavingSpace = notifsWithCollapsedHun,
                    shelfHeightWithSpaceBefore = shelfWithSpaceBefore,
                    shouldForceIntoShelf = counter?.shouldForceIntoShelf() ?: false
                    shouldForceIntoShelf = counter?.shouldForceIntoShelf() ?: false,
                )
            )
        }
@@ -462,6 +486,10 @@ constructor(

    fun dump(pw: PrintWriter, args: Array<out String>) {
        pw.println("NotificationStackSizeCalculator saveSpaceOnLockscreen=$saveSpaceOnLockscreen")
        pw.println(
            "NotificationStackSizeCalculator " +
                "limitLockScreenToOneImportant=$limitLockScreenToOneImportant"
        )
    }

    private fun ExpandableView.isShowable(onLockscreen: Boolean): Boolean {
@@ -484,7 +512,7 @@ constructor(
        stack: NotificationStackScrollLayout,
        previous: ExpandableView?,
        current: ExpandableView?,
        currentIndex: Int
        currentIndex: Int,
    ): Float {
        if (currentIndex == 0) {
            return 0f
@@ -536,11 +564,7 @@ constructor(
        takeWhile(predicate).count() - 1

    /** Counts the number of notifications for each type of bucket */
    data class BucketTypeCounter(
        var ongoing: Int = 0,
        var important: Int = 0,
        var other: Int = 0,
    ) {
    data class BucketTypeCounter(var ongoing: Int = 0, var important: Int = 0, var other: Int = 0) {
        fun incrementForBucket(@PriorityBucket bucket: Int?) {
            when (bucket) {
                BUCKET_MEDIA_CONTROLS,