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

Commit 11908b1a authored by Lyn Han's avatar Lyn Han Committed by Android (Google) Code Review
Browse files

Merge "Count total notif entry for bundle repository" into main

parents dcbfe903 71a05c54
Loading
Loading
Loading
Loading
+137 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2025 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.notification.collection

import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.SetFlagsRule
import android.testing.TestableLooper.RunWithLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.notification.row.data.repository.TEST_BUNDLE_SPEC
import com.android.systemui.statusbar.notification.shared.NotificationBundleUi
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@SmallTest
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@EnableFlags(NotificationBundleUi.FLAG_NAME)
class BundleEntryTest : SysuiTestCase() {
    private lateinit var bundleEntry: BundleEntry
    @get:Rule val setFlagsRule = SetFlagsRule()

    @Before
    fun setUp() {
        bundleEntry = BundleEntry(TEST_BUNDLE_SPEC)
    }

    @Test
    fun testTotalCount_initial_isZero() {
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(0)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_addNotif() {
        bundleEntry.addChild(NotificationEntryBuilder().build())
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(1)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_addGroup() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(2)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_addMultipleGroups() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)

        val groupEntry2 = GroupEntry("key", 0)
        groupEntry2.addChild(NotificationEntryBuilder().build())
        groupEntry2.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry2)

        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(3)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_addNotifAndGroup() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)
        bundleEntry.addChild(NotificationEntryBuilder().build())
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(2)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_removeNotif() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)

        val bundleNotifChild = NotificationEntryBuilder().build()
        bundleEntry.addChild(bundleNotifChild)
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(2)

        bundleEntry.removeChild(bundleNotifChild)
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(1)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_removeGroupChild() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)
        bundleEntry.addChild(NotificationEntryBuilder().build())
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(2)

        groupEntry1.clearChildren()

        // Explicitly call updateTotalCount, which is what ShadeListBuilder does via
        // BundleCoordinator's OnBeforeRenderListListener before rendering.
        bundleEntry.updateTotalCount()
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(1)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun testTotalCount_clearChildren() {
        val groupEntry1 = GroupEntry("key", 0)
        groupEntry1.addChild(NotificationEntryBuilder().build())
        bundleEntry.addChild(groupEntry1)
        bundleEntry.addChild(NotificationEntryBuilder().build())
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(2)

        bundleEntry.clearChildren()
        assertThat(bundleEntry.bundleRepository.numberOfChildren).isEqualTo(0)
    }
}
+24 −0
Original line number Original line Diff line number Diff line
@@ -15,6 +15,7 @@
 */
 */
package com.android.systemui.statusbar.notification.collection
package com.android.systemui.statusbar.notification.collection


import androidx.annotation.VisibleForTesting
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.data.repository.BundleRepository
import com.android.systemui.statusbar.notification.row.data.repository.BundleRepository
import java.util.Collections
import java.util.Collections
@@ -47,16 +48,19 @@ class BundleEntry(spec: BundleSpec) : PipelineEntry(spec.key) {
    @InternalNotificationsApi
    @InternalNotificationsApi
    fun addChild(child: ListEntry) {
    fun addChild(child: ListEntry) {
        _children.add(child)
        _children.add(child)
        updateTotalCount()
    }
    }


    @InternalNotificationsApi
    @InternalNotificationsApi
    fun removeChild(child: ListEntry) {
    fun removeChild(child: ListEntry) {
        _children.remove(child)
        _children.remove(child)
        updateTotalCount()
    }
    }


    @InternalNotificationsApi
    @InternalNotificationsApi
    fun clearChildren() {
    fun clearChildren() {
        _children.clear()
        _children.clear()
        updateTotalCount()
    }
    }


    override fun asListEntry(): ListEntry? {
    override fun asListEntry(): ListEntry? {
@@ -74,4 +78,24 @@ class BundleEntry(spec: BundleSpec) : PipelineEntry(spec.key) {
     */
     */
    val isClearable: Boolean
    val isClearable: Boolean
        get() = _children.all { it.representativeEntry?.sbn?.isClearable != false }
        get() = _children.all { it.representativeEntry?.sbn?.isClearable != false }

    /**
     * The total count of [NotificationEntry]s within bundle. Notification updates trigger
     * pipeline rebuilds, so updates to group children will be reflected in this count.
     */
    @VisibleForTesting
    fun updateTotalCount() {
        var count = 0
        for (child in _children) {
            when (child) {
                is NotificationEntry -> {
                    count++
                }
                is GroupEntry -> {
                    count += child.getChildren().size
                }
            }
        }
        bundleRepository.numberOfChildren = count
    }
}
}
+7 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.PipelineEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifBundler
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifBundler
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
@@ -168,11 +169,17 @@ constructor(
            }
            }
        }
        }


    private val bundleCountUpdater = OnBeforeRenderListListener { entries ->
        entries.filterIsInstance<BundleEntry>()
            .forEach(BundleEntry::updateTotalCount)
    }

    override fun attach(pipeline: NotifPipeline) {
    override fun attach(pipeline: NotifPipeline) {
        if (NotificationBundleUi.isEnabled) {
        if (NotificationBundleUi.isEnabled) {
            pipeline.setNotifBundler(bundler)
            pipeline.setNotifBundler(bundler)
            pipeline.addOnBeforeFinalizeFilterListener(this::inflateAllBundleEntries)
            pipeline.addOnBeforeFinalizeFilterListener(this::inflateAllBundleEntries)
            pipeline.addFinalizeFilter(bundleFilter)
            pipeline.addFinalizeFilter(bundleFilter)
            pipeline.addOnBeforeRenderListListener(bundleCountUpdater)
        }
        }
    }
    }