OSDN Git Service

Icon support comes to Notification.
authorDan Sandler <dsandler@android.com>
Wed, 6 May 2015 19:18:49 +0000 (15:18 -0400)
committerDan Sandler <dsandler@android.com>
Thu, 14 May 2015 03:50:43 +0000 (23:50 -0400)
  And you may ask yourself: what is that beautiful icon?
  And you may ask yourself: where does that API go to?
  And you may ask yourself: is it a resource? is it a Bitmap?
  And you may say to yourself: my god, what have I done

Bug: 18568715
Change-Id: I4377b311c538bd1cf36b3fba22326bae81af40c9

api/current.txt
api/system-current.txt
core/java/android/app/Notification.java
core/java/com/android/internal/statusbar/StatusBarIcon.java
core/java/com/android/internal/util/NotificationColorUtil.java
graphics/java/android/graphics/drawable/Icon.java
packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
services/core/java/com/android/server/notification/NotificationManagerService.java

index 42a0b61..95d8f1e 100644 (file)
@@ -4781,6 +4781,8 @@ package android.app {
     method public android.app.Notification clone();
     method public int describeContents();
     method public java.lang.String getGroup();
+    method public android.graphics.drawable.Icon getLargeIcon();
+    method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public void writeToParcel(android.os.Parcel, int);
@@ -4925,6 +4927,7 @@ package android.app {
     ctor public Notification.BigPictureStyle();
     ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
     method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap);
     method public android.app.Notification.BigPictureStyle setBigContentTitle(java.lang.CharSequence);
     method public android.app.Notification.BigPictureStyle setSummaryText(java.lang.CharSequence);
@@ -4963,6 +4966,7 @@ package android.app {
     method public android.app.Notification.Builder setGroup(java.lang.String);
     method public android.app.Notification.Builder setGroupSummary(boolean);
     method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
     method public android.app.Notification.Builder setNumber(int);
@@ -4974,6 +4978,7 @@ package android.app {
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
+    method public android.app.Notification.Builder setSmallIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setSortKey(java.lang.String);
     method public android.app.Notification.Builder setSound(android.net.Uri);
     method public deprecated android.app.Notification.Builder setSound(android.net.Uri, int);
index 7d5bdd4..5d11b25 100644 (file)
@@ -4875,6 +4875,8 @@ package android.app {
     method public android.app.Notification clone();
     method public int describeContents();
     method public java.lang.String getGroup();
+    method public android.graphics.drawable.Icon getLargeIcon();
+    method public android.graphics.drawable.Icon getSmallIcon();
     method public java.lang.String getSortKey();
     method public deprecated void setLatestEventInfo(android.content.Context, java.lang.CharSequence, java.lang.CharSequence, android.app.PendingIntent);
     method public void writeToParcel(android.os.Parcel, int);
@@ -5019,6 +5021,7 @@ package android.app {
     ctor public Notification.BigPictureStyle();
     ctor public Notification.BigPictureStyle(android.app.Notification.Builder);
     method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.BigPictureStyle bigLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.BigPictureStyle bigPicture(android.graphics.Bitmap);
     method public android.app.Notification.BigPictureStyle setBigContentTitle(java.lang.CharSequence);
     method public android.app.Notification.BigPictureStyle setSummaryText(java.lang.CharSequence);
@@ -5057,6 +5060,7 @@ package android.app {
     method public android.app.Notification.Builder setGroup(java.lang.String);
     method public android.app.Notification.Builder setGroupSummary(boolean);
     method public android.app.Notification.Builder setLargeIcon(android.graphics.Bitmap);
+    method public android.app.Notification.Builder setLargeIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setLights(int, int, int);
     method public android.app.Notification.Builder setLocalOnly(boolean);
     method public android.app.Notification.Builder setNumber(int);
@@ -5068,6 +5072,7 @@ package android.app {
     method public android.app.Notification.Builder setShowWhen(boolean);
     method public android.app.Notification.Builder setSmallIcon(int);
     method public android.app.Notification.Builder setSmallIcon(int, int);
+    method public android.app.Notification.Builder setSmallIcon(android.graphics.drawable.Icon);
     method public android.app.Notification.Builder setSortKey(java.lang.String);
     method public android.app.Notification.Builder setSound(android.net.Uri);
     method public deprecated android.app.Notification.Builder setSound(android.net.Uri, int);
index 49b2549..3ffeea7 100644 (file)
@@ -30,6 +30,7 @@ import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.PorterDuff;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.session.MediaSession;
@@ -885,6 +886,9 @@ public class Notification implements Parcelable
      */
     public static final int HEADS_UP_REQUESTED = 2;
 
+    private Icon mSmallIcon;
+    private Icon mLargeIcon;
+
     /**
      * Structure to encapsulate a named action that can be shown as part of this notification.
      * It must include an icon, a label, and a {@link PendingIntent} to be fired when the action is
@@ -1362,7 +1366,7 @@ public class Notification implements Parcelable
         int version = parcel.readInt();
 
         when = parcel.readLong();
-        icon = parcel.readInt();
+        mSmallIcon = Icon.CREATOR.createFromParcel(parcel);
         number = parcel.readInt();
         if (parcel.readInt() != 0) {
             contentIntent = PendingIntent.CREATOR.createFromParcel(parcel);
@@ -1380,7 +1384,7 @@ public class Notification implements Parcelable
             contentView = RemoteViews.CREATOR.createFromParcel(parcel);
         }
         if (parcel.readInt() != 0) {
-            largeIcon = Bitmap.CREATOR.createFromParcel(parcel);
+            mLargeIcon = Icon.CREATOR.createFromParcel(parcel);
         }
         defaults = parcel.readInt();
         flags = parcel.readInt();
@@ -1445,7 +1449,7 @@ public class Notification implements Parcelable
      */
     public void cloneInto(Notification that, boolean heavy) {
         that.when = this.when;
-        that.icon = this.icon;
+        that.mSmallIcon = this.mSmallIcon;
         that.number = this.number;
 
         // PendingIntents are global, so there's no reason (or way) to clone them.
@@ -1462,8 +1466,8 @@ public class Notification implements Parcelable
         if (heavy && this.contentView != null) {
             that.contentView = this.contentView.clone();
         }
-        if (heavy && this.largeIcon != null) {
-            that.largeIcon = Bitmap.createBitmap(this.largeIcon);
+        if (heavy && this.mLargeIcon != null) {
+            that.mLargeIcon = this.mLargeIcon;
         }
         that.iconLevel = this.iconLevel;
         that.sound = this.sound; // android.net.Uri is immutable
@@ -1544,7 +1548,7 @@ public class Notification implements Parcelable
         contentView = null;
         bigContentView = null;
         headsUpContentView = null;
-        largeIcon = null;
+        mLargeIcon = null;
         if (extras != null) {
             extras.remove(Notification.EXTRA_LARGE_ICON);
             extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
@@ -1586,7 +1590,7 @@ public class Notification implements Parcelable
         parcel.writeInt(1);
 
         parcel.writeLong(when);
-        parcel.writeInt(icon);
+        mSmallIcon.writeToParcel(parcel, 0);
         parcel.writeInt(number);
         if (contentIntent != null) {
             parcel.writeInt(1);
@@ -1618,9 +1622,9 @@ public class Notification implements Parcelable
         } else {
             parcel.writeInt(0);
         }
-        if (largeIcon != null) {
+        if (mLargeIcon != null) {
             parcel.writeInt(1);
-            largeIcon.writeToParcel(parcel, 0);
+            mLargeIcon.writeToParcel(parcel, 0);
         } else {
             parcel.writeInt(0);
         }
@@ -1865,6 +1869,27 @@ public class Notification implements Parcelable
     }
 
     /**
+     * The small icon representing this notification in the status bar and content view.
+     *
+     * @return the small icon representing this notification.
+     *
+     * @see Builder#getSmallIcon()
+     * @see Builder#setSmallIcon(Icon)
+     */
+    public Icon getSmallIcon() {
+        return mSmallIcon;
+    }
+
+    /**
+     * The large icon shown in this notification's content view.
+     * @see Builder#getLargeIcon()
+     * @see Builder#setLargeIcon(Icon)
+     */
+    public Icon getLargeIcon() {
+        return mLargeIcon;
+    }
+
+    /**
      * @hide
      */
     public boolean isValid() {
@@ -1966,7 +1991,7 @@ public class Notification implements Parcelable
         private Context mContext;
 
         private long mWhen;
-        private int mSmallIcon;
+        private Icon mSmallIcon, mLargeIcon;
         private int mSmallIconLevel;
         private int mNumber;
         private CharSequence mContentTitle;
@@ -1979,7 +2004,6 @@ public class Notification implements Parcelable
         private PendingIntent mFullScreenIntent;
         private CharSequence mTickerText;
         private RemoteViews mTickerView;
-        private Bitmap mLargeIcon;
         private Uri mSound;
         private int mAudioStreamType;
         private AudioAttributes mAudioAttributes;
@@ -2160,8 +2184,7 @@ public class Notification implements Parcelable
          * @see Notification#icon
          */
         public Builder setSmallIcon(@DrawableRes int icon) {
-            mSmallIcon = icon;
-            return this;
+            return setSmallIcon(Icon.createWithResource(mContext.getResources(), icon));
         }
 
         /**
@@ -2176,8 +2199,20 @@ public class Notification implements Parcelable
          * @see Notification#iconLevel
          */
         public Builder setSmallIcon(@DrawableRes int icon, int level) {
-            mSmallIcon = icon;
             mSmallIconLevel = level;
+            return setSmallIcon(icon);
+        }
+
+        /**
+         * Set the small icon, which will be used to represent the notification in the
+         * status bar and content view (unless overriden there by a
+         * {@link #setLargeIcon(Bitmap) large icon}).
+         *
+         * @param icon An Icon object to use.
+         * @see Notification#icon
+         */
+        public Builder setSmallIcon(Icon icon) {
+            mSmallIcon = icon;
             return this;
         }
 
@@ -2324,14 +2359,24 @@ public class Notification implements Parcelable
         }
 
         /**
-         * Add a large icon to the notification (and the ticker on some devices).
+         * Add a large icon to the notification content view.
          *
          * In the platform template, this image will be shown on the left of the notification view
-         * in place of the {@link #setSmallIcon(int) small icon} (which will move to the right side).
+         * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small
+         * badge atop the large icon).
+         */
+        public Builder setLargeIcon(Bitmap b) {
+            return setLargeIcon(b != null ? Icon.createWithBitmap(b) : null);
+        }
+
+        /**
+         * Add a large icon to the notification content view.
          *
-         * @see Notification#largeIcon
+         * In the platform template, this image will be shown on the left of the notification view
+         * in place of the {@link #setSmallIcon(Icon) small icon} (which will be placed in a small
+         * badge atop the large icon).
          */
-        public Builder setLargeIcon(Bitmap icon) {
+        public Builder setLargeIcon(Icon icon) {
             mLargeIcon = icon;
             return this;
         }
@@ -2840,13 +2885,13 @@ public class Notification implements Parcelable
             boolean contentTextInLine2 = false;
 
             if (mLargeIcon != null) {
-                contentView.setImageViewBitmap(R.id.icon, mLargeIcon);
+                contentView.setImageViewIcon(R.id.icon, mLargeIcon);
                 processLargeLegacyIcon(mLargeIcon, contentView);
-                contentView.setImageViewResource(R.id.right_icon, mSmallIcon);
+                contentView.setImageViewIcon(R.id.right_icon, mSmallIcon);
                 contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
                 processSmallRightIcon(mSmallIcon, contentView);
             } else { // small icon at left
-                contentView.setImageViewResource(R.id.icon, mSmallIcon);
+                contentView.setImageViewIcon(R.id.icon, mSmallIcon);
                 contentView.setViewVisibility(R.id.icon, View.VISIBLE);
                 processSmallIconAsLarge(mSmallIcon, contentView);
             }
@@ -3086,14 +3131,16 @@ public class Notification implements Parcelable
         /**
          * Apply any necessary background to smallIcons being used in the largeIcon spot.
          */
-        private void processSmallIconAsLarge(int largeIconId, RemoteViews contentView) {
+        private void processSmallIconAsLarge(Icon largeIcon, RemoteViews contentView) {
             if (!isLegacy()) {
                 contentView.setDrawableParameters(R.id.icon, false, -1,
                         0xFFFFFFFF,
                         PorterDuff.Mode.SRC_ATOP, -1);
-            }
-            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, largeIconId)) {
                 applyLargeIconBackground(contentView);
+            } else {
+                if (mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
+                    applyLargeIconBackground(contentView);
+                }
             }
         }
 
@@ -3102,8 +3149,9 @@ public class Notification implements Parcelable
          * if it's grayscale).
          */
         // TODO: also check bounds, transparency, that sort of thing.
-        private void processLargeLegacyIcon(Bitmap largeIcon, RemoteViews contentView) {
-            if (isLegacy() && mColorUtil.isGrayscaleIcon(largeIcon)) {
+        private void processLargeLegacyIcon(Icon largeIcon, RemoteViews contentView) {
+            if (largeIcon != null && isLegacy()
+                    && mColorUtil.isGrayscaleIcon(mContext, largeIcon)) {
                 applyLargeIconBackground(contentView);
             } else {
                 removeLargeIconBackground(contentView);
@@ -3137,14 +3185,15 @@ public class Notification implements Parcelable
         /**
          * Recolor small icons when used in the R.id.right_icon slot.
          */
-        private void processSmallRightIcon(int smallIconDrawableId,
-                RemoteViews contentView) {
+        private void processSmallRightIcon(Icon smallIcon, RemoteViews contentView) {
             if (!isLegacy()) {
                 contentView.setDrawableParameters(R.id.right_icon, false, -1,
                         0xFFFFFFFF,
                         PorterDuff.Mode.SRC_ATOP, -1);
             }
-            if (!isLegacy() || mColorUtil.isGrayscaleIcon(mContext, smallIconDrawableId)) {
+            final boolean gray = (smallIcon.getType() == Icon.TYPE_RESOURCE
+                    && mColorUtil.isGrayscaleIcon(mContext, smallIcon.getResId()));
+            if (!isLegacy() || gray) {
                 contentView.setInt(R.id.right_icon,
                         "setBackgroundResource",
                         R.drawable.notification_icon_legacy_bg);
@@ -3180,7 +3229,10 @@ public class Notification implements Parcelable
         public Notification buildUnstyled() {
             Notification n = new Notification();
             n.when = mWhen;
-            n.icon = mSmallIcon;
+            n.mSmallIcon = mSmallIcon;
+            if (mSmallIcon.getType() == Icon.TYPE_RESOURCE) {
+                n.icon = mSmallIcon.getResId();
+            }
             n.iconLevel = mSmallIconLevel;
             n.number = mNumber;
 
@@ -3192,7 +3244,10 @@ public class Notification implements Parcelable
             n.fullScreenIntent = mFullScreenIntent;
             n.tickerText = mTickerText;
             n.tickerView = makeTickerView();
-            n.largeIcon = mLargeIcon;
+            n.mLargeIcon = mLargeIcon;
+            if (mLargeIcon != null && mLargeIcon.getType() == Icon.TYPE_BITMAP) {
+                n.largeIcon = mLargeIcon.getBitmap();
+            }
             n.sound = mSound;
             n.audioStreamType = mAudioStreamType;
             n.audioAttributes = mAudioAttributes;
@@ -3242,7 +3297,7 @@ public class Notification implements Parcelable
             extras.putCharSequence(EXTRA_TEXT, mContentText);
             extras.putCharSequence(EXTRA_SUB_TEXT, mSubText);
             extras.putCharSequence(EXTRA_INFO_TEXT, mContentInfo);
-            extras.putInt(EXTRA_SMALL_ICON, mSmallIcon);
+            extras.putParcelable(EXTRA_SMALL_ICON, mSmallIcon);
             extras.putInt(EXTRA_PROGRESS, mProgress);
             extras.putInt(EXTRA_PROGRESS_MAX, mProgressMax);
             extras.putBoolean(EXTRA_PROGRESS_INDETERMINATE, mProgressIndeterminate);
@@ -3430,7 +3485,7 @@ public class Notification implements Parcelable
 
             // Notification fields.
             mWhen = n.when;
-            mSmallIcon = n.icon;
+            mSmallIcon = n.mSmallIcon;
             mSmallIconLevel = n.iconLevel;
             mNumber = n.number;
 
@@ -3441,7 +3496,7 @@ public class Notification implements Parcelable
             mFullScreenIntent = n.fullScreenIntent;
             mTickerText = n.tickerText;
             mTickerView = n.tickerView;
-            mLargeIcon = n.largeIcon;
+            mLargeIcon = n.mLargeIcon;
             mSound = n.sound;
             mAudioStreamType = n.audioStreamType;
             mAudioAttributes = n.audioAttributes;
@@ -3472,7 +3527,7 @@ public class Notification implements Parcelable
             mContentText = extras.getCharSequence(EXTRA_TEXT);
             mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
             mContentInfo = extras.getCharSequence(EXTRA_INFO_TEXT);
-            mSmallIcon = extras.getInt(EXTRA_SMALL_ICON);
+            mSmallIcon = extras.getParcelable(EXTRA_SMALL_ICON);
             mProgress = extras.getInt(EXTRA_PROGRESS);
             mProgressMax = extras.getInt(EXTRA_PROGRESS_MAX);
             mProgressIndeterminate = extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
@@ -3764,7 +3819,7 @@ public class Notification implements Parcelable
      */
     public static class BigPictureStyle extends Style {
         private Bitmap mPicture;
-        private Bitmap mBigLargeIcon;
+        private Icon mBigLargeIcon;
         private boolean mBigLargeIconSet = false;
 
         public BigPictureStyle() {
@@ -3803,8 +3858,15 @@ public class Notification implements Parcelable
          * Override the large icon when the big notification is shown.
          */
         public BigPictureStyle bigLargeIcon(Bitmap b) {
+            return bigLargeIcon(b != null ? Icon.createWithBitmap(b) : null);
+        }
+
+        /**
+         * Override the large icon when the big notification is shown.
+         */
+        public BigPictureStyle bigLargeIcon(Icon icon) {
             mBigLargeIconSet = true;
-            mBigLargeIcon = b;
+            mBigLargeIcon = icon;
             return this;
         }
 
@@ -3815,7 +3877,7 @@ public class Notification implements Parcelable
             //   1. mBigLargeIconSet -> mBigLargeIcon (null or non-null) applies, overrides
             //          mLargeIcon
             //   2. !mBigLargeIconSet -> mLargeIcon applies
-            Bitmap oldLargeIcon = null;
+            Icon oldLargeIcon = null;
             if (mBigLargeIconSet) {
                 oldLargeIcon = mBuilder.mLargeIcon;
                 mBuilder.mLargeIcon = mBigLargeIcon;
index e0792cb..4693d4b 100644 (file)
 
 package com.android.internal.statusbar;
 
+import android.graphics.drawable.Icon;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
 
 public class StatusBarIcon implements Parcelable {
-    public String iconPackage;
     public UserHandle user;
-    public int iconId;
+    public Icon icon;
     public int iconLevel;
     public boolean visible = true;
     public int number;
     public CharSequence contentDescription;
 
-    public StatusBarIcon(String iconPackage, UserHandle user, int iconId, int iconLevel, int number,
+    public StatusBarIcon(UserHandle user, Icon icon, int iconLevel, int number,
             CharSequence contentDescription) {
-        this.iconPackage = iconPackage;
         this.user = user;
-        this.iconId = iconId;
+        this.icon = icon;
         this.iconLevel = iconLevel;
         this.number = number;
         this.contentDescription = contentDescription;
     }
 
+    public StatusBarIcon(String iconPackage, UserHandle user,
+            int iconId, int iconLevel, int number,
+            CharSequence contentDescription) {
+        this(user, Icon.createWithResource(iconPackage, iconId),
+                iconLevel, number, contentDescription);
+    }
+
     @Override
     public String toString() {
-        return "StatusBarIcon(pkg=" + this.iconPackage + "user=" + user.getIdentifier()
-                + " id=0x" + Integer.toHexString(this.iconId)
+        return "StatusBarIcon(icon=" + this.icon
+                + " user=" + user.getIdentifier()
                 + " level=" + this.iconLevel + " visible=" + visible
                 + " num=" + this.number + " )";
     }
 
     @Override
     public StatusBarIcon clone() {
-        StatusBarIcon that = new StatusBarIcon(this.iconPackage, this.user, this.iconId,
+        StatusBarIcon that = new StatusBarIcon(this.user, this.icon,
                 this.iconLevel, this.number, this.contentDescription);
         that.visible = this.visible;
         return that;
@@ -63,9 +69,8 @@ public class StatusBarIcon implements Parcelable {
     }
 
     public void readFromParcel(Parcel in) {
-        this.iconPackage = in.readString();
+        this.icon = (Icon) in.readParcelable(null);
         this.user = (UserHandle) in.readParcelable(null);
-        this.iconId = in.readInt();
         this.iconLevel = in.readInt();
         this.visible = in.readInt() != 0;
         this.number = in.readInt();
@@ -73,9 +78,8 @@ public class StatusBarIcon implements Parcelable {
     }
 
     public void writeToParcel(Parcel out, int flags) {
-        out.writeString(this.iconPackage);
+        out.writeParcelable(this.icon, 0);
         out.writeParcelable(this.user, 0);
-        out.writeInt(this.iconId);
         out.writeInt(this.iconLevel);
         out.writeInt(this.visible ? 1 : 0);
         out.writeInt(this.number);
index 3249ea3..6076973 100644 (file)
@@ -24,6 +24,7 @@ import android.graphics.Color;
 import android.graphics.drawable.AnimationDrawable;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.graphics.drawable.VectorDrawable;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
@@ -129,6 +130,20 @@ public class NotificationColorUtil {
         }
     }
 
+    public boolean isGrayscaleIcon(Context context, Icon icon) {
+        if (icon == null) {
+            return false;
+        }
+        switch (icon.getType()) {
+            case Icon.TYPE_BITMAP:
+                return isGrayscaleIcon(icon.getBitmap());
+            case Icon.TYPE_RESOURCE:
+                return isGrayscaleIcon(context, icon.getResId());
+            default:
+                return false;
+        }
+    }
+
     /**
      * Checks whether a drawable with a resoure id is a small grayscale icon.
      * Grayscale here means "very close to a perfect gray"; icon means "no larger than 64dp".
index 668a14a..37fb703 100644 (file)
@@ -53,10 +53,14 @@ import java.io.OutputStream;
 public final class Icon implements Parcelable {
     private static final String TAG = "Icon";
 
-    private static final int TYPE_BITMAP   = 1;
-    private static final int TYPE_RESOURCE = 2;
-    private static final int TYPE_DATA     = 3;
-    private static final int TYPE_URI      = 4;
+    /** @hide */
+    public static final int TYPE_BITMAP   = 1;
+    /** @hide */
+    public static final int TYPE_RESOURCE = 2;
+    /** @hide */
+    public static final int TYPE_DATA     = 3;
+    /** @hide */
+    public static final int TYPE_URI      = 4;
 
     private static final int VERSION_STREAM_SERIALIZER = 1;
 
@@ -81,15 +85,34 @@ public final class Icon implements Parcelable {
     // TYPE_DATA: data offset
     private int             mInt2;
 
-    // Internal accessors for different mType variants
-    private Bitmap getBitmap() {
+    /**
+     * @return The type of image data held in this Icon. One of
+     * {@link #TYPE_BITMAP},
+     * {@link #TYPE_RESOURCE},
+     * {@link #TYPE_DATA}, or
+     * {@link #TYPE_URI}.
+     * @hide
+     */
+    public int getType() {
+        return mType;
+    }
+
+    /**
+     * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} Icon.
+     * @hide
+     */
+    public Bitmap getBitmap() {
         if (mType != TYPE_BITMAP) {
             throw new IllegalStateException("called getBitmap() on " + this);
         }
         return (Bitmap) mObj1;
     }
 
-    private int getDataLength() {
+    /**
+     * @return The length of the compressed bitmap byte array held by this {@link #TYPE_DATA} Icon.
+     * @hide
+     */
+    public int getDataLength() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataLength() on " + this);
         }
@@ -98,7 +121,12 @@ public final class Icon implements Parcelable {
         }
     }
 
-    private int getDataOffset() {
+    /**
+     * @return The offset into the byte array held by this {@link #TYPE_DATA} Icon at which
+     * valid compressed bitmap data is found.
+     * @hide
+     */
+    public int getDataOffset() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataOffset() on " + this);
         }
@@ -107,7 +135,12 @@ public final class Icon implements Parcelable {
         }
     }
 
-    private byte[] getDataBytes() {
+    /**
+     * @return The byte array held by this {@link #TYPE_DATA} Icon ctonaining compressed
+     * bitmap data.
+     * @hide
+     */
+    public byte[] getDataBytes() {
         if (mType != TYPE_DATA) {
             throw new IllegalStateException("called getDataBytes() on " + this);
         }
@@ -116,39 +149,58 @@ public final class Icon implements Parcelable {
         }
     }
 
-    private Resources getResources() {
+    /**
+     * @return The {@link android.content.res.Resources} for this {@link #TYPE_RESOURCE} Icon.
+     * @hide
+     */
+    public Resources getResources() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResources() on " + this);
         }
         return (Resources) mObj1;
     }
 
-    private String getResPackage() {
+    /**
+     * @return The package containing resources for this {@link #TYPE_RESOURCE} Icon.
+     * @hide
+     */
+    public String getResPackage() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResPackage() on " + this);
         }
         return mString1;
     }
 
-    private int getResId() {
+    /**
+     * @return The resource ID for this {@link #TYPE_RESOURCE} Icon.
+     * @hide
+     */
+    public int getResId() {
         if (mType != TYPE_RESOURCE) {
             throw new IllegalStateException("called getResId() on " + this);
         }
         return mInt1;
     }
 
-    private String getUriString() {
+    /**
+     * @return The URI (as a String) for this {@link #TYPE_URI} Icon.
+     * @hide
+     */
+    public String getUriString() {
         if (mType != TYPE_URI) {
             throw new IllegalStateException("called getUriString() on " + this);
         }
         return mString1;
     }
 
-    private Uri getUri() {
+    /**
+     * @return The {@link android.net.Uri} for this {@link #TYPE_URI} Icon.
+     * @hide
+     */
+    public Uri getUri() {
         return Uri.parse(getUriString());
     }
 
-    // Convert a int32 into a four-char string
     private static final String typeToString(int x) {
         switch (x) {
             case TYPE_BITMAP: return "BITMAP";
index 715f4e4..be33085 100644 (file)
@@ -194,7 +194,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
         // we compose the final post-save notification below.
         mNotificationBuilder.setLargeIcon(croppedIcon);
         // But we still don't set it for the expanded view, allowing the smallIcon to show here.
-        mNotificationStyle.bigLargeIcon(null);
+        mNotificationStyle.bigLargeIcon((Bitmap) null);
     }
 
     @Override
index 2913c7d..1e488f3 100644 (file)
@@ -1390,9 +1390,9 @@ public abstract class BaseStatusBar extends SystemUI implements
             final ImageView profileBadge = (ImageView) publicViewLocal.findViewById(
                     R.id.profile_badge_line3);
 
-            final StatusBarIcon ic = new StatusBarIcon(entry.notification.getPackageName(),
+            final StatusBarIcon ic = new StatusBarIcon(
                     entry.notification.getUser(),
-                    entry.notification.getNotification().icon,
+                    entry.notification.getNotification().getSmallIcon(),
                     entry.notification.getNotification().iconLevel,
                     entry.notification.getNotification().number,
                     entry.notification.getNotification().tickerText);
@@ -1770,9 +1770,9 @@ public abstract class BaseStatusBar extends SystemUI implements
                 sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
         iconView.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
-        final StatusBarIcon ic = new StatusBarIcon(sbn.getPackageName(),
+        final StatusBarIcon ic = new StatusBarIcon(
                 sbn.getUser(),
-                    n.icon,
+                    n.getSmallIcon(),
                     n.iconLevel,
                     n.number,
                     n.tickerText);
@@ -1916,9 +1916,9 @@ public abstract class BaseStatusBar extends SystemUI implements
             try {
                 if (entry.icon != null) {
                     // Update the icon
-                    final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(),
+                    final StatusBarIcon ic = new StatusBarIcon(
                             notification.getUser(),
-                            n.icon,
+                            n.getSmallIcon(),
                             n.iconLevel,
                             n.number,
                             n.tickerText);
@@ -1938,9 +1938,9 @@ public abstract class BaseStatusBar extends SystemUI implements
         }
         if (!updateSuccessful) {
             if (DEBUG) Log.d(TAG, "not reusing notification for key: " + key);
-            final StatusBarIcon ic = new StatusBarIcon(notification.getPackageName(),
+            final StatusBarIcon ic = new StatusBarIcon(
                     notification.getUser(),
-                    n.icon,
+                    n.getSmallIcon(),
                     n.iconLevel,
                     n.number,
                     n.tickerText);
index e6847d8..3294e15 100644 (file)
@@ -24,6 +24,7 @@ import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -100,13 +101,23 @@ public class StatusBarIconView extends AnimatedImageView {
         return a.equals(b);
     }
 
+    public boolean equalIcons(Icon a, Icon b) {
+        if (a == b) return true;
+        if (a.getType() != b.getType()) return false;
+        switch (a.getType()) {
+            case Icon.TYPE_RESOURCE:
+                return a.getResPackage().equals(b.getResPackage()) && a.getResId() == b.getResId();
+            case Icon.TYPE_URI:
+                return a.getUriString().equals(b.getUriString());
+            default:
+                return false;
+        }
+    }
     /**
      * Returns whether the set succeeded.
      */
     public boolean set(StatusBarIcon icon) {
-        final boolean iconEquals = mIcon != null
-                && streq(mIcon.iconPackage, icon.iconPackage)
-                && mIcon.iconId == icon.iconId;
+        final boolean iconEquals = mIcon != null && equalIcons(mIcon.icon, icon.icon);
         final boolean levelEquals = iconEquals
                 && mIcon.iconLevel == icon.iconLevel;
         final boolean visibilityEquals = mIcon != null
@@ -167,45 +178,18 @@ public class StatusBarIconView extends AnimatedImageView {
     }
 
     /**
-     * Returns the right icon to use for this item, respecting the iconId and
-     * iconPackage (if set)
+     * Returns the right icon to use for this item
      *
-     * @param context Context to use to get resources if iconPackage is not set
+     * @param context Context to use to get resources
      * @return Drawable for this item, or null if the package or item could not
      *         be found
      */
     public static Drawable getIcon(Context context, StatusBarIcon icon) {
-        Resources r = null;
-
-        if (icon.iconPackage != null) {
-            try {
-                int userId = icon.user.getIdentifier();
-                if (userId == UserHandle.USER_ALL) {
-                    userId = UserHandle.USER_OWNER;
-                }
-                r = context.getPackageManager()
-                        .getResourcesForApplicationAsUser(icon.iconPackage, userId);
-            } catch (PackageManager.NameNotFoundException ex) {
-                Log.e(TAG, "Icon package not found: " + icon.iconPackage);
-                return null;
-            }
-        } else {
-            r = context.getResources();
+        int userId = icon.user.getIdentifier();
+        if (userId == UserHandle.USER_ALL) {
+            userId = UserHandle.USER_OWNER;
         }
-
-        if (icon.iconId == 0) {
-            return null;
-        }
-
-        try {
-            return r.getDrawable(icon.iconId);
-        } catch (RuntimeException e) {
-            Log.w(TAG, "Icon not found in "
-                  + (icon.iconPackage != null ? icon.iconId : "<system>")
-                  + ": " + Integer.toHexString(icon.iconId));
-        }
-
-        return null;
+        return icon.icon.loadDrawableAsUser(context, userId);
     }
 
     public StatusBarIcon getStatusBarIcon() {
index 44168bc..26d1c86 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.graphics.drawable.Icon;
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.view.Gravity;
@@ -132,8 +133,7 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode {
                     break;
                 } else {
                     StatusBarIcon icon = v.getStatusBarIcon();
-                    icon.iconPackage = iconPkg;
-                    icon.iconId = iconId;
+                    icon.icon = Icon.createWithResource(icon.icon.getResPackage(), iconId);
                     v.set(icon);
                     v.updateDrawable();
                     return;
@@ -152,4 +152,4 @@ public class DemoStatusIcons extends LinearLayout implements DemoMode {
         v.set(icon);
         addView(v, 0, new LinearLayout.LayoutParams(mIconSize, mIconSize));
     }
-}
\ No newline at end of file
+}
index 290fb65..de74a04 100644 (file)
@@ -2017,7 +2017,7 @@ public class NotificationManagerService extends SystemService {
             throw new IllegalArgumentException("null not allowed: pkg=" + pkg
                     + " id=" + id + " notification=" + notification);
         }
-        if (notification.icon != 0) {
+        if (notification.getSmallIcon() != null) {
             if (!notification.isValid()) {
                 throw new IllegalArgumentException("Invalid notification (): pkg=" + pkg
                         + " id=" + id + " notification=" + notification);
@@ -2138,11 +2138,11 @@ public class NotificationManagerService extends SystemService {
                     applyZenModeLocked(r);
                     mRankingHelper.sort(mNotificationList);
 
-                    if (notification.icon != 0) {
+                    if (notification.getSmallIcon() != null) {
                         StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
                         mListeners.notifyPostedLocked(n, oldSbn);
                     } else {
-                        Slog.e(TAG, "Not posting notification with icon==0: " + notification);
+                        Slog.e(TAG, "Not posting notification without small icon: " + notification);
                         if (old != null && !old.isCanceled) {
                             mListeners.notifyRemovedLocked(n);
                         }
@@ -2715,7 +2715,7 @@ public class NotificationManagerService extends SystemService {
         }
 
         // status bar
-        if (r.getNotification().icon != 0) {
+        if (r.getNotification().getSmallIcon() != null) {
             r.isCanceled = true;
             mListeners.notifyRemovedLocked(r.sbn);
         }