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

Commit 08348e26 authored by Tony Huang's avatar Tony Huang Committed by Android (Google) Code Review
Browse files

Merge "Migrate Bubbles to wm-shell (1/n)"

parents 5875f39c 425e5afa
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -37,7 +37,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.bubbles.Bubbles;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
@@ -288,7 +288,7 @@ public class Dependency {
    @Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
    @Inject Lazy<SmartReplyController> mSmartReplyController;
    @Inject Lazy<RemoteInputQuickSettingsDisabler> mRemoteInputQuickSettingsDisabler;
    @Inject Lazy<BubbleController> mBubbleController;
    @Inject Lazy<Bubbles> mBubbles;
    @Inject Lazy<NotificationEntryManager> mNotificationEntryManager;
    @Inject Lazy<SensorPrivacyManager> mSensorPrivacyManager;
    @Inject Lazy<AutoHideController> mAutoHideController;
@@ -483,7 +483,7 @@ public class Dependency {
        mProviders.put(SmartReplyController.class, mSmartReplyController::get);
        mProviders.put(RemoteInputQuickSettingsDisabler.class,
                mRemoteInputQuickSettingsDisabler::get);
        mProviders.put(BubbleController.class, mBubbleController::get);
        mProviders.put(Bubbles.class, mBubbles::get);
        mProviders.put(NotificationEntryManager.class, mNotificationEntryManager::get);
        mProviders.put(ForegroundServiceNotificationListener.class,
                mForegroundServiceNotificationListener::get);
+24 −75
Original line number Diff line number Diff line
@@ -129,7 +129,8 @@ import java.util.Objects;
 *
 * The controller manages addition, removal, and visible state of bubbles on screen.
 */
public class BubbleController implements ConfigurationController.ConfigurationListener, Dumpable {
public class BubbleController implements Bubbles, ConfigurationController.ConfigurationListener,
        Dumpable {

    private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES;

@@ -520,6 +521,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
    /**
     * See {@link NotifCallback}.
     */
    @Override
    public void addNotifCallback(NotifCallback callback) {
        mCallbacks.add(callback);
    }
@@ -701,6 +703,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
     * since we want the scrim's appearance and behavior to be identical to that of the notification
     * shade scrim.
     */
    @Override
    public ScrimView getScrimForBubble() {
        return mBubbleScrim;
    }
@@ -709,6 +712,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
     * Called when the status bar has become visible or invisible (either permanently or
     * temporarily).
     */
    @Override
    public void onStatusBarVisibilityChanged(boolean visible) {
        if (mStackView != null) {
            // Hide the stack temporarily if the status bar has been made invisible, and the stack
@@ -726,14 +730,16 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        mInflateSynchronously = inflateSynchronously;
    }

    void setOverflowListener(BubbleData.Listener listener) {
    @Override
    public void setOverflowListener(BubbleData.Listener listener) {
        mOverflowListener = listener;
    }

    /**
     * @return Bubbles for updating overflow.
     */
    List<Bubble> getOverflowBubbles() {
    @Override
    public List<Bubble> getOverflowBubbles() {
        return mBubbleData.getOverflowBubbles();
    }

@@ -956,13 +962,10 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    }

    boolean inLandscape() {
        return mOrientation == Configuration.ORIENTATION_LANDSCAPE;
    }

    /**
     * Set a listener to be notified of bubble expand events.
     */
    @Override
    public void setExpandListener(BubbleExpandListener listener) {
        mExpandListener = ((isExpanding, key) -> {
            if (listener != null) {
@@ -988,29 +991,17 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        return mBubbleData.hasBubbles();
    }

    /**
     * Whether the stack of bubbles is expanded or not.
     */
    @Override
    public boolean isStackExpanded() {
        return mBubbleData.isExpanded();
    }

    /**
     * Tell the stack of bubbles to collapse.
     */
    @Override
    public void collapseStack() {
        mBubbleData.setExpanded(false /* expanded */);
    }

    /**
     * True if either:
     * (1) There is a bubble associated with the provided key and if its notification is hidden
     *     from the shade.
     * (2) There is a group summary associated with the provided key that is hidden from the shade
     *     because it has been dismissed but still has child bubbles active.
     *
     * False otherwise.
     */
    @Override
    public boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry) {
        String key = entry.getKey();
        boolean isSuppressedBubble = (mBubbleData.hasAnyBubbleWithKey(key)
@@ -1022,19 +1013,14 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        return (isSummary && isSuppressedSummary) || isSuppressedBubble;
    }

    /**
     * True if:
     * (1) The current notification entry same as selected bubble notification entry and the
     * stack is currently expanded.
     *
     * False otherwise.
     */
    @Override
    public boolean isBubbleExpanded(NotificationEntry entry) {
        return isStackExpanded() && mBubbleData != null && mBubbleData.getSelectedBubble() != null
                && mBubbleData.getSelectedBubble().getKey().equals(entry.getKey()) ? true : false;
    }

    void promoteBubbleFromOverflow(Bubble bubble) {
    @Override
    public void promoteBubbleFromOverflow(Bubble bubble) {
        mLogger.log(bubble, BubbleLogger.Event.BUBBLE_OVERFLOW_REMOVE_BACK_TO_STACK);
        bubble.setInflateSynchronously(mInflateSynchronously);
        bubble.setShouldAutoExpand(true);
@@ -1042,12 +1028,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        setIsBubble(bubble, true /* isBubble */);
    }

    /**
     * Request the stack expand if needed, then select the specified Bubble as current.
     * If no bubble exists for this entry, one is created.
     *
     * @param entry the notification for the bubble to be selected
     */
    @Override
    public void expandStackAndSelectBubble(NotificationEntry entry) {
        if (mStatusBarStateListener.getCurrentState() == SHADE) {
            mNotifEntryToExpandOnShadeUnlock = null;
@@ -1075,12 +1056,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    }

    /**
     * When a notification is marked Priority, expand the stack if needed,
     * then (maybe create and) select the given bubble.
     *
     * @param entry the notification for the bubble to show
     */
    @Override
    public void onUserChangedImportance(NotificationEntry entry) {
        try {
            int flags = Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
@@ -1095,10 +1071,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    }

    /**
     * Directs a back gesture at the bubble stack. When opened, the current expanded bubble
     * is forwarded a back key down/up pair.
     */
    @Override
    public void performBackPressIfNeeded() {
        if (mStackView != null) {
            mStackView.performBackPressIfNeeded();
@@ -1162,15 +1135,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
                mContext, mStackView, mBubbleIconFactory, false /* skipInflation */);
    }

    /**
     * Called when a user has indicated that an active notification should be shown as a bubble.
     * <p>
     * This method will collapse the shade, create the bubble without a flyout or dot, and suppress
     * the notification from appearing in the shade.
     *
     * @param entry the notification to change bubble state for.
     * @param shouldBubble whether the notification should show as a bubble or not.
     */
    @Override
    public void onUserChangedBubble(@NonNull final NotificationEntry entry, boolean shouldBubble) {
        NotificationChannel channel = entry.getChannel();
        final String appPkg = entry.getSbn().getPackageName();
@@ -1209,13 +1174,9 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    }

    /**
     * Removes the bubble with the given key.
     * <p>
     * Must be called from the main thread.
     */
    @MainThread
    void removeBubble(String key, int reason) {
    @Override
    public void removeBubble(String key, int reason) {
        if (mBubbleData.hasAnyBubbleWithKey(key)) {
            mBubbleData.dismissBubbleWithKey(key, reason);
        }
@@ -1457,16 +1418,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        }
    };

    /**
     * We intercept notification entries (including group summaries) dismissed by the user when
     * there is an active bubble associated with it. We do this so that developers can still
     * cancel it (and hence the bubbles associated with it). However, these intercepted
     * notifications should then be hidden from the shade since the user has cancelled them, so we
     *  {@link Bubble#setSuppressNotification}.  For the case of suppressed summaries, we also add
     *  {@link BubbleData#addSummaryToSuppress}.
     *
     * @return true if we want to intercept the dismissal of the entry, else false.
     */
    @Override
    public boolean handleDismissalInterception(NotificationEntry entry) {
        if (entry == null) {
            return false;
@@ -1589,10 +1541,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
        mStackView.updateContentDescription();
    }

    /**
     * The display id of the expanded view, if the stack is expanded and not occluded by the
     * status bar, otherwise returns {@link Display#INVALID_DISPLAY}.
     */
    @Override
    public int getExpandedDisplayId(Context context) {
        if (mStackView == null) {
            return INVALID_DISPLAY;
+4 −4
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ public class BubbleExpandedView extends LinearLayout {

    private boolean mIsOverflow;

    private BubbleController mBubbleController = Dependency.get(BubbleController.class);
    private Bubbles mBubbles = Dependency.get(Bubbles.class);
    private WindowManager mWindowManager;
    private ActivityManager mActivityManager;

@@ -168,7 +168,7 @@ public class BubbleExpandedView extends LinearLayout {
                                    + "bubble=" + getBubbleKey());
                        }
                        if (mActivityView == null) {
                            mBubbleController.removeBubble(getBubbleKey(),
                            mBubbles.removeBubble(getBubbleKey(),
                                    BubbleController.DISMISS_INVALID_INTENT);
                            return;
                        }
@@ -194,7 +194,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(getBubbleKey(),
                            mBubbles.removeBubble(getBubbleKey(),
                                    BubbleController.DISMISS_INVALID_INTENT);
                        }
                    });
@@ -242,7 +242,7 @@ public class BubbleExpandedView extends LinearLayout {
            }
            if (mBubble != null) {
                // Must post because this is called from a binder thread.
                post(() -> mBubbleController.removeBubble(mBubble.getKey(),
                post(() -> mBubbles.removeBubble(mBubble.getKey(),
                        BubbleController.DISMISS_TASK_FINISHED));
            }
        }
+9 −9
Original line number Diff line number Diff line
@@ -60,7 +60,7 @@ public class BubbleOverflowActivity extends Activity {
    private TextView mEmptyStateTitle;
    private TextView mEmptyStateSubtitle;
    private ImageView mEmptyStateImage;
    private BubbleController mBubbleController;
    private Bubbles mBubbles;
    private BubbleOverflowAdapter mAdapter;
    private RecyclerView mRecyclerView;
    private List<Bubble> mOverflowBubbles = new ArrayList<>();
@@ -71,7 +71,8 @@ public class BubbleOverflowActivity extends Activity {
        }
        @Override
        public boolean canScrollVertically() {
            if (mBubbleController.inLandscape()) {
            if (getResources().getConfiguration().orientation
                    == Configuration.ORIENTATION_LANDSCAPE) {
                return super.canScrollVertically();
            }
            return false;
@@ -93,8 +94,8 @@ public class BubbleOverflowActivity extends Activity {
    }

    @Inject
    public BubbleOverflowActivity(BubbleController controller) {
        mBubbleController = controller;
    public BubbleOverflowActivity(Bubbles bubbles) {
        mBubbles = bubbles;
    }

    @Override
@@ -131,15 +132,15 @@ public class BubbleOverflowActivity extends Activity {
        final int viewHeight = recyclerViewHeight / rows;

        mAdapter = new BubbleOverflowAdapter(getApplicationContext(), mOverflowBubbles,
                mBubbleController::promoteBubbleFromOverflow, viewWidth, viewHeight);
                mBubbles::promoteBubbleFromOverflow, viewWidth, viewHeight);
        mRecyclerView.setAdapter(mAdapter);

        mOverflowBubbles.clear();
        mOverflowBubbles.addAll(mBubbleController.getOverflowBubbles());
        mOverflowBubbles.addAll(mBubbles.getOverflowBubbles());
        mAdapter.notifyDataSetChanged();
        updateEmptyStateVisibility();

        mBubbleController.setOverflowListener(mDataListener);
        mBubbles.setOverflowListener(mDataListener);
        updateTheme();
    }

@@ -209,8 +210,7 @@ public class BubbleOverflowActivity extends Activity {

            if (DEBUG_OVERFLOW) {
                Log.d(TAG, BubbleDebugConfig.formatBubblesString(
                        mBubbleController.getOverflowBubbles(),
                        null));
                        mBubbles.getOverflowBubbles(), null));
            }
        }
    };
+145 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.bubbles;

import android.annotation.NonNull;
import android.content.Context;
import android.view.Display;

import androidx.annotation.MainThread;

import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.phone.ScrimController;

import java.util.List;

/**
 * Interface to engage bubbles feature.
 */
public interface Bubbles {

    /**
     * @return {@code true} if there is a bubble associated with the provided key and if its
     * notification is hidden from the shade or there is a group summary associated with the
     * provided key that is hidden from the shade because it has been dismissed but still has child
     * bubbles active.
     */
    boolean isBubbleNotificationSuppressedFromShade(NotificationEntry entry);

    /**
     * @return {@code true} if the current notification entry same as selected bubble
     * notification entry and the stack is currently expanded.
     */
    boolean isBubbleExpanded(NotificationEntry entry);

    /** @return {@code true} if stack of bubbles is expanded or not. */
    boolean isStackExpanded();

    /**
     * @return the {@link ScrimView} drawn behind the bubble stack. This is managed by
     * {@link ScrimController} since we want the scrim's appearance and behavior to be identical to
     * that of the notification shade scrim.
     */
    ScrimView getScrimForBubble();

    /**
     * @return the display id of the expanded view, if the stack is expanded and not occluded by the
     * status bar, otherwise returns {@link Display#INVALID_DISPLAY}.
     */
    int getExpandedDisplayId(Context context);

    /** @return Bubbles for updating overflow. */
    List<Bubble> getOverflowBubbles();

    /** Tell the stack of bubbles to collapse. */
    void collapseStack();

    /**
     * Request the stack expand if needed, then select the specified Bubble as current.
     * If no bubble exists for this entry, one is created.
     *
     * @param entry the notification for the bubble to be selected
     */
    void expandStackAndSelectBubble(NotificationEntry entry);


    /**
     * Directs a back gesture at the bubble stack. When opened, the current expanded bubble
     * is forwarded a back key down/up pair.
     */
    void performBackPressIfNeeded();

    /** Promote the provided bubbles when overflow view. */
    void promoteBubbleFromOverflow(Bubble bubble);

    /**
     * We intercept notification entries (including group summaries) dismissed by the user when
     * there is an active bubble associated with it. We do this so that developers can still
     * cancel it (and hence the bubbles associated with it). However, these intercepted
     * notifications should then be hidden from the shade since the user has cancelled them, so we
     * {@link Bubble#setSuppressNotification}.  For the case of suppressed summaries, we also add
     * {@link BubbleData#addSummaryToSuppress}.
     *
     * @return true if we want to intercept the dismissal of the entry, else false.
     */
    boolean handleDismissalInterception(NotificationEntry entry);

    /**
     * Removes the bubble with the given key.
     * <p>
     * Must be called from the main thread.
     */
    @MainThread
    void removeBubble(String key, int reason);


    /**
     * When a notification is marked Priority, expand the stack if needed,
     * then (maybe create and) select the given bubble.
     *
     * @param entry the notification for the bubble to show
     */
    void onUserChangedImportance(NotificationEntry entry);

    /**
     * Called when the status bar has become visible or invisible (either permanently or
     * temporarily).
     */
    void onStatusBarVisibilityChanged(boolean visible);

    /**
     * Called when a user has indicated that an active notification should be shown as a bubble.
     * <p>
     * This method will collapse the shade, create the bubble without a flyout or dot, and suppress
     * the notification from appearing in the shade.
     *
     * @param entry the notification to change bubble state for.
     * @param shouldBubble whether the notification should show as a bubble or not.
     */
    void onUserChangedBubble(@NonNull NotificationEntry entry, boolean shouldBubble);


    /** See {@link BubbleController.NotifCallback}. */
    void addNotifCallback(BubbleController.NotifCallback callback);

    /** Set a listener to be notified of bubble expand events. */
    void setExpandListener(BubbleController.BubbleExpandListener listener);

    /** Set a listener to be notified of when overflow view update. */
    void setOverflowListener(BubbleData.Listener listener);
}
Loading