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

Commit 01696728 authored by Danning Chen's avatar Danning Chen Committed by Automerger Merge Worker
Browse files

Merge "Cache the shortcut when the associated notifications are posted and...

Merge "Cache the shortcut when the associated notifications are posted and uncache when they are gone" into rvc-dev am: 7095f4c9 am: 24e69902

Change-Id: I2cb0dcba900c087d833ae9b5c5882760b9f0cab7
parents c8e5eafb 24e69902
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -5699,6 +5699,14 @@ public class NotificationManagerService extends SystemService {
            return;
        }

        if (info != null) {
            // Cache the shortcut synchronously after the associated notification is posted in case
            // the app unpublishes this shortcut immediately after posting the notification. If the
            // user does not modify the notification settings on this conversation, the shortcut
            // will be uncached by People Service when all the associated notifications are removed.
            mShortcutHelper.cacheShortcut(info, user);
        }

        // Whitelist pending intents.
        if (notification.allPendingIntents != null) {
            final int intentCount = notification.allPendingIntents.size();
+12 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.internal.annotations.VisibleForTesting;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

@@ -185,6 +186,17 @@ public class ShortcutHelper {
        }
    }

    /**
     * Caches the given shortcut in Shortcut Service.
     */
    void cacheShortcut(ShortcutInfo shortcutInfo, UserHandle user) {
        if (shortcutInfo.isLongLived() && !shortcutInfo.isCached()) {
            mShortcutServiceInternal.cacheShortcuts(user.getIdentifier(), "android",
                    shortcutInfo.getPackage(), Collections.singletonList(shortcutInfo.getId()),
                    shortcutInfo.getUserId());
        }
    }

    /**
     * Shortcut based bubbles require some extra work to listen for shortcut changes.
     *
+12 −0
Original line number Diff line number Diff line
@@ -62,6 +62,8 @@ public class ConversationInfo {

    private static final int FLAG_DEMOTED = 1 << 6;

    private static final int FLAG_NOTIFICATION_SETTING_CHANGED = 1 << 7;

    @IntDef(flag = true, prefix = {"FLAG_"}, value = {
            FLAG_IMPORTANT,
            FLAG_NOTIFICATION_SILENCED,
@@ -70,6 +72,7 @@ public class ConversationInfo {
            FLAG_PERSON_BOT,
            FLAG_CONTACT_STARRED,
            FLAG_DEMOTED,
            FLAG_NOTIFICATION_SETTING_CHANGED,
    })
    @Retention(RetentionPolicy.SOURCE)
    private @interface ConversationFlags {
@@ -185,6 +188,11 @@ public class ConversationInfo {
        return hasConversationFlags(FLAG_CONTACT_STARRED);
    }

    /** Whether the conversation's notification setting has ever been changed by the user. */
    boolean isNotificationSettingChanged() {
        return hasConversationFlags(FLAG_NOTIFICATION_SETTING_CHANGED);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
@@ -491,6 +499,10 @@ public class ConversationInfo {
            return setConversationFlag(FLAG_CONTACT_STARRED, value);
        }

        Builder setNotificationSettingChanged(boolean value) {
            return setConversationFlag(FLAG_NOTIFICATION_SETTING_CHANGED, value);
        }

        private Builder setConversationFlag(@ConversationFlags int flags, boolean value) {
            if (value) {
                return addConversationFlags(flags);
+57 −21
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.people.data;

import static android.app.NotificationChannel.USER_LOCKED_ALLOW_BUBBLE;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -56,6 +58,7 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telecom.TelecomManager;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
@@ -482,7 +485,8 @@ public class DataManager {
    }

    @Nullable
    private EventHistoryImpl getEventHistoryIfEligible(StatusBarNotification sbn) {
    private PackageData getPackageIfConversationExists(StatusBarNotification sbn,
            Consumer<ConversationInfo> conversationConsumer) {
        Notification notification = sbn.getNotification();
        String shortcutId = notification.getShortcutId();
        if (shortcutId == null) {
@@ -490,12 +494,16 @@ public class DataManager {
        }
        PackageData packageData = getPackage(sbn.getPackageName(),
                sbn.getUser().getIdentifier());
        if (packageData == null
                || packageData.getConversationStore().getConversation(shortcutId) == null) {
        if (packageData == null) {
            return null;
        }
        return packageData.getEventStore().getOrCreateEventHistory(
                EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
        ConversationInfo conversationInfo =
                packageData.getConversationStore().getConversation(shortcutId);
        if (conversationInfo == null) {
            return null;
        }
        conversationConsumer.accept(conversationInfo);
        return packageData;
    }

    @VisibleForTesting
@@ -745,10 +753,19 @@ public class DataManager {
    /** Listener for the notifications and their settings changes. */
    private class NotificationListener extends NotificationListenerService {

        // Conversation shortcut ID -> Number of active notifications
        private final Map<String, Integer> mActiveNotifCounts = new ArrayMap<>();

        @Override
        public void onNotificationPosted(StatusBarNotification sbn) {
            EventHistoryImpl eventHistory = getEventHistoryIfEligible(sbn);
            if (eventHistory != null) {
            String shortcutId = sbn.getNotification().getShortcutId();
            PackageData packageData = getPackageIfConversationExists(sbn, conversationInfo -> {
                mActiveNotifCounts.merge(shortcutId, 1, Integer::sum);
            });

            if (packageData != null) {
                EventHistoryImpl eventHistory = packageData.getEventStore().getOrCreateEventHistory(
                        EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
                eventHistory.addEvent(new Event(sbn.getPostTime(), Event.TYPE_NOTIFICATION_POSTED));
            }
        }
@@ -756,13 +773,32 @@ public class DataManager {
        @Override
        public void onNotificationRemoved(StatusBarNotification sbn, RankingMap rankingMap,
                int reason) {
            if (reason != REASON_CLICK) {
                return;
            String shortcutId = sbn.getNotification().getShortcutId();
            PackageData packageData = getPackageIfConversationExists(sbn, conversationInfo -> {
                int count = mActiveNotifCounts.getOrDefault(shortcutId, 0) - 1;
                if (count <= 0) {
                    mActiveNotifCounts.remove(sbn.getNotification().getShortcutId());
                    // The shortcut was cached by Notification Manager synchronously when the
                    // associated notification was posted. Uncache it here when all the associated
                    // notifications are removed.
                    if (conversationInfo.isShortcutCached()
                            && !conversationInfo.isNotificationSettingChanged()) {
                        int userId = sbn.getUser().getIdentifier();
                        mShortcutServiceInternal.uncacheShortcuts(userId,
                                mContext.getPackageName(), sbn.getPackageName(),
                                Collections.singletonList(conversationInfo.getShortcutId()),
                                userId);
                    }
            EventHistoryImpl eventHistory = getEventHistoryIfEligible(sbn);
            if (eventHistory == null) {
                } else {
                    mActiveNotifCounts.put(shortcutId, count);
                }
            });

            if (reason != REASON_CLICK || packageData == null) {
                return;
            }
            EventHistoryImpl eventHistory = packageData.getEventStore().getOrCreateEventHistory(
                    EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
            long currentTime = System.currentTimeMillis();
            eventHistory.addEvent(new Event(currentTime, Event.TYPE_NOTIFICATION_OPENED));
        }
@@ -780,7 +816,16 @@ public class DataManager {
            if (conversationInfo == null) {
                return;
            }
            boolean isNotificationSettingChanged =
                    conversationInfo.isImportant() != channel.isImportantConversation()
                            || conversationInfo.isDemoted() != channel.isDemoted()
                            || channel.hasUserSetImportance()
                            || (channel.getUserLockedFields() & USER_LOCKED_ALLOW_BUBBLE) != 0;
            ConversationInfo.Builder builder = new ConversationInfo.Builder(conversationInfo);
            if (modificationType == NOTIFICATION_CHANNEL_OR_GROUP_UPDATED
                    && isNotificationSettingChanged) {
                builder.setNotificationSettingChanged(true);
            }
            switch (modificationType) {
                case NOTIFICATION_CHANNEL_OR_GROUP_ADDED:
                case NOTIFICATION_CHANNEL_OR_GROUP_UPDATED:
@@ -802,15 +847,6 @@ public class DataManager {
                    break;
            }
            conversationStore.addOrUpdate(builder.build());

            if (modificationType == NOTIFICATION_CHANNEL_OR_GROUP_UPDATED
                    && conversationInfo.isShortcutLongLived()
                    && !conversationInfo.isShortcutCached()) {
                mShortcutServiceInternal.cacheShortcuts(user.getIdentifier(),
                        mContext.getPackageName(), pkg,
                        Collections.singletonList(conversationInfo.getShortcutId()),
                        user.getIdentifier());
            }
        }
    }

+5 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ public final class ConversationInfoTest {
                .setPersonImportant(true)
                .setPersonBot(true)
                .setContactStarred(true)
                .setNotificationSettingChanged(true)
                .build();

        assertEquals(SHORTCUT_ID, conversationInfo.getShortcutId());
@@ -70,6 +71,7 @@ public final class ConversationInfoTest {
        assertTrue(conversationInfo.isPersonImportant());
        assertTrue(conversationInfo.isPersonBot());
        assertTrue(conversationInfo.isContactStarred());
        assertTrue(conversationInfo.isNotificationSettingChanged());
    }

    @Test
@@ -92,6 +94,7 @@ public final class ConversationInfoTest {
        assertFalse(conversationInfo.isPersonImportant());
        assertFalse(conversationInfo.isPersonBot());
        assertFalse(conversationInfo.isContactStarred());
        assertFalse(conversationInfo.isNotificationSettingChanged());
    }

    @Test
@@ -109,6 +112,7 @@ public final class ConversationInfoTest {
                .setPersonImportant(true)
                .setPersonBot(true)
                .setContactStarred(true)
                .setNotificationSettingChanged(true)
                .build();

        ConversationInfo destination = new ConversationInfo.Builder(source)
@@ -128,5 +132,6 @@ public final class ConversationInfoTest {
        assertTrue(destination.isPersonImportant());
        assertTrue(destination.isPersonBot());
        assertFalse(destination.isContactStarred());
        assertTrue(destination.isNotificationSettingChanged());
    }
}
Loading