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

Commit e0a8d08b authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Fix logic for person level of group summaries

And delete some unused code

Test: PeopleNotificationIdentifierTest
Fixes: 441151799
Flag: EXEMPT BUG_FIX
Change-Id: I9e79bf786ec582367d68c60ce1547e4ca90ad92a
parent f5ad0485
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -52,10 +52,8 @@ import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
import com.android.systemui.statusbar.notification.people.NotificationPersonExtractor;
import com.android.systemui.util.DeviceConfigProxyFake;

import org.jetbrains.annotations.NotNull;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+3 −6
Original line number Diff line number Diff line
@@ -16,14 +16,11 @@

package com.android.systemui.statusbar.notification.collection.coordinator

import android.app.Flags
import android.app.NotificationChannel
import android.app.NotificationChannel.SYSTEM_RESERVED_IDS
import android.app.NotificationManager.IMPORTANCE_DEFAULT
import android.app.NotificationManager.IMPORTANCE_HIGH
import android.app.NotificationManager.IMPORTANCE_LOW
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -91,13 +88,13 @@ class ConversationCoordinatorTest : SysuiTestCase() {
    fun setUp() {
        MockitoAnnotations.initMocks(this)
        peopleNotificationIdentifier =
            PeopleNotificationIdentifierImpl(mock(), GroupMembershipManagerImpl())
            PeopleNotificationIdentifierImpl(GroupMembershipManagerImpl())
        coordinator =
            ConversationCoordinator(
                peopleNotificationIdentifier,
                conversationIconManager,
                HighPriorityProvider(peopleNotificationIdentifier, GroupMembershipManagerImpl()),
                headerController
                headerController,
            )

        coordinator.attach(pipeline)
@@ -234,7 +231,7 @@ class ConversationCoordinatorTest : SysuiTestCase() {

    private fun makeEntryOfPeopleType(
        @PeopleNotificationType type: Int,
        buildBlock: NotificationEntryBuilder.() -> Unit = {}
        buildBlock: NotificationEntryBuilder.() -> Unit = {},
    ): NotificationEntry {
        val channel: NotificationChannel = mock()
        whenever(channel.isImportantConversation).thenReturn(type == TYPE_IMPORTANT_PERSON)
+62 −113
Original line number Diff line number Diff line
@@ -15,148 +15,97 @@
 */
package com.android.systemui.statusbar.notification.people

import android.app.Notification
import android.app.NotificationChannel
import android.content.pm.ShortcutInfo
import android.service.notification.NotificationListenerService.Ranking
import android.service.notification.StatusBarNotification
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.RankingBuilder
import com.android.systemui.statusbar.notification.collection.BundleEntry
import com.android.systemui.statusbar.notification.collection.BundleSpec
import com.android.systemui.statusbar.notification.collection.GroupEntry
import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_FULL_PERSON
import com.android.systemui.statusbar.notification.collection.InternalNotificationsApi
import com.android.systemui.statusbar.notification.collection.buildSummaryNotificationEntry
import com.android.systemui.statusbar.notification.collection.makeEntryOfPeopleType
import com.android.systemui.statusbar.notification.collection.render.groupMembershipManager
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_IMPORTANT_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_PERSON
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mockito.Mockito.mock


@SmallTest
@RunWith(AndroidJUnit4::class)
class PeopleNotificationIdentifierTest : SysuiTestCase() {

    private val kosmos = testKosmos()
    private lateinit var underTest: PeopleNotificationIdentifierImpl

    private val summary1 = notificationEntry("foo", 1, summary = true)
    private val summary2 = notificationEntry("bar", 1, summary = true)
    private val entries =
        listOf<GroupEntry>(
            GroupEntryBuilder()
                .setSummary(summary1)
                .setChildren(
                    listOf(
                        notificationEntry("foo", 2),
                        notificationEntry("foo", 3),
                        notificationEntry("foo", 4)
                    )
                )
                .build(),
            GroupEntryBuilder()
                .setSummary(summary2)
                .setChildren(
                    listOf(
                        notificationEntry("bar", 2),
                        notificationEntry("bar", 3),
                        notificationEntry("bar", 4)
                    )
                )
                .build()
        )

    private fun notificationEntry(
        pkg: String,
        id: Int,
        summary: Boolean = false
    ): NotificationEntry {
        val sbn = mock(StatusBarNotification::class.java)
        Mockito.`when`(sbn.key).thenReturn("key")
        Mockito.`when`(sbn.notification).thenReturn(mock(Notification::class.java))
        if (summary)
            Mockito.`when`(sbn.notification.isGroupSummary).thenReturn(true)
        return NotificationEntryBuilder().setPkg(pkg)
            .setId(id)
            .setSbn(sbn)
            .build().apply {
                row = mock(ExpandableNotificationRow::class.java)
            }
    }

    private fun personRanking(entry: NotificationEntry, personType: Int): Ranking {
        val channel = NotificationChannel("person", "person", 4)
        channel.setConversationId("parent", "person")
        channel.setImportantConversation(true)

        val br = RankingBuilder(entry.ranking)

        when (personType) {
            TYPE_NON_PERSON -> br.setIsConversation(false)
            TYPE_PERSON -> {
                br.setIsConversation(true)
                br.setShortcutInfo(null)
    @Before
    fun setUp() {
        underTest = PeopleNotificationIdentifierImpl(kosmos.groupMembershipManager)
    }

            TYPE_IMPORTANT_PERSON -> {
                br.setIsConversation(true)
                br.setShortcutInfo(mock(ShortcutInfo::class.java))
                br.setChannel(channel)
    @Test
    fun getPeopleNotificationType_entryIsImportant() {
        assertThat(
                underTest.getPeopleNotificationType(
                    kosmos.makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)
                )
            )
            .isEqualTo(TYPE_IMPORTANT_PERSON)
    }

            else -> {
                br.setIsConversation(true)
                br.setShortcutInfo(mock(ShortcutInfo::class.java))
            }
        }
    @Test
    fun getPeopleNotificationType_importantChild() {
        val child = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val child2 = kosmos.makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)
        val summary = kosmos.buildSummaryNotificationEntry(listOf(child, child2))

        return br.build()
        assertThat(underTest.getPeopleNotificationType(summary)).isEqualTo(TYPE_IMPORTANT_PERSON)
    }

    @Before
    fun setUp() {
        val personExtractor = object : NotificationPersonExtractor {
            public override fun isPersonNotification(sbn: StatusBarNotification): Boolean {
                return true
            }
        }
    @Test
    fun getPeopleNotificationType_noImportantChildren() {
        val child = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val child2 = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val summary = kosmos.buildSummaryNotificationEntry(listOf(child, child2))

        underTest = PeopleNotificationIdentifierImpl(
            personExtractor,
            GroupMembershipManagerImpl()
        )
        assertThat(underTest.getPeopleNotificationType(summary)).isEqualTo(TYPE_PERSON)
    }

    private val Ranking.personTypeInfo
        get() = when {
            !isConversation -> TYPE_NON_PERSON
            conversationShortcutInfo == null -> TYPE_PERSON
            channel?.isImportantConversation == true -> TYPE_IMPORTANT_PERSON
            else -> TYPE_FULL_PERSON
    @Test
    fun getPeopleNotificationType_nestedGroup() {
        val child = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val innerSummary = kosmos.buildSummaryNotificationEntry(listOf(child))
        val child1 = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val child2 = kosmos.makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)
        val summary = kosmos.buildSummaryNotificationEntry(listOf(child1, child2, innerSummary))

        assertThat(underTest.getPeopleNotificationType(summary)).isEqualTo(TYPE_IMPORTANT_PERSON)
    }

    @Test
    fun getPeopleNotificationType_entryIsImportant() {
        summary1.setRanking(personRanking(summary1, TYPE_IMPORTANT_PERSON))

        assertThat(underTest.getPeopleNotificationType(summary1)).isEqualTo(TYPE_IMPORTANT_PERSON)
    fun getPeopleNotificationType_circularGroup() {
        val child = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val innerSummary = kosmos.buildSummaryNotificationEntry(listOf(child))
        val child1 = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val child2 = kosmos.makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)
        val summary = kosmos.buildSummaryNotificationEntry(listOf(child1, child2, innerSummary))
        (summary.parent as? GroupEntry)?.rawChildren?.add(summary)

        assertThat(underTest.getPeopleNotificationType(summary)).isEqualTo(TYPE_IMPORTANT_PERSON)
    }

    @OptIn(InternalNotificationsApi::class)
    @Test
    fun getPeopleNotificationType_importantChild() {
        entries.get(0).getChildren().get(0).setRanking(
            personRanking(entries.get(0).getChildren().get(0), TYPE_IMPORTANT_PERSON)
        )

        assertThat(entries.get(0).summary?.let { underTest.getPeopleNotificationType(it) })
            .isEqualTo(TYPE_IMPORTANT_PERSON)
    fun getPeopleNotificationType_groupInBundle() {
        val bundleEntry = BundleEntry(BundleSpec.NEWS)
        val child1 = kosmos.makeEntryOfPeopleType(TYPE_PERSON)
        val child2 = kosmos.makeEntryOfPeopleType(TYPE_IMPORTANT_PERSON)
        val summary = kosmos.buildSummaryNotificationEntry(listOf(child1, child2))
        summary.parent?.parent = bundleEntry
        bundleEntry.addChild(summary)

        assertThat(underTest.getPeopleNotificationType(summary)).isEqualTo(TYPE_IMPORTANT_PERSON)
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -186,7 +186,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
    @Test
    @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
    public void testRecreateNotificationHeader_hasHeader() {
        mChildrenContainer.recreateNotificationHeader(null, false);
        mChildrenContainer.recreateNotificationHeader(null);
        Assert.assertNotNull("Children container must have a header after recreation",
                mChildrenContainer.getCurrentHeaderView());
    }
+0 −49
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.people

import android.service.notification.StatusBarNotification
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.NotificationPersonExtractorPlugin
import com.android.systemui.statusbar.policy.ExtensionController
import javax.inject.Inject

interface NotificationPersonExtractor {
    fun isPersonNotification(sbn: StatusBarNotification): Boolean
}

@SysUISingleton
class NotificationPersonExtractorPluginBoundary @Inject constructor(
    extensionController: ExtensionController
) : NotificationPersonExtractor {

    private var plugin: NotificationPersonExtractorPlugin? = null

    init {
        plugin = extensionController
                .newExtension(NotificationPersonExtractorPlugin::class.java)
                .withPlugin(NotificationPersonExtractorPlugin::class.java)
                .withCallback { extractor ->
                    plugin = extractor
                }
                .build()
                .get()
    }

    override fun isPersonNotification(sbn: StatusBarNotification): Boolean =
            plugin?.isPersonNotification(sbn) ?: false
}
Loading