summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt2
-rw-r--r--core/java/android/app/Notification.java133
2 files changed, 100 insertions, 35 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 2b5196b3b5f7..297de90047be 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -5654,6 +5654,7 @@ package android.app {
field public static final String EXTRA_PEOPLE_LIST = "android.people.list";
field public static final String EXTRA_PICTURE = "android.picture";
field public static final String EXTRA_PICTURE_CONTENT_DESCRIPTION = "android.pictureContentDescription";
+ field public static final String EXTRA_PICTURE_ICON = "android.pictureIcon";
field public static final String EXTRA_PROGRESS = "android.progress";
field public static final String EXTRA_PROGRESS_INDETERMINATE = "android.progressIndeterminate";
field public static final String EXTRA_PROGRESS_MAX = "android.progressMax";
@@ -5802,6 +5803,7 @@ package android.app {
method @NonNull public android.app.Notification.BigPictureStyle bigLargeIcon(@Nullable android.graphics.Bitmap);
method @NonNull public android.app.Notification.BigPictureStyle bigLargeIcon(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.app.Notification.BigPictureStyle bigPicture(@Nullable android.graphics.Bitmap);
+ method @NonNull public android.app.Notification.BigPictureStyle bigPicture(@Nullable android.graphics.drawable.Icon);
method @NonNull public android.app.Notification.BigPictureStyle bigPictureContentDescription(@Nullable CharSequence);
method @NonNull public android.app.Notification.BigPictureStyle setBigContentTitle(@Nullable CharSequence);
method @NonNull public android.app.Notification.BigPictureStyle setSummaryText(@Nullable CharSequence);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 11572953a188..14e9b6aa6657 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1196,6 +1196,13 @@ public class Notification implements Parcelable
public static final String EXTRA_PICTURE = "android.picture";
/**
+ * {@link #extras} key: this is an {@link Icon} of an image to be
+ * shown in {@link BigPictureStyle} expanded notifications, supplied to
+ * {@link BigPictureStyle#bigPicture(Icon)}.
+ */
+ public static final String EXTRA_PICTURE_ICON = "android.pictureIcon";
+
+ /**
* {@link #extras} key: this is a content description of the big picture supplied from
* {@link BigPictureStyle#bigPicture(Bitmap)}, supplied to
* {@link BigPictureStyle#bigPictureContentDescription(CharSequence)}.
@@ -2657,6 +2664,14 @@ public class Notification implements Parcelable
}
}
+ private static void visitIconUri(@NonNull Consumer<Uri> visitor, @Nullable Icon icon) {
+ if (icon == null) return;
+ final int iconType = icon.getType();
+ if (iconType == TYPE_URI || iconType == TYPE_URI_ADAPTIVE_BITMAP) {
+ visitor.accept(icon.getUri());
+ }
+ }
+
/**
* Note all {@link Uri} that are referenced internally, with the expectation
* that Uri permission grants will need to be issued to ensure the recipient
@@ -2672,7 +2687,19 @@ public class Notification implements Parcelable
if (bigContentView != null) bigContentView.visitUris(visitor);
if (headsUpContentView != null) headsUpContentView.visitUris(visitor);
+ visitIconUri(visitor, mSmallIcon);
+ visitIconUri(visitor, mLargeIcon);
+
+ if (actions != null) {
+ for (Action action : actions) {
+ visitIconUri(visitor, action.getIcon());
+ }
+ }
+
if (extras != null) {
+ visitIconUri(visitor, extras.getParcelable(EXTRA_LARGE_ICON_BIG));
+ visitIconUri(visitor, extras.getParcelable(EXTRA_PICTURE_ICON));
+
// NOTE: The documentation of EXTRA_AUDIO_CONTENTS_URI explicitly says that it is a
// String representation of a Uri, but the previous implementation (and unit test) of
// this method has always treated it as a Uri object. Given the inconsistency,
@@ -2691,14 +2718,12 @@ public class Notification implements Parcelable
ArrayList<Person> people = extras.getParcelableArrayList(EXTRA_PEOPLE_LIST);
if (people != null && !people.isEmpty()) {
for (Person p : people) {
- if (p.getIconUri() != null) {
- visitor.accept(p.getIconUri());
- }
+ visitor.accept(p.getIconUri());
}
}
final Person person = extras.getParcelable(EXTRA_MESSAGING_PERSON);
- if (person != null && person.getIconUri() != null) {
+ if (person != null) {
visitor.accept(person.getIconUri());
}
}
@@ -2711,7 +2736,7 @@ public class Notification implements Parcelable
visitor.accept(message.getDataUri());
Person senderPerson = message.getSenderPerson();
- if (senderPerson != null && senderPerson.getIconUri() != null) {
+ if (senderPerson != null) {
visitor.accept(senderPerson.getIconUri());
}
}
@@ -2724,19 +2749,15 @@ public class Notification implements Parcelable
visitor.accept(message.getDataUri());
Person senderPerson = message.getSenderPerson();
- if (senderPerson != null && senderPerson.getIconUri() != null) {
+ if (senderPerson != null) {
visitor.accept(senderPerson.getIconUri());
}
}
}
}
- if (mBubbleMetadata != null && mBubbleMetadata.getIcon() != null) {
- final Icon icon = mBubbleMetadata.getIcon();
- final int iconType = icon.getType();
- if (iconType == TYPE_URI_ADAPTIVE_BITMAP || iconType == TYPE_URI) {
- visitor.accept(icon.getUri());
- }
+ if (mBubbleMetadata != null) {
+ visitIconUri(visitor, mBubbleMetadata.getIcon());
}
}
@@ -7220,7 +7241,7 @@ public class Notification implements Parcelable
* @see Notification#bigContentView
*/
public static class BigPictureStyle extends Style {
- private Bitmap mPicture;
+ private Icon mPictureIcon;
private Icon mBigLargeIcon;
private boolean mBigLargeIconSet = false;
private CharSequence mPictureContentDescription;
@@ -7269,8 +7290,12 @@ public class Notification implements Parcelable
/**
* @hide
*/
- public Bitmap getBigPicture() {
- return mPicture;
+ @Nullable
+ public Icon getBigPicture() {
+ if (mPictureIcon != null) {
+ return mPictureIcon;
+ }
+ return null;
}
/**
@@ -7278,7 +7303,16 @@ public class Notification implements Parcelable
*/
@NonNull
public BigPictureStyle bigPicture(@Nullable Bitmap b) {
- mPicture = b;
+ mPictureIcon = b == null ? null : Icon.createWithBitmap(b);
+ return this;
+ }
+
+ /**
+ * Provide the content Uri to be used as the payload for the BigPicture notification.
+ */
+ @NonNull
+ public BigPictureStyle bigPicture(@Nullable Icon icon) {
+ mPictureIcon = icon;
return this;
}
@@ -7320,10 +7354,8 @@ public class Notification implements Parcelable
@Override
public void purgeResources() {
super.purgeResources();
- if (mPicture != null &&
- mPicture.isMutable() &&
- mPicture.getAllocationByteCount() >= MIN_ASHMEM_BITMAP_SIZE) {
- mPicture = mPicture.asShared();
+ if (mPictureIcon != null) {
+ mPictureIcon.convertToAshmem();
}
if (mBigLargeIcon != null) {
mBigLargeIcon.convertToAshmem();
@@ -7338,14 +7370,14 @@ public class Notification implements Parcelable
super.reduceImageSizes(context);
Resources resources = context.getResources();
boolean isLowRam = ActivityManager.isLowRamDeviceStatic();
- if (mPicture != null) {
+ if (mPictureIcon != null) {
int maxPictureWidth = resources.getDimensionPixelSize(isLowRam
? R.dimen.notification_big_picture_max_height_low_ram
: R.dimen.notification_big_picture_max_height);
int maxPictureHeight = resources.getDimensionPixelSize(isLowRam
? R.dimen.notification_big_picture_max_width_low_ram
: R.dimen.notification_big_picture_max_width);
- mPicture = Icon.scaleDownIfNecessary(mPicture, maxPictureWidth, maxPictureHeight);
+ mPictureIcon.scaleDownIfNecessary(maxPictureWidth, maxPictureHeight);
}
if (mBigLargeIcon != null) {
int rightIconSize = resources.getDimensionPixelSize(isLowRam
@@ -7360,12 +7392,12 @@ public class Notification implements Parcelable
*/
@Override
public RemoteViews makeContentView(boolean increasedHeight) {
- if (mPicture == null || !mShowBigPictureWhenCollapsed) {
+ if (mPictureIcon == null || !mShowBigPictureWhenCollapsed) {
return super.makeContentView(increasedHeight);
}
Icon oldLargeIcon = mBuilder.mN.mLargeIcon;
- mBuilder.mN.mLargeIcon = Icon.createWithBitmap(mPicture);
+ mBuilder.mN.mLargeIcon = mPictureIcon;
// The legacy largeIcon might not allow us to clear the image, as it's taken in
// replacement if the other one is null. Because we're restoring these legacy icons
// for old listeners, this is in general non-null.
@@ -7390,12 +7422,12 @@ public class Notification implements Parcelable
*/
@Override
public RemoteViews makeHeadsUpContentView(boolean increasedHeight) {
- if (mPicture == null || !mShowBigPictureWhenCollapsed) {
+ if (mPictureIcon == null || !mShowBigPictureWhenCollapsed) {
return super.makeHeadsUpContentView(increasedHeight);
}
Icon oldLargeIcon = mBuilder.mN.mLargeIcon;
- mBuilder.mN.mLargeIcon = Icon.createWithBitmap(mPicture);
+ mBuilder.mN.mLargeIcon = mPictureIcon;
// The legacy largeIcon might not allow us to clear the image, as it's taken in
// replacement if the other one is null. Because we're restoring these legacy icons
// for old listeners, this is in general non-null.
@@ -7452,7 +7484,7 @@ public class Notification implements Parcelable
mBuilder.mN.largeIcon = largeIconLegacy;
}
- contentView.setImageViewBitmap(R.id.big_picture, mPicture);
+ contentView.setImageViewIcon(R.id.big_picture, mPictureIcon);
if (mPictureContentDescription != null) {
contentView.setContentDescription(R.id.big_picture, mPictureContentDescription);
@@ -7475,7 +7507,17 @@ public class Notification implements Parcelable
mPictureContentDescription);
}
extras.putBoolean(EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED, mShowBigPictureWhenCollapsed);
- extras.putParcelable(EXTRA_PICTURE, mPicture);
+
+ // If the icon contains a bitmap, use the old extra so that listeners which look for
+ // that extra can still find the picture. Don't include the new extra in that case,
+ // to avoid duplicating data.
+ if (mPictureIcon != null && mPictureIcon.getType() == Icon.TYPE_BITMAP) {
+ extras.putParcelable(EXTRA_PICTURE, mPictureIcon.getBitmap());
+ extras.putParcelable(EXTRA_PICTURE_ICON, null);
+ } else {
+ extras.putParcelable(EXTRA_PICTURE, null);
+ extras.putParcelable(EXTRA_PICTURE_ICON, mPictureIcon);
+ }
}
/**
@@ -7496,7 +7538,16 @@ public class Notification implements Parcelable
}
mShowBigPictureWhenCollapsed = extras.getBoolean(EXTRA_SHOW_BIG_PICTURE_WHEN_COLLAPSED);
- mPicture = extras.getParcelable(EXTRA_PICTURE);
+
+ // When this style adds a picture, we only add one of the keys. If both were added,
+ // it would most likely be a legacy app trying to override the picture in some way.
+ // Because of that case it's better to give precedence to the legacy field.
+ Bitmap bitmapPicture = extras.getParcelable(EXTRA_PICTURE);
+ if (bitmapPicture != null) {
+ mPictureIcon = Icon.createWithBitmap(bitmapPicture);
+ } else {
+ mPictureIcon = extras.getParcelable(EXTRA_PICTURE_ICON);
+ }
}
/**
@@ -7518,20 +7569,32 @@ public class Notification implements Parcelable
return true;
}
BigPictureStyle otherS = (BigPictureStyle) other;
- return areBitmapsObviouslyDifferent(getBigPicture(), otherS.getBigPicture());
+ return areIconsObviouslyDifferent(getBigPicture(), otherS.getBigPicture());
}
- private static boolean areBitmapsObviouslyDifferent(Bitmap a, Bitmap b) {
+ private static boolean areIconsObviouslyDifferent(Icon a, Icon b) {
if (a == b) {
return false;
}
if (a == null || b == null) {
return true;
}
- return a.getWidth() != b.getWidth()
- || a.getHeight() != b.getHeight()
- || a.getConfig() != b.getConfig()
- || a.getGenerationId() != b.getGenerationId();
+ if (a.sameAs(b)) {
+ return false;
+ }
+ final int aType = a.getType();
+ if (aType != b.getType()) {
+ return true;
+ }
+ if (aType == Icon.TYPE_BITMAP || aType == Icon.TYPE_ADAPTIVE_BITMAP) {
+ final Bitmap aBitmap = a.getBitmap();
+ final Bitmap bBitmap = b.getBitmap();
+ return aBitmap.getWidth() != bBitmap.getWidth()
+ || aBitmap.getHeight() != bBitmap.getHeight()
+ || aBitmap.getConfig() != bBitmap.getConfig()
+ || aBitmap.getGenerationId() != bBitmap.getGenerationId();
+ }
+ return true;
}
}