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

Commit 6cdc1bab authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Automerger Merge Worker
Browse files

Merge "Persists bubbles to disk (part 4)" into rvc-dev am: 682217b4

Change-Id: I9e8607cdbe5ce1cf8af277594df9b9f6a8f0aaf1
parents 29cb5ecd 682217b4
Loading
Loading
Loading
Loading
+108 −11
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles;


import static android.app.Notification.FLAG_BUBBLE;
import static android.os.AsyncTask.Status.FINISHED;
import static android.view.Display.INVALID_DISPLAY;

@@ -27,6 +28,7 @@ import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
@@ -55,6 +57,11 @@ import java.util.Objects;
class Bubble implements BubbleViewProvider {
    private static final String TAG = "Bubble";

    /**
     * NotificationEntry associated with the bubble. A null value implies this bubble is loaded
     * from disk.
     */
    @Nullable
    private NotificationEntry mEntry;
    private final String mKey;
    private final String mGroupId;
@@ -95,18 +102,56 @@ class Bubble implements BubbleViewProvider {
    private Bitmap mBadgedImage;
    private int mDotColor;
    private Path mDotPath;
    private int mFlags;


    /**
     * Extract GroupId from {@link NotificationEntry}. See also {@link #groupId(ShortcutInfo)}.
     */
    public static String groupId(NotificationEntry entry) {
        UserHandle user = entry.getSbn().getUser();
        return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
    }

    // TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble
    /**
     * Extract GroupId from {@link ShortcutInfo}. This should match the one generated from
     * {@link NotificationEntry}. See also {@link #groupId(NotificationEntry)}.
     */
    @NonNull
    public static String groupId(@NonNull final ShortcutInfo shortcutInfo) {
        return shortcutInfo.getUserId() + "|" + shortcutInfo.getPackage();
    }

    /**
     * Generate a unique identifier for this bubble based on given {@link NotificationEntry}. If
     * {@link ShortcutInfo} was found in the notification entry, the identifier would be generated
     * from {@link ShortcutInfo} instead. See also {@link #key(ShortcutInfo)}.
     */
    @NonNull
    public static String key(@NonNull final NotificationEntry entry) {
        final ShortcutInfo shortcutInfo = entry.getRanking().getShortcutInfo();
        if (shortcutInfo != null) return key(shortcutInfo);
        return entry.getKey();
    }

    /**
     * Generate a unique identifier for this bubble based on given {@link ShortcutInfo}.
     * See also {@link #key(NotificationEntry)}.
     */
    @NonNull
    public static String key(@NonNull final ShortcutInfo shortcutInfo) {
        return shortcutInfo.getUserId() + "|" + shortcutInfo.getPackage() + "|"
                + shortcutInfo.getId();
    }

    /**
     * Create a bubble with limited information based on given {@link ShortcutInfo}.
     * Note: Currently this is only being used when the bubble is persisted to disk.
     */
    Bubble(ShortcutInfo shortcutInfo) {
        mShortcutInfo = shortcutInfo;
        mKey = shortcutInfo.getId();
        mGroupId = shortcutInfo.getId();
        mKey = key(shortcutInfo);
        mGroupId = groupId(shortcutInfo);
        mFlags = 0;
    }

    /** Used in tests when no UI is required. */
@@ -114,10 +159,11 @@ class Bubble implements BubbleViewProvider {
    Bubble(NotificationEntry e,
            BubbleController.NotificationSuppressionChangedListener listener) {
        mEntry = e;
        mKey = e.getKey();
        mKey = key(e);
        mLastUpdated = e.getSbn().getPostTime();
        mGroupId = groupId(e);
        mSuppressionListener = listener;
        mFlags = e.getSbn().getNotification().flags;
    }

    @Override
@@ -125,16 +171,26 @@ class Bubble implements BubbleViewProvider {
        return mKey;
    }

    @Nullable
    public NotificationEntry getEntry() {
        return mEntry;
    }

    @Nullable
    public UserHandle getUser() {
        if (mEntry != null) return mEntry.getSbn().getUser();
        if (mShortcutInfo != null) return mShortcutInfo.getUserHandle();
        return null;
    }

    public String getGroupId() {
        return mGroupId;
    }

    public String getPackageName() {
        return mEntry.getSbn().getPackageName();
        return mEntry == null
                ? mShortcutInfo == null ? null : mShortcutInfo.getPackage()
                : mEntry.getSbn().getPackageName();
    }

    @Override
@@ -218,7 +274,8 @@ class Bubble implements BubbleViewProvider {
    void inflate(BubbleViewInfoTask.Callback callback,
            Context context,
            BubbleStackView stackView,
            BubbleIconFactory iconFactory) {
            BubbleIconFactory iconFactory,
            boolean skipInflation) {
        if (isBubbleLoading()) {
            mInflationTask.cancel(true /* mayInterruptIfRunning */);
        }
@@ -226,6 +283,7 @@ class Bubble implements BubbleViewProvider {
                context,
                stackView,
                iconFactory,
                skipInflation,
                callback);
        if (mInflateSynchronously) {
            mInflationTask.onPostExecute(mInflationTask.doInBackground());
@@ -345,6 +403,7 @@ class Bubble implements BubbleViewProvider {
     * Whether this notification should be shown in the shade.
     */
    boolean showInShade() {
        if (mEntry == null) return false;
        return !shouldSuppressNotification() || !mEntry.isClearable();
    }

@@ -352,8 +411,8 @@ class Bubble implements BubbleViewProvider {
     * Sets whether this notification should be suppressed in the shade.
     */
    void setSuppressNotification(boolean suppressNotification) {
        if (mEntry == null) return;
        boolean prevShowInShade = showInShade();

        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
        int flags = data.getFlags();
        if (suppressNotification) {
@@ -384,6 +443,7 @@ class Bubble implements BubbleViewProvider {
     */
    @Override
    public boolean showDot() {
        if (mEntry == null) return false;
        return mShowBubbleUpdateDot
                && !mEntry.shouldSuppressNotificationDot()
                && !shouldSuppressNotification();
@@ -393,6 +453,7 @@ class Bubble implements BubbleViewProvider {
     * Whether the flyout for the bubble should be shown.
     */
    boolean showFlyout() {
        if (mEntry == null) return false;
        return !mSuppressFlyout && !mEntry.shouldSuppressPeek()
                && !shouldSuppressNotification()
                && !mEntry.shouldSuppressNotificationList();
@@ -416,11 +477,13 @@ class Bubble implements BubbleViewProvider {
     * is an ongoing bubble.
     */
    boolean isOngoing() {
        if (mEntry == null) return false;
        int flags = mEntry.getSbn().getNotification().flags;
        return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
    }

    float getDesiredHeight(Context context) {
        if (mEntry == null) return 0;
        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
        boolean useRes = data.getDesiredHeightResId() != 0;
        if (useRes) {
@@ -434,6 +497,7 @@ class Bubble implements BubbleViewProvider {
    }

    String getDesiredHeightString() {
        if (mEntry == null) return String.valueOf(0);
        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
        boolean useRes = data.getDesiredHeightResId() != 0;
        if (useRes) {
@@ -450,11 +514,13 @@ class Bubble implements BubbleViewProvider {
     * To populate the icon use {@link LauncherApps#getShortcutIconDrawable(ShortcutInfo, int)}.
     */
    boolean usingShortcutInfo() {
        return mEntry.getBubbleMetadata().getShortcutId() != null;
        return mEntry != null && mEntry.getBubbleMetadata().getShortcutId() != null
                || mShortcutInfo != null;
    }

    @Nullable
    PendingIntent getBubbleIntent() {
        if (mEntry == null) return null;
        Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
        if (data != null) {
            return data.getIntent();
@@ -462,16 +528,32 @@ class Bubble implements BubbleViewProvider {
        return null;
    }

    Intent getSettingsIntent() {
    Intent getSettingsIntent(final Context context) {
        final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
        intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
        intent.putExtra(Settings.EXTRA_APP_UID, mEntry.getSbn().getUid());
        final int uid = getUid(context);
        if (uid != -1) {
            intent.putExtra(Settings.EXTRA_APP_UID, uid);
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        return intent;
    }

    private int getUid(final Context context) {
        if (mEntry != null) return mEntry.getSbn().getUid();
        final PackageManager pm = context.getPackageManager();
        if (pm == null) return -1;
        try {
            final ApplicationInfo info = pm.getApplicationInfo(mShortcutInfo.getPackage(), 0);
            return info.uid;
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "cannot find uid", e);
        }
        return -1;
    }

    private int getDimenForPackageUser(Context context, int resId, String pkg, int userId) {
        PackageManager pm = context.getPackageManager();
        Resources r;
@@ -493,15 +575,30 @@ class Bubble implements BubbleViewProvider {
    }

    private boolean shouldSuppressNotification() {
        if (mEntry == null) return false;
        return mEntry.getBubbleMetadata() != null
                && mEntry.getBubbleMetadata().isNotificationSuppressed();
    }

    boolean shouldAutoExpand() {
        if (mEntry == null) return false;
        Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
        return metadata != null && metadata.getAutoExpandBubble();
    }

    public boolean isBubble() {
        if (mEntry == null) return (mFlags & FLAG_BUBBLE) != 0;
        return (mEntry.getSbn().getNotification().flags & FLAG_BUBBLE) != 0;
    }

    public void enable(int option) {
        mFlags |= option;
    }

    public void disable(int option) {
        mFlags &= ~option;
    }

    @Override
    public String toString() {
        return "Bubble{" + mKey + '}';
+69 −29
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager.RunningTaskInfo;
import android.app.INotificationManager;
@@ -242,7 +243,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
         * This can happen when an app cancels a bubbled notification or when the user dismisses a
         * bubble.
         */
        void removeNotification(NotificationEntry entry, int reason);
        void removeNotification(@NonNull NotificationEntry entry, int reason);

        /**
         * Called when a bubbled notification has changed whether it should be
@@ -258,7 +259,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
         * removes all remnants of the group's summary from the notification pipeline.
         * TODO: (b/145659174) Only old pipeline needs this - delete post-migration.
         */
        void maybeCancelSummary(NotificationEntry entry);
        void maybeCancelSummary(@NonNull NotificationEntry entry);
    }

    /**
@@ -481,7 +482,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi

        addNotifCallback(new NotifCallback() {
            @Override
            public void removeNotification(NotificationEntry entry, int reason) {
            public void removeNotification(@NonNull final NotificationEntry entry, int reason) {
                mNotificationEntryManager.performRemoveNotification(entry.getSbn(),
                        reason);
            }
@@ -492,7 +493,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            }

            @Override
            public void maybeCancelSummary(NotificationEntry entry) {
            public void maybeCancelSummary(@NonNull final NotificationEntry entry) {
                // Check if removed bubble has an associated suppressed group summary that needs
                // to be removed now.
                final String groupKey = entry.getSbn().getGroupKey();
@@ -701,10 +702,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        mBubbleIconFactory = new BubbleIconFactory(mContext);
        // Reload each bubble
        for (Bubble b: mBubbleData.getBubbles()) {
            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory);
            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory,
                    false /* skipInflation */);
        }
        for (Bubble b: mBubbleData.getOverflowBubbles()) {
            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory);
            b.inflate(null /* callback */, mContext, mStackView, mBubbleIconFactory,
                    false /* skipInflation */);
        }
    }

@@ -803,7 +806,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            if (bubble != null) {
                mBubbleData.promoteBubbleFromOverflow(bubble, mStackView, mBubbleIconFactory);
            }
        } else if (bubble.getEntry().isBubble()){
        } else if (bubble.isBubble()) {
            mBubbleData.setSelectedBubble(bubble);
        }
        mBubbleData.setExpanded(true);
@@ -832,10 +835,33 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        updateBubble(notif, suppressFlyout, true /* showInShade */);
    }

    /**
     * Fills the overflow bubbles by loading them from disk.
     */
    void loadOverflowBubblesFromDisk() {
        if (!mBubbleData.getOverflowBubbles().isEmpty()) {
            // we don't need to load overflow bubbles from disk if it is already in memory
            return;
        }
        mDataRepository.loadBubbles((bubbles) -> {
            bubbles.forEach(bubble -> {
                if (mBubbleData.getBubbles().contains(bubble)) {
                    // if the bubble is already active, there's no need to push it to overflow
                    return;
                }
                bubble.inflate((b) -> mBubbleData.overflowBubble(DISMISS_AGED, bubble),
                        mContext, mStackView, mBubbleIconFactory, true /* skipInflation */);
            });
            return null;
        });
    }

    void updateBubble(NotificationEntry notif, boolean suppressFlyout, boolean showInShade) {
        if (mStackView == null) {
            // Lazy init stack view when a bubble is created
            ensureStackViewCreated();
            // Lazy load overflow bubbles from disk
            loadOverflowBubblesFromDisk();
        }
        // If this is an interruptive notif, mark that it's interrupted
        if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) {
@@ -855,11 +881,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                            return;
                        }
                        mHandler.post(
                                () -> removeBubble(bubble.getEntry(),
                                () -> removeBubble(bubble.getKey(),
                                        BubbleController.DISMISS_INVALID_INTENT));
                    });
                },
                mContext, mStackView, mBubbleIconFactory);
                mContext, mStackView, mBubbleIconFactory, false /* skipInflation */);
    }

    /**
@@ -871,7 +897,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
     * @param entry the notification to change bubble state for.
     * @param shouldBubble whether the notification should show as a bubble or not.
     */
    public void onUserChangedBubble(NotificationEntry entry, boolean shouldBubble) {
    public void onUserChangedBubble(@Nullable final NotificationEntry entry, boolean shouldBubble) {
        if (entry == null) {
            return;
        }
        NotificationChannel channel = entry.getChannel();
        final String appPkg = entry.getSbn().getPackageName();
        final int appUid = entry.getSbn().getUid();
@@ -909,14 +938,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
    }

    /**
     * Removes the bubble with the given NotificationEntry.
     * Removes the bubble with the given key.
     * <p>
     * Must be called from the main thread.
     */
    @MainThread
    void removeBubble(NotificationEntry entry, int reason) {
        if (mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
            mBubbleData.notificationEntryRemoved(entry, reason);
    void removeBubble(String key, int reason) {
        if (mBubbleData.hasAnyBubbleWithKey(key)) {
            mBubbleData.notificationEntryRemoved(key, reason);
        }
    }

@@ -932,7 +961,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                && canLaunchInActivityView(mContext, entry);
        if (!shouldBubble && mBubbleData.hasAnyBubbleWithKey(entry.getKey())) {
            // It was previously a bubble but no longer a bubble -- lets remove it
            removeBubble(entry, DISMISS_NO_LONGER_BUBBLE);
            removeBubble(entry.getKey(), DISMISS_NO_LONGER_BUBBLE);
        } else if (shouldBubble) {
            updateBubble(entry);
        }
@@ -946,10 +975,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            // Remove any associated bubble children with the summary
            final List<Bubble> bubbleChildren = mBubbleData.getBubblesInGroup(groupKey);
            for (int i = 0; i < bubbleChildren.size(); i++) {
                removeBubble(bubbleChildren.get(i).getEntry(), DISMISS_GROUP_CANCELLED);
                removeBubble(bubbleChildren.get(i).getKey(), DISMISS_GROUP_CANCELLED);
            }
        } else {
            removeBubble(entry, DISMISS_NOTIF_CANCEL);
            removeBubble(entry.getKey(), DISMISS_NOTIF_CANCEL);
        }
    }

@@ -971,7 +1000,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
            rankingMap.getRanking(key, mTmpRanking);
            boolean isActiveBubble = mBubbleData.hasAnyBubbleWithKey(key);
            if (isActiveBubble && !mTmpRanking.canBubble()) {
                mBubbleData.notificationEntryRemoved(entry, BubbleController.DISMISS_BLOCKED);
                mBubbleData.notificationEntryRemoved(entry.getKey(),
                        BubbleController.DISMISS_BLOCKED);
            } else if (entry != null && mTmpRanking.isBubble() && !isActiveBubble) {
                entry.setFlagBubble(true);
                onEntryUpdated(entry);
@@ -981,10 +1011,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi

    private void setIsBubble(Bubble b, boolean isBubble) {
        if (isBubble) {
            if (b.getEntry() != null) {
                b.getEntry().getSbn().getNotification().flags |= FLAG_BUBBLE;
            }
            b.enable(FLAG_BUBBLE);
        } else {
            if (b.getEntry() != null) {
                b.getEntry().getSbn().getNotification().flags &= ~FLAG_BUBBLE;
            }
            b.disable(FLAG_BUBBLE);
        }
        try {
            mBarService.onNotificationBubbleChanged(b.getKey(), isBubble, 0);
        } catch (RemoteException e) {
@@ -1031,18 +1067,21 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                        // The bubble is now gone & the notification is hidden from the shade, so
                        // time to actually remove it
                        for (NotifCallback cb : mCallbacks) {
                            if (bubble.getEntry() != null) {
                                cb.removeNotification(bubble.getEntry(), REASON_CANCEL);
                            }
                        }
                    } else {
                        if (bubble.getEntry().isBubble() && bubble.showInShade()) {
                        if (bubble.isBubble() && bubble.showInShade()) {
                            setIsBubble(bubble, /* isBubble */ false);
                        }
                        if (bubble.getEntry().getRow() != null) {
                        if (bubble.getEntry() != null && bubble.getEntry().getRow() != null) {
                            bubble.getEntry().getRow().updateBubbleButton();
                        }
                    }

                }
                if (bubble.getEntry() != null) {
                    final String groupKey = bubble.getEntry().getSbn().getGroupKey();
                    if (mBubbleData.getBubblesInGroup(groupKey).isEmpty()) {
                        // Time to potentially remove the summary
@@ -1051,6 +1090,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                        }
                    }
                }
            }
            mDataRepository.removeBubbles(mCurrentUserId, bubblesToBeRemovedFromRepository);

            if (update.addedBubble != null) {
@@ -1072,7 +1112,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi

            if (update.selectionChanged) {
                mStackView.setSelectedBubble(update.selectedBubble);
                if (update.selectedBubble != null) {
                if (update.selectedBubble != null && update.selectedBubble.getEntry() != null) {
                    mNotificationGroupManager.updateSuppression(
                            update.selectedBubble.getEntry());
                }
+16 −8
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME

import static java.util.stream.Collectors.toList;

import android.annotation.NonNull;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
@@ -223,7 +224,7 @@ public class BubbleData {
                            false, /* showInShade */ true);
                    setSelectedBubble(bubble);
                },
                mContext, stack, factory);
                mContext, stack, factory, false /* skipInflation */);
        dispatchPendingChanges();
    }

@@ -278,7 +279,8 @@ public class BubbleData {
        }
        mPendingBubbles.remove(bubble); // No longer pending once we're here
        Bubble prevBubble = getBubbleInStackWithKey(bubble.getKey());
        suppressFlyout |= !bubble.getEntry().getRanking().visuallyInterruptive();
        suppressFlyout |= bubble.getEntry() == null
                || !bubble.getEntry().getRanking().visuallyInterruptive();

        if (prevBubble == null) {
            // Create a new bubble
@@ -307,11 +309,14 @@ public class BubbleData {
        dispatchPendingChanges();
    }

    public void notificationEntryRemoved(NotificationEntry entry, @DismissReason int reason) {
    /**
     * Called when a notification associated with a bubble is removed.
     */
    public void notificationEntryRemoved(String key, @DismissReason int reason) {
        if (DEBUG_BUBBLE_DATA) {
            Log.d(TAG, "notificationEntryRemoved: entry=" + entry + " reason=" + reason);
            Log.d(TAG, "notificationEntryRemoved: key=" + key + " reason=" + reason);
        }
        doRemove(entry.getKey(), reason);
        doRemove(key, reason);
        dispatchPendingChanges();
    }

@@ -359,7 +364,7 @@ public class BubbleData {
            return bubbleChildren;
        }
        for (Bubble b : mBubbles) {
            if (groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
            if (b.getEntry() != null && groupKey.equals(b.getEntry().getSbn().getGroupKey())) {
                bubbleChildren.add(b);
            }
        }
@@ -470,8 +475,10 @@ public class BubbleData {
            Bubble newSelected = mBubbles.get(newIndex);
            setSelectedBubbleInternal(newSelected);
        }
        if (bubbleToRemove.getEntry() != null) {
            maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
        }
    }

    void overflowBubble(@DismissReason int reason, Bubble bubble) {
        if (bubble.getPendingIntentCanceled()
@@ -744,7 +751,8 @@ public class BubbleData {
        return true;
    }

    private void maybeSendDeleteIntent(@DismissReason int reason, NotificationEntry entry) {
    private void maybeSendDeleteIntent(@DismissReason int reason,
            @NonNull final NotificationEntry entry) {
        if (reason == BubbleController.DISMISS_USER_GESTURE) {
            Notification.BubbleMetadata bubbleMetadata = entry.getBubbleMetadata();
            PendingIntent deleteIntent = bubbleMetadata != null
+4 −2
Original line number Diff line number Diff line
@@ -74,7 +74,10 @@ internal class BubbleDataRepository @Inject constructor(

    private fun transform(userId: Int, bubbles: List<Bubble>): List<BubbleEntity> {
        return bubbles.mapNotNull { b ->
            val shortcutId = b.shortcutInfo?.id ?: return@mapNotNull null
            var shortcutId = b.shortcutInfo?.id
            if (shortcutId == null) shortcutId = b.entry?.bubbleMetadata?.shortcutId
            if (shortcutId == null) shortcutId = b.entry?.ranking?.shortcutInfo?.id
            if (shortcutId == null) return@mapNotNull null
            BubbleEntity(userId, b.packageName, shortcutId)
        }
    }
@@ -108,7 +111,6 @@ internal class BubbleDataRepository @Inject constructor(
    /**
     * Load bubbles from disk.
     */
    // TODO: call this method from BubbleController and update UI
    @SuppressLint("WrongConstant")
    fun loadBubbles(cb: (List<Bubble>) -> Unit) = ioScope.launch {
        /**
+2 −7
Original line number Diff line number Diff line
@@ -65,7 +65,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.recents.TriangleShape;
import com.android.systemui.statusbar.AlphaOptimizedButton;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;

/**
 * Container for the expanded bubble view, handles rendering the caret and settings icon.
@@ -161,7 +160,7 @@ public class BubbleExpandedView extends LinearLayout {
                            // the bubble again so we'll just remove it.
                            Log.w(TAG, "Exception while displaying bubble: " + getBubbleKey()
                                    + ", " + e.getMessage() + "; removing bubble");
                            mBubbleController.removeBubble(getBubbleEntry(),
                            mBubbleController.removeBubble(getBubbleKey(),
                                    BubbleController.DISMISS_INVALID_INTENT);
                        }
                    });
@@ -205,7 +204,7 @@ public class BubbleExpandedView extends LinearLayout {
            }
            if (mBubble != null) {
                // Must post because this is called from a binder thread.
                post(() -> mBubbleController.removeBubble(mBubble.getEntry(),
                post(() -> mBubbleController.removeBubble(mBubble.getKey(),
                        BubbleController.DISMISS_TASK_FINISHED));
            }
        }
@@ -292,10 +291,6 @@ public class BubbleExpandedView extends LinearLayout {
        return mBubble != null ? mBubble.getKey() : "null";
    }

    private NotificationEntry getBubbleEntry() {
        return mBubble != null ? mBubble.getEntry() : null;
    }

    void setManageClickListener(OnClickListener manageClickListener) {
        findViewById(R.id.settings_button).setOnClickListener(manageClickListener);
    }
Loading