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

Commit 979fe90f authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Add cached state to prevent blocking calls from SysUI->Shell" into sc-dev

parents fcf3dca8 523ab2ab
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -284,6 +284,15 @@ public class Bubble implements BubbleViewProvider {
        return mTitle;
    }

    /**
     * @return the ShortcutInfo id if it exists, or the metadata shortcut id otherwise.
     */
    String getShortcutId() {
        return getShortcutInfo() != null
                ? getShortcutInfo().getId()
                : getMetadataShortcutId();
    }

    String getMetadataShortcutId() {
        return mMetadataShortcutId;
    }
+131 −31
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
@@ -265,15 +266,7 @@ public class BubbleController {

    public void initialize() {
        mBubbleData.setListener(mBubbleDataListener);
        mBubbleData.setSuppressionChangedListener(bubble -> {
            // Make sure NoMan knows suppression state so that anyone querying it can tell.
            try {
                mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
                        !bubble.showInShade(), bubble.isSuppressed());
            } catch (RemoteException e) {
                // Bad things have happened
            }
        });
        mBubbleData.setSuppressionChangedListener(this::onBubbleNotificationSuppressionChanged);

        mBubbleData.setPendingIntentCancelledListener(bubble -> {
            if (bubble.getBubbleIntent() == null) {
@@ -401,6 +394,11 @@ public class BubbleController {
        return mImpl;
    }

    @VisibleForTesting
    public BubblesImpl.CachedState getImplCachedState() {
        return mImpl.mCachedState;
    }

    public ShellExecutor getMainExecutor() {
        return mMainExecutor;
    }
@@ -500,6 +498,18 @@ public class BubbleController {
        updateStack();
    }

    @VisibleForTesting
    public void onBubbleNotificationSuppressionChanged(Bubble bubble) {
        // Make sure NoMan knows suppression state so that anyone querying it can tell.
        try {
            mBarService.onBubbleNotificationSuppressionChanged(bubble.getKey(),
                    !bubble.showInShade(), bubble.isSuppressed());
        } catch (RemoteException e) {
            // Bad things have happened
        }
        mImpl.mCachedState.updateBubbleSuppressedState(bubble);
    }

    /** Called when the current user changes. */
    @VisibleForTesting
    public void onUserChanged(int newUserId) {
@@ -808,11 +818,6 @@ public class BubbleController {
        }
    }

    private boolean isBubbleExpanded(String key) {
        return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null
                && mBubbleData.getSelectedBubble().getKey().equals(key);
    }

    /** Promote the provided bubble from the overflow view. */
    public void promoteBubbleFromOverflow(Bubble bubble) {
        mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
@@ -1191,6 +1196,9 @@ public class BubbleController {

            mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate");
            updateStack();

            // Update the cached state for queries from SysUI
            mImpl.mCachedState.update(update);
        }
    };

@@ -1364,25 +1372,124 @@ public class BubbleController {
    }

    private class BubblesImpl implements Bubbles {
        // Up-to-date cached state of bubbles data for SysUI to query from the calling thread
        @VisibleForTesting
        public class CachedState {
            private boolean mIsStackExpanded;
            private String mSelectedBubbleKey;
            private HashSet<String> mSuppressedBubbleKeys = new HashSet<>();
            private HashMap<String, String> mSuppressedGroupToNotifKeys = new HashMap<>();
            private HashMap<String, Bubble> mShortcutIdToBubble = new HashMap<>();

            private ArrayList<Bubble> mTmpBubbles = new ArrayList<>();

            /**
             * Updates the cached state based on the last full BubbleData change.
             */
            synchronized void update(BubbleData.Update update) {
                if (update.selectionChanged) {
                    mSelectedBubbleKey = update.selectedBubble != null
                            ? update.selectedBubble.getKey()
                            : null;
                }
                if (update.expandedChanged) {
                    mIsStackExpanded = update.expanded;
                }
                if (update.suppressedSummaryChanged) {
                    String summaryKey =
                            mBubbleData.getSummaryKey(update.suppressedSummaryGroup);
                    if (summaryKey != null) {
                        mSuppressedGroupToNotifKeys.put(update.suppressedSummaryGroup, summaryKey);
                    } else {
                        mSuppressedGroupToNotifKeys.remove(update.suppressedSummaryGroup);
                    }
                }

                mTmpBubbles.clear();
                mTmpBubbles.addAll(update.bubbles);
                mTmpBubbles.addAll(update.overflowBubbles);

                mSuppressedBubbleKeys.clear();
                mShortcutIdToBubble.clear();
                for (Bubble b : mTmpBubbles) {
                    mShortcutIdToBubble.put(b.getShortcutId(), b);
                    updateBubbleSuppressedState(b);
                }
            }

            /**
             * Updates a specific bubble suppressed state.  This is used mainly because notification
             * suppression changes don't go through the same BubbleData update mechanism.
             */
            synchronized void updateBubbleSuppressedState(Bubble b) {
                if (!b.showInShade()) {
                    mSuppressedBubbleKeys.add(b.getKey());
                } else {
                    mSuppressedBubbleKeys.remove(b.getKey());
                }
            }

            public synchronized boolean isStackExpanded() {
                return mIsStackExpanded;
            }

            public synchronized boolean isBubbleExpanded(String key) {
                return mIsStackExpanded && key.equals(mSelectedBubbleKey);
            }

            public synchronized boolean isBubbleNotificationSuppressedFromShade(String key,
                    String groupKey) {
                return mSuppressedBubbleKeys.contains(key)
                        || (mSuppressedGroupToNotifKeys.containsKey(groupKey)
                                && key.equals(mSuppressedGroupToNotifKeys.get(groupKey)));
            }

            @Nullable
            public synchronized Bubble getBubbleWithShortcutId(String id) {
                return mShortcutIdToBubble.get(id);
            }

            synchronized void dump(PrintWriter pw) {
                pw.println("BubbleImpl.CachedState state:");

                pw.println("mIsStackExpanded: " + mIsStackExpanded);
                pw.println("mSelectedBubbleKey: " + mSelectedBubbleKey);

                pw.print("mSuppressedBubbleKeys: ");
                pw.println(mSuppressedBubbleKeys.size());
                for (String key : mSuppressedBubbleKeys) {
                    pw.println("   suppressing: " + key);
                }

                pw.print("mSuppressedGroupToNotifKeys: ");
                pw.println(mSuppressedGroupToNotifKeys.size());
                for (String key : mSuppressedGroupToNotifKeys.keySet()) {
                    pw.println("   suppressing: " + key);
                }
            }
        }

        private CachedState mCachedState = new CachedState();

        @Override
        public boolean isBubbleNotificationSuppressedFromShade(String key, String groupKey) {
            return mMainExecutor.executeBlockingForResult(() -> {
                return BubbleController.this.isBubbleNotificationSuppressedFromShade(key, groupKey);
            }, Boolean.class);
            return mCachedState.isBubbleNotificationSuppressedFromShade(key, groupKey);
        }

        @Override
        public boolean isBubbleExpanded(String key) {
            return mMainExecutor.executeBlockingForResult(() -> {
                return BubbleController.this.isBubbleExpanded(key);
            }, Boolean.class);
            return mCachedState.isBubbleExpanded(key);
        }

        @Override
        public boolean isStackExpanded() {
            return mMainExecutor.executeBlockingForResult(() -> {
                return BubbleController.this.isStackExpanded();
            }, Boolean.class);
            return mCachedState.isStackExpanded();
        }

        @Override
        @Nullable
        public Bubble getBubbleWithShortcutId(String shortcutId) {
            return mCachedState.getBubbleWithShortcutId(shortcutId);
        }

        @Override
@@ -1424,14 +1531,6 @@ public class BubbleController {
            });
        }

        @Override
        @Nullable
        public Bubble getBubbleWithShortcutId(String shortcutId) {
            return mMainExecutor.executeBlockingForResult(() -> {
                return BubbleController.this.mBubbleData.getAnyBubbleWithShortcutId(shortcutId);
            }, Bubble.class);
        }

        @Override
        public void onTaskbarChanged(Bundle b) {
            mMainExecutor.execute(() -> {
@@ -1555,6 +1654,7 @@ public class BubbleController {
            try {
                mMainExecutor.executeBlocking(() -> {
                    BubbleController.this.dump(fd, pw, args);
                    mCachedState.dump(pw);
                });
            } catch (InterruptedException e) {
                Slog.e(TAG, "Failed to dump BubbleController in 2s");
+11 −1
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ public class BubbleData {
        boolean expandedChanged;
        boolean selectionChanged;
        boolean orderChanged;
        boolean suppressedSummaryChanged;
        boolean expanded;
        @Nullable BubbleViewProvider selectedBubble;
        @Nullable Bubble addedBubble;
@@ -81,6 +82,7 @@ public class BubbleData {
        @Nullable Bubble removedOverflowBubble;
        @Nullable Bubble suppressedBubble;
        @Nullable Bubble unsuppressedBubble;
        @Nullable String suppressedSummaryGroup;
        // Pair with Bubble and @DismissReason Integer
        final List<Pair<Bubble, Integer>> removedBubbles = new ArrayList<>();

@@ -103,7 +105,9 @@ public class BubbleData {
                    || removedOverflowBubble != null
                    || orderChanged
                    || suppressedBubble != null
                    || unsuppressedBubble != null;
                    || unsuppressedBubble != null
                    || suppressedSummaryChanged
                    || suppressedSummaryGroup != null;
        }

        void bubbleRemoved(Bubble bubbleToRemove, @DismissReason int reason) {
@@ -380,6 +384,9 @@ public class BubbleData {
     */
    void addSummaryToSuppress(String groupKey, String notifKey) {
        mSuppressedGroupKeys.put(groupKey, notifKey);
        mStateChange.suppressedSummaryChanged = true;
        mStateChange.suppressedSummaryGroup = groupKey;
        dispatchPendingChanges();
    }

    /**
@@ -397,6 +404,9 @@ public class BubbleData {
     */
    void removeSuppressedSummary(String groupKey) {
        mSuppressedGroupKeys.remove(groupKey);
        mStateChange.suppressedSummaryChanged = true;
        mStateChange.suppressedSummaryGroup = groupKey;
        dispatchPendingChanges();
    }

    /**
+1 −1
Original line number Diff line number Diff line
@@ -617,7 +617,7 @@ public class BubblesManager implements Dumpable {
     * cancel it (and hence the bubbles associated with it).
     *
     * @return true if we want to intercept the dismissal of the entry, else false.
     * @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer)
     * @see Bubbles#handleDismissalInterception(BubbleEntry, List, IntConsumer, Executor)
     */
    public boolean handleDismissalInterception(NotificationEntry entry) {
        if (entry == null) {
+90 −75

File changed.

Preview size limit exceeded, changes collapsed.

Loading