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

Commit 0ee71845 authored by Lyn Han's avatar Lyn Han
Browse files

Dedup smart reply updates for bubble flyout [DO NOT MERGE]

[Cherrypicked from master]

Smart reply updates are not visually interruptive and bubbles should not
show flyout for them, since flyout text remains the same.

1) Modify NoMan.isVisuallyInterruptive to skip evaluation of fields
irrelevant to bubbles

2) Modify NotificationComparator to rank interruptive notifs higher

3) Pipe bool (isInterruptive) from system_process to SysUI
	NoMan --- set bool on notif record and ranking
	Ranking --- parcel bool for cross-process transport
	SysUI notif entry --- get bool from ranking
	SysUI bubble data --- on notif entry update, suppress flyout if isInterruptive=false

	Considered adding "isInterruptive" bool to StatusBarNotification.
	Did not because "visually-interruptive" is additional information that the
	system figured out and SBNs should be limited to info from the app.

4) NoMan --- schedule ranking update if interruptive changes for bubble

Fixes: 138755533
Test: manual - send one sms => flyout appears once
Test: manual - send multiple sms in a row => flyout appears for each one
Test: atest FrameworksUiServicesTests
Test: atest NotificationComparatorTest
Test: atest SystemUITests
Change-Id: Id4b855054689ee73a109bb7cd18004531b41f28c
(cherry picked from commit 0dddc61824d091e48962e36939828cae3cde2aa9)
parent 39195ba2
Loading
Loading
Loading
Loading
+13 −2
Original line number Diff line number Diff line
@@ -1514,6 +1514,7 @@ public abstract class NotificationListenerService extends Service {
        private ArrayList<Notification.Action> mSmartActions;
        private ArrayList<CharSequence> mSmartReplies;
        private boolean mCanBubble;
        private boolean mVisuallyInterruptive;

        private static final int PARCEL_VERSION = 2;

@@ -1545,6 +1546,7 @@ public abstract class NotificationListenerService extends Service {
            out.writeTypedList(mSmartActions, flags);
            out.writeCharSequenceList(mSmartReplies);
            out.writeBoolean(mCanBubble);
            out.writeBoolean(mVisuallyInterruptive);
        }

        /** @hide */
@@ -1577,6 +1579,7 @@ public abstract class NotificationListenerService extends Service {
            mSmartActions = in.createTypedArrayList(Notification.Action.CREATOR);
            mSmartReplies = in.readCharSequenceList();
            mCanBubble = in.readBoolean();
            mVisuallyInterruptive = in.readBoolean();
        }


@@ -1763,6 +1766,11 @@ public abstract class NotificationListenerService extends Service {
            return mCanBubble;
        }

        /** @hide */
        public boolean visuallyInterruptive() {
            return mVisuallyInterruptive;
        }

        /** @hide */
        public boolean isNoisy() {
            return mNoisy;
@@ -1779,7 +1787,8 @@ public abstract class NotificationListenerService extends Service {
                ArrayList<SnoozeCriterion> snoozeCriteria, boolean showBadge,
                int userSentiment, boolean hidden, long lastAudiblyAlertedMs,
                boolean noisy, ArrayList<Notification.Action> smartActions,
                ArrayList<CharSequence> smartReplies, boolean canBubble) {
                ArrayList<CharSequence> smartReplies, boolean canBubble,
                boolean visuallyInterruptive) {
            mKey = key;
            mRank = rank;
            mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW;
@@ -1800,6 +1809,7 @@ public abstract class NotificationListenerService extends Service {
            mSmartActions = smartActions;
            mSmartReplies = smartReplies;
            mCanBubble = canBubble;
            mVisuallyInterruptive = visuallyInterruptive;
        }

        /**
@@ -1824,7 +1834,8 @@ public abstract class NotificationListenerService extends Service {
                    other.mNoisy,
                    other.mSmartActions,
                    other.mSmartReplies,
                    other.mCanBubble);
                    other.mCanBubble,
                    other.mVisuallyInterruptive);
        }

        /**
+4 −0
Original line number Diff line number Diff line
@@ -184,6 +184,8 @@ public class BubbleData {
            Log.d(TAG, "notificationEntryUpdated: " + entry);
        }
        Bubble bubble = getBubbleWithKey(entry.key);
        suppressFlyout = !entry.isVisuallyInterruptive || suppressFlyout;

        if (bubble == null) {
            // Create a new bubble
            bubble = new Bubble(mContext, entry);
@@ -193,8 +195,10 @@ public class BubbleData {
        } else {
            // Updates an existing bubble
            bubble.updateEntry(entry);
            bubble.setSuppressFlyout(suppressFlyout);
            doUpdate(bubble);
        }

        if (bubble.shouldAutoExpand()) {
            setSelectedBubbleInternal(bubble);
            if (!mExpanded) {
+7 −0
Original line number Diff line number Diff line
@@ -154,6 +154,12 @@ public final class NotificationEntry {
     */
    public boolean canBubble;

    /**
     * Whether this notification has changed in visual appearance since the previous post.
     * New notifications are  interruptive by default.
     */
    public boolean isVisuallyInterruptive;

    /**
     * Whether this notification is shown to the user as a high priority notification: visible on
     * the lock screen/status bar and in the top section in the shade.
@@ -196,6 +202,7 @@ public final class NotificationEntry {
        suppressedVisualEffects = ranking.getSuppressedVisualEffects();
        suspended = ranking.isSuspended();
        canBubble = ranking.canBubble();
        isVisuallyInterruptive = ranking.visuallyInterruptive();
    }

    public void setInterruption() {
+2 −2
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
                    0,
                    NotificationManager.IMPORTANCE_DEFAULT,
                    null, null,
                    null, null, null, true, sentiment, false, -1, false, null, null, false);
                    null, null, null, true, sentiment, false, -1, false, null, null, false, false);
            return true;
        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
    }
@@ -201,7 +201,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
                    null, null,
                    null, null, null, true,
                    NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL, false, -1,
                    false, smartActions, null, false);
                    false, smartActions, null, false, false);
            return true;
        }).when(mRankingMap).getRanking(eq(key), any(NotificationListenerService.Ranking.class));
    }
+4 −1
Original line number Diff line number Diff line
@@ -623,6 +623,7 @@ public class NotificationDataTest extends SysuiTestCase {
        public static final String OVERRIDE_SMART_ACTIONS = "sa";
        public static final String OVERRIDE_SMART_REPLIES = "sr";
        public static final String OVERRIDE_BUBBLE = "cb";
        public static final String OVERRIDE_VISUALLY_INTERRUPTIVE = "vi";

        public Map<String, Bundle> rankingOverrides = new HashMap<>();

@@ -683,7 +684,9 @@ public class NotificationDataTest extends SysuiTestCase {
                        overrides.containsKey(OVERRIDE_SMART_REPLIES)
                                ? overrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
                                : currentReplies,
                        overrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
                        overrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()),
                        overrides.getBoolean(OVERRIDE_VISUALLY_INTERRUPTIVE,
                                outRanking.visuallyInterruptive()));
            }
            return true;
        }
Loading