From 8411376884622d75ddbd26d3c17dfdc0e4448523 Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Wed, 8 Mar 2023 15:23:18 -0800 Subject: [PATCH] Use BubbleBarLayerView & BubbleBarExpandedView * Adds BubbleBarLayerView to BubbleController, if the bubble bar is active, BBLV will be used instead of BubbleStackView. Some methods in BubbleController are updated to account for BBLV. * Updates the BubbleViewInfoTask (the inflation code for bubbles) to expect either BubbleBarExpandedView OR the BadgedImageView and BubbleExpandedView used when bubbles are NOT in the bubble bar. When showing in the bubble bar, BubbleBarExpandedView will be the only view inflated. Test: treehugger / manual with other CLs Bug: 253318833 Change-Id: I9e8410c62260304e286eddd9bf3c32fecc7ee317 --- .../com/android/wm/shell/bubbles/Bubble.java | 11 +- .../wm/shell/bubbles/BubbleController.java | 167 ++++++++++++------ .../wm/shell/bubbles/BubbleViewInfoTask.java | 87 +++++++-- 3 files changed, 200 insertions(+), 65 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index bd3aa16e726aa..8f364b448bf2d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -48,6 +48,7 @@ import android.util.Log; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; +import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.bubbles.BubbleInfo; import java.io.PrintWriter; @@ -430,14 +431,16 @@ public class Bubble implements BubbleViewProvider { * @param callback the callback to notify one the bubble is ready to be displayed. * @param context the context for the bubble. * @param controller the bubble controller. - * @param stackView the stackView the bubble is eventually added to. + * @param stackView the view the bubble is added to, iff showing as floating. + * @param layerView the layer the bubble is added to, iff showing in the bubble bar. * @param iconFactory the icon factory use to create images for the bubble. * @param badgeIconFactory the icon factory to create app badges for the bubble. */ void inflate(BubbleViewInfoTask.Callback callback, Context context, BubbleController controller, - BubbleStackView stackView, + @Nullable BubbleStackView stackView, + @Nullable BubbleBarLayerView layerView, BubbleIconFactory iconFactory, BubbleBadgeIconFactory badgeIconFactory, boolean skipInflation) { @@ -448,6 +451,7 @@ public class Bubble implements BubbleViewProvider { context, controller, stackView, + layerView, iconFactory, badgeIconFactory, skipInflation, @@ -479,6 +483,7 @@ public class Bubble implements BubbleViewProvider { if (!isInflated()) { mIconView = info.imageView; mExpandedView = info.expandedView; + mBubbleBarExpandedView = info.bubbleBarExpandedView; } mShortcutInfo = info.shortcutInfo; @@ -489,7 +494,7 @@ public class Bubble implements BubbleViewProvider { mFlyoutMessage = info.flyoutMessage; mBadgeBitmap = info.badgeBitmap; - mRawBadgeBitmap = info.mRawBadgeBitmap; + mRawBadgeBitmap = info.rawBadgeBitmap; mBubbleBitmap = info.bubbleBitmap; mDotColor = info.dotColor; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index 8040bd72e2a3b..0bb1cabb9b5ef 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -89,6 +89,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.WindowManagerShellWrapper; +import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.ExternalInterfaceBinder; import com.android.wm.shell.common.FloatingContentCoordinator; @@ -201,6 +202,7 @@ public class BubbleController implements ConfigurationChangeListener, private BubbleLogger mLogger; private BubbleData mBubbleData; @Nullable private BubbleStackView mStackView; + @Nullable private BubbleBarLayerView mLayerView; private BubbleIconFactory mBubbleIconFactory; private BubbleBadgeIconFactory mBubbleBadgeIconFactory; private BubblePositioner mBubblePositioner; @@ -546,7 +548,7 @@ public class BubbleController implements ConfigurationChangeListener, } private void openBubbleOverflow() { - ensureStackViewCreated(); + ensureBubbleViewsAndWindowCreated(); mBubbleData.setShowingOverflow(true); mBubbleData.setSelectedBubble(mBubbleData.getOverflow()); mBubbleData.setExpanded(true); @@ -586,7 +588,7 @@ public class BubbleController implements ConfigurationChangeListener, expandStackAndSelectBubble(mNotifEntryToExpandOnShadeUnlock); } - updateStack(); + updateBubbleViews(); } @VisibleForTesting @@ -687,34 +689,54 @@ public class BubbleController implements ConfigurationChangeListener, } /** - * BubbleStackView is lazily created by this method the first time a Bubble is added. This - * method initializes the stack view and adds it to window manager. + * The view and window for bubbles is lazily created by this method the first time a Bubble + * is added. Depending on the device state, this method will: + * - initialize a {@link BubbleStackView} and add it to window manager OR + * - initialize a {@link com.android.wm.shell.bubbles.bar.BubbleBarLayerView} and adds + * it to window manager. */ - private void ensureStackViewCreated() { - if (mStackView == null) { - mStackView = new BubbleStackView( - mContext, this, mBubbleData, mSurfaceSynchronizer, mFloatingContentCoordinator, - mMainExecutor); - mStackView.onOrientationChanged(); - if (mExpandListener != null) { - mStackView.setExpandListener(mExpandListener); + private void ensureBubbleViewsAndWindowCreated() { + mBubblePositioner.setShowingInBubbleBar(isShowingAsBubbleBar()); + if (isShowingAsBubbleBar()) { + // When we're showing in launcher / bubble bar is enabled, we don't have bubble stack + // view, instead we just show the expanded bubble view as necessary. We still need a + // window to show this in, but we use a separate code path. + // TODO(b/273312602): consider foldables where we do need a stack view when folded + if (mLayerView == null) { + mLayerView = new BubbleBarLayerView(mContext, this); + } + } else { + if (mStackView == null) { + mStackView = new BubbleStackView( + mContext, this, mBubbleData, mSurfaceSynchronizer, + mFloatingContentCoordinator, + mMainExecutor); + mStackView.onOrientationChanged(); + if (mExpandListener != null) { + mStackView.setExpandListener(mExpandListener); + } + mStackView.setUnbubbleConversationCallback(mSysuiProxy::onUnbubbleConversation); } - mStackView.setUnbubbleConversationCallback(mSysuiProxy::onUnbubbleConversation); } - addToWindowManagerMaybe(); } - /** Adds the BubbleStackView to the WindowManager if it's not already there. */ + /** Adds the appropriate view to WindowManager if it's not already there. */ private void addToWindowManagerMaybe() { - // If the stack is null, or already added, don't add it. - if (mStackView == null || mAddedToWindowManager) { + // If already added, don't add it. + if (mAddedToWindowManager) { + return; + } + // If the appropriate view is null, don't add it. + if (isShowingAsBubbleBar() && mLayerView == null) { + return; + } else if (!isShowingAsBubbleBar() && mStackView == null) { return; } mWmLayoutParams = new WindowManager.LayoutParams( // Fill the screen so we can use translation animations to position the bubble - // stack. We'll use touchable regions to ignore touches that are not on the bubbles + // views. We'll use touchable regions to ignore touches that are not on the bubbles // themselves. ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, @@ -737,17 +759,30 @@ public class BubbleController implements ConfigurationChangeListener, mAddedToWindowManager = true; registerBroadcastReceiver(); mBubbleData.getOverflow().initialize(this); - mWindowManager.addView(mStackView, mWmLayoutParams); - mStackView.setOnApplyWindowInsetsListener((view, windowInsets) -> { - if (!windowInsets.equals(mWindowInsets)) { - mWindowInsets = windowInsets; - mBubblePositioner.update(); - mStackView.onDisplaySizeChanged(); - } - return windowInsets; - }); + // (TODO: b/273314541) some duplication in the inset listener + if (isShowingAsBubbleBar()) { + mWindowManager.addView(mLayerView, mWmLayoutParams); + mLayerView.setOnApplyWindowInsetsListener((view, windowInsets) -> { + if (!windowInsets.equals(mWindowInsets)) { + mWindowInsets = windowInsets; + mBubblePositioner.update(); + mLayerView.onDisplaySizeChanged(); + } + return windowInsets; + }); + } else { + mWindowManager.addView(mStackView, mWmLayoutParams); + mStackView.setOnApplyWindowInsetsListener((view, windowInsets) -> { + if (!windowInsets.equals(mWindowInsets)) { + mWindowInsets = windowInsets; + mBubblePositioner.update(); + mStackView.onDisplaySizeChanged(); + } + return windowInsets; + }); + } } catch (IllegalStateException e) { - // This means the stack has already been added. This shouldn't happen... + // This means the view has already been added. This shouldn't happen... e.printStackTrace(); } } @@ -770,7 +805,7 @@ public class BubbleController implements ConfigurationChangeListener, } } - /** Removes the BubbleStackView from the WindowManager if it's there. */ + /** Removes any bubble views from the WindowManager that exist. */ private void removeFromWindowManagerMaybe() { if (!mAddedToWindowManager) { return; @@ -791,8 +826,10 @@ public class BubbleController implements ConfigurationChangeListener, if (mStackView != null) { mWindowManager.removeView(mStackView); mBubbleData.getOverflow().cleanUpExpandedState(); - } else { - Log.w(TAG, "StackView added to WindowManager, but was null when removing!"); + } + if (mLayerView != null) { + mWindowManager.removeView(mLayerView); + mBubbleData.getOverflow().cleanUpExpandedState(); } } catch (IllegalArgumentException e) { // This means the stack has already been removed - it shouldn't happen, but ignore if it @@ -887,12 +924,22 @@ public class BubbleController implements ConfigurationChangeListener, // Reload each bubble for (Bubble b : mBubbleData.getBubbles()) { - b.inflate(null /* callback */, mContext, this, mStackView, mBubbleIconFactory, + b.inflate(null /* callback */, + mContext, + this, + mStackView, + mLayerView, + mBubbleIconFactory, mBubbleBadgeIconFactory, false /* skipInflation */); } for (Bubble b : mBubbleData.getOverflowBubbles()) { - b.inflate(null /* callback */, mContext, this, mStackView, mBubbleIconFactory, + b.inflate(null /* callback */, + mContext, + this, + mStackView, + mLayerView, + mBubbleIconFactory, mBubbleBadgeIconFactory, false /* skipInflation */); } @@ -959,7 +1006,7 @@ public class BubbleController implements ConfigurationChangeListener, */ @VisibleForTesting public boolean hasBubbles() { - if (mStackView == null) { + if (mStackView == null && mLayerView == null) { return false; } return mBubbleData.hasBubbles() || mBubbleData.isShowingOverflow(); @@ -1166,7 +1213,12 @@ public class BubbleController implements ConfigurationChangeListener, } bubble.inflate( (b) -> mBubbleData.overflowBubble(Bubbles.DISMISS_RELOAD_FROM_DISK, bubble), - mContext, this, mStackView, mBubbleIconFactory, mBubbleBadgeIconFactory, + mContext, + this, + mStackView, + mLayerView, + mBubbleIconFactory, + mBubbleBadgeIconFactory, true /* skipInflation */); }); return null; @@ -1238,10 +1290,11 @@ public class BubbleController implements ConfigurationChangeListener, @VisibleForTesting public void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) { // Lazy init stack view when a bubble is created - ensureStackViewCreated(); + ensureBubbleViewsAndWindowCreated(); bubble.setInflateSynchronously(mInflateSynchronously); bubble.inflate(b -> mBubbleData.notificationEntryUpdated(b, suppressFlyout, showInShade), - mContext, this, mStackView, mBubbleIconFactory, mBubbleBadgeIconFactory, + mContext, this, mStackView, mLayerView, + mBubbleIconFactory, mBubbleBadgeIconFactory, false /* skipInflation */); } @@ -1475,7 +1528,7 @@ public class BubbleController implements ConfigurationChangeListener, + " unsuppressed=" + (update.unsuppressedBubble != null)); } - ensureStackViewCreated(); + ensureBubbleViewsAndWindowCreated(); // Lazy load overflow bubbles from disk loadOverflowBubblesFromDisk(); @@ -1570,7 +1623,7 @@ public class BubbleController implements ConfigurationChangeListener, } mSysuiProxy.notifyInvalidateNotifications("BubbleData.Listener.applyUpdate"); - updateStack(); + updateBubbleViews(); // Update the cached state for queries from SysUI mImpl.mCachedState.update(update); @@ -1650,28 +1703,42 @@ public class BubbleController implements ConfigurationChangeListener, /** * Updates the visibility of the bubbles based on current state. - * Does not un-bubble, just hides or un-hides. - * Updates stack description for TalkBack focus. - * Updates bubbles' icon views clickable states + * Does not un-bubble, just hides or un-hides the views themselves. + * + * Updates view description for TalkBack focus. + * Updates bubbles' icon views clickable states (when floating). */ - public void updateStack() { - if (mStackView == null) { + public void updateBubbleViews() { + if (mStackView == null && mLayerView == null) { return; } if (!mIsStatusBarShade) { - // Bubbles don't appear over the locked shade. - mStackView.setVisibility(INVISIBLE); + // Bubbles don't appear when the device is locked. + if (mStackView != null) { + mStackView.setVisibility(INVISIBLE); + } + if (mLayerView != null) { + mLayerView.setVisibility(INVISIBLE); + } } else if (hasBubbles()) { // If we're unlocked, show the stack if we have bubbles. If we don't have bubbles, the // stack will be set to INVISIBLE in onAllBubblesAnimatedOut after the bubbles animate // out. - mStackView.setVisibility(VISIBLE); + if (mStackView != null) { + mStackView.setVisibility(VISIBLE); + } + if (mLayerView != null && isStackExpanded()) { + mLayerView.setVisibility(VISIBLE); + } } - mStackView.updateContentDescription(); - - mStackView.updateBubblesAcessibillityStates(); + if (mStackView != null) { + mStackView.updateContentDescription(); + mStackView.updateBubblesAcessibillityStates(); + } else if (mLayerView != null) { + // TODO(b/273313561): handle a11y for BubbleBarLayerView + } } @VisibleForTesting diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java index f437553337efe..1a97c0504b379 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleViewInfoTask.java @@ -22,6 +22,7 @@ import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES; import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -38,12 +39,12 @@ import android.util.Log; import android.util.PathParser; import android.view.LayoutInflater; -import androidx.annotation.Nullable; -import androidx.annotation.VisibleForTesting; - +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.launcher3.icons.BitmapInfo; import com.android.wm.shell.R; +import com.android.wm.shell.bubbles.bar.BubbleBarExpandedView; +import com.android.wm.shell.bubbles.bar.BubbleBarLayerView; import java.lang.ref.WeakReference; import java.util.Objects; @@ -70,6 +71,7 @@ public class BubbleViewInfoTask extends AsyncTask mContext; private WeakReference mController; private WeakReference mStackView; + private WeakReference mLayerView; private BubbleIconFactory mIconFactory; private BubbleBadgeIconFactory mBadgeIconFactory; private boolean mSkipInflation; @@ -83,7 +85,8 @@ public class BubbleViewInfoTask extends AsyncTask(context); mController = new WeakReference<>(controller); mStackView = new WeakReference<>(stackView); + mLayerView = new WeakReference<>(layerView); mIconFactory = factory; mBadgeIconFactory = badgeFactory; mSkipInflation = skipInflation; @@ -102,8 +106,13 @@ public class BubbleViewInfoTask extends AsyncTask