Bubbles taskbar broadcast

* listen for broadcasts related to taskbar
* update info in BubblePositioner based on that
* show a scrim behind the bubbles when taskbar is on left / right so
  you don't see contents beneath

Test: manual
Bug: 173386799
Bug: 167413172
Change-Id: Id520718e779d3a45bcde447d7fcb0d2ba785c88e
This commit is contained in:
Mady Mellor
2020-11-11 14:44:56 -08:00
parent f15a5fc2bf
commit 4ac05e33d3
7 changed files with 156 additions and 62 deletions

View File

@@ -24,6 +24,10 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_BUBBLES;
import static com.android.wm.shell.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_BOTTOM;
import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_LEFT;
import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_NONE;
import static com.android.wm.shell.bubbles.BubblePositioner.TASKBAR_POSITION_RIGHT;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -38,7 +42,9 @@ import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.graphics.PointF;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -81,6 +87,18 @@ public class BubbleController implements Bubbles {
private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES;
// TODO(b/173386799) keep in sync with Launcher3 and also don't do a broadcast
public static final String TASKBAR_CHANGED_BROADCAST = "taskbarChanged";
public static final String EXTRA_BUBBLE_OVERFLOW_OPENED = "bubbleOverflowOpened";
public static final String EXTRA_TASKBAR_VISIBLE = "taskbarVisible";
public static final String EXTRA_TASKBAR_POSITION = "taskbarPosition";
public static final String EXTRA_TASKBAR_ICON_SIZE = "taskbarIconSize";
public static final String EXTRA_TASKBAR_BUBBLE_XY = "taskbarBubbleXY";
public static final String EXTRA_TASKBAR_SIZE = "taskbarSize";
public static final String LEFT_POSITION = "Left";
public static final String RIGHT_POSITION = "Right";
public static final String BOTTOM_POSITION = "Bottom";
private final Context mContext;
private BubbleExpandListener mExpandListener;
@Nullable private BubbleStackView.SurfaceSynchronizer mSurfaceSynchronizer;
@@ -295,6 +313,57 @@ public class BubbleController implements Bubbles {
}
}
@Override
public void openBubbleOverflow() {
ensureStackViewCreated();
mBubbleData.setShowingOverflow(true);
mBubbleData.setSelectedBubble(mBubbleData.getOverflow());
mBubbleData.setExpanded(true);
}
/** Called when any taskbar state changes (e.g. visibility, position, sizes). */
@Override
public void onTaskbarChanged(Bundle b) {
if (b == null) {
return;
}
boolean isVisible = b.getBoolean(EXTRA_TASKBAR_VISIBLE, false /* default */);
String position = b.getString(EXTRA_TASKBAR_POSITION, RIGHT_POSITION /* default */);
@BubblePositioner.TaskbarPosition int taskbarPosition = TASKBAR_POSITION_NONE;
switch (position) {
case LEFT_POSITION:
taskbarPosition = TASKBAR_POSITION_LEFT;
break;
case RIGHT_POSITION:
taskbarPosition = TASKBAR_POSITION_RIGHT;
break;
case BOTTOM_POSITION:
taskbarPosition = TASKBAR_POSITION_BOTTOM;
break;
}
int[] itemPosition = b.getIntArray(EXTRA_TASKBAR_BUBBLE_XY);
int iconSize = b.getInt(EXTRA_TASKBAR_ICON_SIZE);
int taskbarSize = b.getInt(EXTRA_TASKBAR_SIZE);
Log.w(TAG, "onTaskbarChanged:"
+ " isVisible: " + isVisible
+ " position: " + position
+ " itemPosition: " + itemPosition[0] + "," + itemPosition[1]
+ " iconSize: " + iconSize);
PointF point = new PointF(itemPosition[0], itemPosition[1]);
mBubblePositioner.setPinnedLocation(point);
mBubblePositioner.updateForTaskbar(iconSize, taskbarPosition, isVisible, taskbarSize);
if (mStackView != null) {
if (isVisible) {
mStackView.updateStackPosition();
}
mBubbleIconFactory = new BubbleIconFactory(mContext);
mStackView.onDisplaySizeChanged();
}
if (b.getBoolean(EXTRA_BUBBLE_OVERFLOW_OPENED, false)) {
openBubbleOverflow();
}
}
/**
* Called when the status bar has become visible or invisible (either permanently or
* temporarily).

View File

@@ -396,7 +396,7 @@ public class BubbleExpandedView extends LinearLayout {
/** Return a GraphicBuffer with the contents of the task view surface. */
@Nullable
SurfaceControl.ScreenshotHardwareBuffer snapshotActivitySurface() {
if (mTaskView == null) {
if (mTaskView == null || mTaskView.getSurfaceControl() == null) {
return null;
}
return SurfaceControl.captureLayers(

View File

@@ -48,8 +48,10 @@ public class BubblePositioner {
: BubbleDebugConfig.TAG_BUBBLES;
@Retention(SOURCE)
@IntDef({TASKBAR_POSITION_RIGHT, TASKBAR_POSITION_LEFT, TASKBAR_POSITION_BOTTOM})
@IntDef({TASKBAR_POSITION_NONE, TASKBAR_POSITION_RIGHT, TASKBAR_POSITION_LEFT,
TASKBAR_POSITION_BOTTOM})
@interface TaskbarPosition {}
public static final int TASKBAR_POSITION_NONE = -1;
public static final int TASKBAR_POSITION_RIGHT = 0;
public static final int TASKBAR_POSITION_LEFT = 1;
public static final int TASKBAR_POSITION_BOTTOM = 2;
@@ -73,8 +75,9 @@ public class BubblePositioner {
private PointF mRestingStackPosition;
private boolean mShowingInTaskbar;
private @TaskbarPosition int mTaskbarPosition;
private @TaskbarPosition int mTaskbarPosition = TASKBAR_POSITION_NONE;
private int mTaskbarIconSize;
private int mTaskbarSize;
public BubblePositioner(Context context, WindowManager windowManager) {
mContext = context;
@@ -107,6 +110,21 @@ public class BubblePositioner {
updateInternal(orientation, insets, windowMetrics.getBounds());
}
/**
* Updates position information to account for taskbar state.
*
* @param taskbarPosition which position the taskbar is displayed in.
* @param showingInTaskbar whether the taskbar is being shown.
*/
public void updateForTaskbar(int iconSize,
@TaskbarPosition int taskbarPosition, boolean showingInTaskbar, int taskbarSize) {
mShowingInTaskbar = showingInTaskbar;
mTaskbarIconSize = iconSize;
mTaskbarPosition = taskbarPosition;
mTaskbarSize = taskbarSize;
update(mOrientation);
}
@VisibleForTesting
public void updateInternal(int orientation, Insets insets, Rect bounds) {
mOrientation = orientation;
@@ -121,21 +139,9 @@ public class BubblePositioner {
Resources res = mContext.getResources();
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mBubbleBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_bitmap_size);
adjustForTaskbar();
}
/**
* Updates position information to account for taskbar state.
*
* @param taskbarPosition which position the taskbar is displayed in.
* @param showingInTaskbar whether the taskbar is being shown.
*/
public void updateForTaskbar(int iconSize,
@TaskbarPosition int taskbarPosition, boolean showingInTaskbar) {
mShowingInTaskbar = showingInTaskbar;
mTaskbarIconSize = iconSize;
mTaskbarPosition = taskbarPosition;
update(mOrientation);
if (mShowingInTaskbar) {
adjustForTaskbar();
}
}
/**
@@ -262,6 +268,17 @@ public class BubblePositioner {
return mShowingInTaskbar;
}
/**
* @return the taskbar position if set.
*/
public int getTaskbarPosition() {
return mTaskbarPosition;
}
public int getTaskbarSize() {
return mTaskbarSize;
}
/**
* In some situations bubbles will be pinned to a specific onscreen location. This sets the
* location to anchor the stack to.

View File

@@ -32,6 +32,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Insets;
@@ -194,6 +195,7 @@ public class BubbleStackView extends FrameLayout
private StackAnimationController mStackAnimationController;
private ExpandedAnimationController mExpandedAnimationController;
private View mTaskbarScrim;
private FrameLayout mExpandedViewContainer;
/** Matrix used to scale the expanded view container with a given pivot point. */
@@ -631,7 +633,9 @@ public class BubbleStackView extends FrameLayout
public void onUp(@NonNull View v, @NonNull MotionEvent ev, float viewInitialX,
float viewInitialY, float dx, float dy, float velX, float velY) {
// If we're expanding or collapsing, ignore all touch events.
if (mIsExpansionAnimating) {
if (mIsExpansionAnimating
// Also ignore events if we shouldn't be draggable.
|| (mPositioner.showingInTaskbar() && !mIsExpanded)) {
return;
}
@@ -741,14 +745,13 @@ public class BubbleStackView extends FrameLayout
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleTouchPadding = res.getDimensionPixelSize(R.dimen.bubble_touch_padding);
mPointerHeight = res.getDimensionPixelSize(R.dimen.bubble_pointer_height);
mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
mPositioner = mBubbleController.getPositioner();
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mPositioner = mBubbleController.getPositioner();
final TypedArray ta = mContext.obtainStyledAttributes(
new int[] {android.R.attr.dialogCornerRadius});
mCornerRadius = ta.getDimensionPixelSize(0, 0);
@@ -840,6 +843,12 @@ public class BubbleStackView extends FrameLayout
mBubbleData.setExpanded(true);
});
mTaskbarScrim = new View(getContext());
mTaskbarScrim.setBackgroundColor(Color.BLACK);
addView(mTaskbarScrim);
mTaskbarScrim.setAlpha(0f);
mTaskbarScrim.setVisibility(GONE);
setOnApplyWindowInsetsListener((View view, WindowInsets insets) -> {
mBubbleController.onImeVisibilityChanged(
insets.getInsets(WindowInsets.Type.ime()).bottom > 0);
@@ -1631,6 +1640,7 @@ public class BubbleStackView extends FrameLayout
/** Set the stack position to whatever the positioner says. */
void updateStackPosition() {
mStackAnimationController.setStackPosition(mPositioner.getRestingPosition());
mDismissView.hide();
}
private void beforeExpandedViewAnimation() {
@@ -1664,6 +1674,17 @@ public class BubbleStackView extends FrameLayout
}
} /* after */);
if (mPositioner.showingInTaskbar()
// Don't need the scrim when the bar is at the bottom
&& mPositioner.getTaskbarPosition() != BubblePositioner.TASKBAR_POSITION_BOTTOM) {
mTaskbarScrim.getLayoutParams().width = mPositioner.getTaskbarSize();
mTaskbarScrim.setTranslationX(mStackOnLeftOrWillBe
? 0f
: mPositioner.getAvailableRect().right - mPositioner.getTaskbarSize());
mTaskbarScrim.setVisibility(VISIBLE);
mTaskbarScrim.animate().alpha(1f).start();
}
mExpandedViewContainer.setTranslationX(0f);
mExpandedViewContainer.setTranslationY(getExpandedViewY());
mExpandedViewContainer.setAlpha(1f);
@@ -1781,6 +1802,10 @@ public class BubbleStackView extends FrameLayout
/* collapseTo */,
() -> mBubbleContainer.setActiveController(mStackAnimationController)), startDelay);
if (mTaskbarScrim.getVisibility() == VISIBLE) {
mTaskbarScrim.animate().alpha(0f).start();
}
// We want to visually collapse into this bubble during the animation.
final View expandingFromBubble = mExpandedBubble.getIconView();
@@ -1856,6 +1881,10 @@ public class BubbleStackView extends FrameLayout
if (previouslySelected != null) {
previouslySelected.setContentVisibility(false);
}
if (mPositioner.showingInTaskbar()) {
mTaskbarScrim.setVisibility(GONE);
}
})
.start();
}

View File

@@ -22,6 +22,7 @@ import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.content.res.Configuration;
import android.os.Bundle;
import android.service.notification.NotificationListenerService.RankingMap;
import android.util.ArraySet;
import android.view.View;
@@ -104,6 +105,12 @@ public interface Bubbles {
*/
void expandStackAndSelectBubble(BubbleEntry entry);
/** Called for any taskbar changes. */
void onTaskbarChanged(Bundle b);
/** Open the overflow view. */
void openBubbleOverflow();
/**
* 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

View File

@@ -769,7 +769,6 @@ public class StackAnimationController extends
if (getBubbleCount() > 0) {
animationForChildAtIndex(0).translationX(mStackPosition.x).start();
} else {
// TODO: still needed with positioner?
// When all children are removed ensure stack position is sane
mPositioner.setRestingPosition(mPositioner.getRestingPosition());
@@ -939,45 +938,6 @@ public class StackAnimationController extends
setStackPosition(position.getAbsolutePositionInRegion(getAllowableStackPositionRegion()));
}
public BubbleStackView.RelativeStackPosition getRelativeStackPosition() {
return new BubbleStackView.RelativeStackPosition(
mStackPosition, getAllowableStackPositionRegion());
}
/**
* Sets the starting position for the stack, where it will be located when the first bubble is
* added.
*/
public void setStackStartPosition(BubbleStackView.RelativeStackPosition position) {
mStackStartPosition = position;
}
/**
* Returns the starting stack position. If {@link #setStackStartPosition} was called, this will
* return that position - otherwise, a reasonable default will be returned.
*/
@Nullable public PointF getStartPosition() {
if (mLayout == null) {
return null;
}
if (mStackStartPosition == null) {
// Start on the left if we're in LTR, right otherwise.
final boolean startOnLeft =
mLayout.getResources().getConfiguration().getLayoutDirection()
!= View.LAYOUT_DIRECTION_RTL;
final float startingVerticalOffset = mLayout.getResources().getDimensionPixelOffset(
R.dimen.bubble_stack_starting_offset_y);
mStackStartPosition = new BubbleStackView.RelativeStackPosition(
startOnLeft,
startingVerticalOffset / getAllowableStackPositionRegion().height());
}
return mStackStartPosition.getAbsolutePositionInRegion(getAllowableStackPositionRegion());
}
private boolean isStackPositionSet() {
return mStackMovedToStartPosition;
}

View File

@@ -45,6 +45,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCE
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING;
import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -561,6 +562,15 @@ public class StatusBar extends SystemUI implements DemoMode,
}
};
BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (mBubblesOptional.isPresent()) {
mBubblesOptional.get().onTaskbarChanged(intent.getExtras());
}
}
};
private Runnable mLaunchTransitionEndRunnable;
private NotificationEntry mDraggedDownEntry;
private boolean mLaunchCameraWhenFinishedWaking;
@@ -844,6 +854,8 @@ public class StatusBar extends SystemUI implements DemoMode,
mBypassHeadsUpNotifier.setUp();
if (mBubblesOptional.isPresent()) {
mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
IntentFilter filter = new IntentFilter(TASKBAR_CHANGED_BROADCAST);
mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter);
}
mColorExtractor.addOnColorsChangedListener(this);