diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 91a8ab5f692f1..bfc646bf6f8f5 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -113,6 +113,7 @@ android_library {
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
"androidx-constraintlayout_constraintlayout",
+ "iconloader_base",
"SystemUI-tags",
"SystemUI-proto",
"metrics-helper-lib",
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 47b9e9e27ae69..919844e387265 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1110,7 +1110,9 @@
16dp
- 52dp
+ 60dp
+
+ 52dp
56dp
@@ -1142,9 +1144,9 @@
5dp
- 5dp
+ 9dp
- 100dp
+ 96dp
48dp
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
index c91ba34f6dbff..f0f351fa25fea 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgeRenderer.java
@@ -55,9 +55,9 @@ public class BadgeRenderer {
/** Space between the center of the dot and the top or left of the bubble stack. */
static float getDotCenterOffset(Context context) {
- final int iconSizePx =
- context.getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
- return SIZE_PERCENTAGE * iconSizePx;
+ final int iconBitmapSize =
+ context.getResources().getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
+ return SIZE_PERCENTAGE * iconBitmapSize;
}
static float getDotRadius(float dotCenterOffset) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
index 783780f8819c6..d2fd13e3ad00a 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BadgedImageView.java
@@ -32,7 +32,8 @@ import com.android.systemui.R;
public class BadgedImageView extends ImageView {
private BadgeRenderer mDotRenderer;
- private int mIconSize;
+ private int mIconBitmapSize;
+
private Rect mTempBounds = new Rect();
private Point mTempPoint = new Point();
@@ -56,7 +57,7 @@ public class BadgedImageView extends ImageView {
public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
- mIconSize = getResources().getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mIconBitmapSize = getResources().getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
mDotRenderer = new BadgeRenderer(getContext());
TypedArray ta = context.obtainStyledAttributes(
@@ -69,7 +70,7 @@ public class BadgedImageView extends ImageView {
super.onDraw(canvas);
if (mShowUpdateDot) {
getDrawingRect(mTempBounds);
- mTempPoint.set((getWidth() - mIconSize) / 2, getPaddingTop());
+ mTempPoint.set((getWidth() - mIconBitmapSize) / 2, getPaddingTop());
mDotRenderer.draw(canvas, mUpdateDotColor, mTempBounds, mDotScale, mTempPoint,
mOnLeft);
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
index 71f68c16bd8d0..1cf52813632a7 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleFlyoutView.java
@@ -57,6 +57,7 @@ public class BubbleFlyoutView extends FrameLayout {
private final int mFlyoutSpaceFromBubble;
private final int mPointerSize;
private final int mBubbleSize;
+ private final int mBubbleIconBitmapSize;
private final int mFlyoutElevation;
private final int mBubbleElevation;
private final int mFloatingBackgroundColor;
@@ -143,7 +144,9 @@ public class BubbleFlyoutView extends FrameLayout {
mFlyoutPadding = res.getDimensionPixelSize(R.dimen.bubble_flyout_padding_x);
mFlyoutSpaceFromBubble = res.getDimensionPixelSize(R.dimen.bubble_flyout_space_from_bubble);
mPointerSize = res.getDimensionPixelSize(R.dimen.bubble_flyout_pointer_size);
+
mBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubbleIconBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
mBubbleElevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mFlyoutElevation = res.getDimensionPixelSize(R.dimen.bubble_flyout_elevation);
mNewDotOffsetFromBubbleBounds = BadgeRenderer.getDotCenterOffset(context);
@@ -216,7 +219,8 @@ public class BubbleFlyoutView extends FrameLayout {
post(() -> {
// Multi line flyouts get top-aligned to the bubble.
if (mFlyoutText.getLineCount() > 1) {
- setTranslationY(stackPos.y);
+ float bubbleIconTopPadding = (mBubbleSize - mBubbleIconBitmapSize) / 2f;
+ setTranslationY(stackPos.y + bubbleIconTopPadding);
} else {
// Single line flyouts are vertically centered with respect to the bubble.
setTranslationY(
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
new file mode 100644
index 0000000000000..dc38d59f8753f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleIconFactory.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 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.content.Context;
+
+import com.android.launcher3.icons.BaseIconFactory;
+
+/**
+ * Factory for creating normalized bubble icons.
+ * We are not using Launcher's IconFactory because bubbles only runs on the UI thread,
+ * so there is no need to manage a pool across multiple threads.
+ */
+public class BubbleIconFactory extends BaseIconFactory {
+ protected BubbleIconFactory(Context context, int iconBitmapSize) {
+ super(context, context.getResources().getConfiguration().densityDpi, iconBitmapSize);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 4e41dced7cab5..6487e422e7d87 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -32,7 +32,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PointF;
@@ -49,7 +48,6 @@ import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewOutlineProvider;
import android.view.ViewTreeObserver;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -183,7 +181,7 @@ public class BubbleStackView extends FrameLayout {
private int mStatusBarHeight;
private int mPipDismissHeight;
private int mImeOffset;
-
+ private BubbleIconFactory mBubbleIconFactory;
private Bubble mExpandedBubble;
private boolean mIsExpanded;
private boolean mImeVisible;
@@ -284,7 +282,8 @@ public class BubbleStackView extends FrameLayout {
}
};
- @NonNull private final SurfaceSynchronizer mSurfaceSynchronizer;
+ @NonNull
+ private final SurfaceSynchronizer mSurfaceSynchronizer;
private BubbleDismissView mDismissContainer;
private Runnable mAfterMagnet;
@@ -337,6 +336,9 @@ public class BubbleStackView extends FrameLayout {
mBubbleContainer.setClipChildren(false);
addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
+ int iconBitmapSize = getResources().getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
+ mBubbleIconFactory = new BubbleIconFactory(context, iconBitmapSize);
+
mExpandedViewContainer = new FrameLayout(context);
mExpandedViewContainer.setElevation(elevation);
mExpandedViewContainer.setPadding(mExpandedViewPadding, mExpandedViewPadding,
@@ -455,7 +457,7 @@ public class BubbleStackView extends FrameLayout {
* Handle theme changes.
*/
public void onThemeChanged() {
- for (Bubble b: mBubbleData.getBubbles()) {
+ for (Bubble b : mBubbleData.getBubbles()) {
b.iconView.updateViews();
b.expandedView.applyThemeAttrs();
}
@@ -618,6 +620,7 @@ public class BubbleStackView extends FrameLayout {
/**
* Updates the visibility of the 'dot' indicating an update on the bubble.
+ *
* @param key the {@link NotificationEntry#key} associated with the bubble.
*/
public void updateDotVisibility(String key) {
@@ -690,6 +693,9 @@ public class BubbleStackView extends FrameLayout {
Log.d(TAG, "addBubble: " + bubble);
}
bubble.inflate(mInflater, this);
+ bubble.iconView.setBubbleIconFactory(mBubbleIconFactory);
+ bubble.iconView.updateViews();
+
mBubbleContainer.addView(bubble.iconView, 0,
new FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
ViewClippingUtil.setClippingDeactivated(bubble.iconView, true, mClippingParameters);
@@ -796,6 +802,7 @@ public class BubbleStackView extends FrameLayout {
/**
* Dismiss the stack of bubbles.
+ *
* @deprecated
*/
@Deprecated
@@ -1518,24 +1525,12 @@ public class BubbleStackView extends FrameLayout {
/** Sets the appropriate Z-order and dot position for each bubble in the stack. */
private void updateBubbleShadowsAndDotPosition(boolean animate) {
- int bubbsCount = mBubbleContainer.getChildCount();
- for (int i = 0; i < bubbsCount; i++) {
+ int bubbleCount = mBubbleContainer.getChildCount();
+ for (int i = 0; i < bubbleCount; i++) {
BubbleView bv = (BubbleView) mBubbleContainer.getChildAt(i);
bv.updateDotVisibility(true /* animate */);
bv.setZ((BubbleController.MAX_BUBBLES
* getResources().getDimensionPixelSize(R.dimen.bubble_elevation)) - i);
-
- // Draw the shadow around the circle inscribed within the bubble's bounds. This
- // (intentionally) does not draw a shadow behind the update dot, which should be drawing
- // its own shadow since it's on a different (higher) plane.
- bv.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setOval(0, 0, mBubbleSize, mBubbleSize);
- }
- });
- bv.setClipToOutline(false);
-
// If the dot is on the left, and so is the stack, we need to change the dot position.
if (bv.getDotPositionOnLeft() == mStackOnLeftOrWillBe) {
bv.setDotPosition(!mStackOnLeftOrWillBe, animate);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
index 3442245f4f609..697d381162eb3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleView.java
@@ -29,6 +29,7 @@ import android.util.AttributeSet;
import android.widget.FrameLayout;
import com.android.internal.graphics.ColorUtils;
+import com.android.launcher3.icons.BitmapInfo;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -41,7 +42,7 @@ public class BubbleView extends FrameLayout {
private static final int DARK_ICON_ALPHA = 180;
private static final double ICON_MIN_CONTRAST = 4.1;
- private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
+ private static final int DEFAULT_BACKGROUND_COLOR = Color.LTGRAY;
// Same value as Launcher3 badge code
private static final float WHITE_SCRIM_ALPHA = 0.54f;
private Context mContext;
@@ -50,6 +51,9 @@ public class BubbleView extends FrameLayout {
private int mBadgeColor;
private int mIconInset;
+ // mBubbleIconFactory cannot be static because it depends on Context.
+ private BubbleIconFactory mBubbleIconFactory;
+
private boolean mSuppressDot = false;
private NotificationEntry mEntry;
@@ -93,7 +97,6 @@ public class BubbleView extends FrameLayout {
*/
public void setNotif(NotificationEntry entry) {
mEntry = entry;
- updateViews();
}
/**
@@ -120,6 +123,13 @@ public class BubbleView extends FrameLayout {
updateViews();
}
+ /**
+ * @param factory Factory for creating normalized bubble icons.
+ */
+ public void setBubbleIconFactory(BubbleIconFactory factory) {
+ mBubbleIconFactory = factory;
+ }
+
/**
* @return the {@link ExpandableNotificationRow} view to display notification content when the
* bubble is expanded.
@@ -203,7 +213,7 @@ public class BubbleView extends FrameLayout {
}
void updateViews() {
- if (mEntry == null) {
+ if (mEntry == null || mBubbleIconFactory == null) {
return;
}
Notification.BubbleMetadata metadata = mEntry.getBubbleMetadata();
@@ -219,10 +229,13 @@ public class BubbleView extends FrameLayout {
}
Drawable iconDrawable = ic.loadDrawable(mContext);
if (needsTint) {
- mBadgedImageView.setImageDrawable(buildIconWithTint(iconDrawable, n.color));
- } else {
- mBadgedImageView.setImageDrawable(iconDrawable);
+ iconDrawable = buildIconWithTint(iconDrawable, n.color);
}
+ BitmapInfo bitmapInfo = mBubbleIconFactory.createBadgedIconBitmap(iconDrawable,
+ null /* user */,
+ true /* shrinkNonAdaptiveIcons */);
+ mBadgedImageView.setImageBitmap(bitmapInfo.icon);
+
int badgeColor = determineDominateColor(iconDrawable, n.color);
mBadgeColor = badgeColor;
mBadgedImageView.setDotColor(badgeColor);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index f111f04cd4f91..b69b94c6d00a9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -86,10 +86,12 @@ public class ExpandedAnimationController
private boolean mSpringingBubbleToTouch = false;
private int mExpandedViewPadding;
+ private float mLauncherGridDiff;
public ExpandedAnimationController(Point displaySize, int expandedViewPadding) {
mDisplaySize = displaySize;
mExpandedViewPadding = expandedViewPadding;
+ mLauncherGridDiff = 30f;
}
/**
@@ -438,8 +440,7 @@ public class ExpandedAnimationController
* [launcherGridDiff] --- arbitrary value until launcher exports widths
* Launcher's app icon grid edge that we must match
*/
- final float launcherGridDiff = mBubbleSizePx / 2f;
- final float rowMargins = (mExpandedViewPadding + launcherGridDiff) * 2;
+ final float rowMargins = (mExpandedViewPadding + mLauncherGridDiff) * 2;
final float maxRowWidth = mDisplaySize.x - rowMargins;
final float totalBubbleWidth = mBubblesMaxRendered * mBubbleSizePx;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index 356efc9da12ba..0d9e3b679611b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -140,7 +140,7 @@ public class StackAnimationController extends
/** Horizontal offset of bubbles in the stack. */
private float mStackOffset;
/** Diameter of the bubbles themselves. */
- private int mIndividualBubbleSize;
+ private int mBubbleIconBitmapSize;
/**
* The amount of space to add between the bubbles and certain UI elements, such as the top of
* the screen or the IME. This does not apply to the left/right sides of the screen since the
@@ -185,7 +185,7 @@ public class StackAnimationController extends
return false;
}
- float stackCenter = mStackPosition.x + mIndividualBubbleSize / 2;
+ float stackCenter = mStackPosition.x + mBubbleIconBitmapSize / 2;
float screenCenter = mLayout.getWidth() / 2;
return stackCenter < screenCenter;
}
@@ -218,7 +218,7 @@ public class StackAnimationController extends
* @return The X value that the stack will end up at after the fling/spring.
*/
public float flingStackThenSpringToEdge(float x, float velX, float velY) {
- final boolean stackOnLeftSide = x - mIndividualBubbleSize / 2 < mLayout.getWidth() / 2;
+ final boolean stackOnLeftSide = x - mBubbleIconBitmapSize / 2 < mLayout.getWidth() / 2;
final boolean stackShouldFlingLeft = stackOnLeftSide
? velX < ESCAPE_VELOCITY
@@ -427,7 +427,7 @@ public class StackAnimationController extends
: 0);
allowableRegion.right =
mLayout.getWidth()
- - mIndividualBubbleSize
+ - mBubbleIconBitmapSize
+ mBubbleOffscreen
- Math.max(
insets.getSystemWindowInsetRight(),
@@ -444,7 +444,7 @@ public class StackAnimationController extends
: 0);
allowableRegion.bottom =
mLayout.getHeight()
- - mIndividualBubbleSize
+ - mBubbleIconBitmapSize
- mBubblePaddingTop
- (mImeHeight > Float.MIN_VALUE ? mImeHeight + mBubblePaddingTop : 0f)
- Math.max(
@@ -517,7 +517,7 @@ public class StackAnimationController extends
mFirstBubbleSpringingToTouch = false;
animationForChildAtIndex(0)
- .translationX(mLayout.getWidth() / 2f - mIndividualBubbleSize / 2f)
+ .translationX(mLayout.getWidth() / 2f - mBubbleIconBitmapSize / 2f)
.translationY(destY, after)
.withPositionStartVelocities(velX, velY)
.withStiffness(SpringForce.STIFFNESS_MEDIUM)
@@ -657,7 +657,7 @@ public class StackAnimationController extends
void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
Resources res = layout.getResources();
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubbleIconBitmapSize = res.getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
mBubblePaddingTop = res.getDimensionPixelSize(R.dimen.bubble_padding_top);
mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
mStackStartingVerticalOffset =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 10b631d9b12c1..7a0bad28f0f14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -46,6 +46,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
private int mDisplayWidth = 500;
private int mDisplayHeight = 1000;
private int mExpandedViewPadding = 10;
+ private float mLauncherGridDiff = 30f;
@Spy
private ExpandedAnimationController mExpandedController =
@@ -281,8 +282,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
* @return Space between bubbles in row above expanded view.
*/
private float getSpaceBetweenBubbles() {
- final float launcherGridDiff = mBubbleSize / 2f;
- final float rowMargins = (mExpandedViewPadding + launcherGridDiff) * 2;
+ final float rowMargins = (mExpandedViewPadding + mLauncherGridDiff) * 2;
final float maxRowWidth = mDisplayWidth - rowMargins;
final float totalBubbleWidth = mMaxBubbles * mBubbleSize;