summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorDaniel Sandler <dsandler@android.com>2013-04-18 14:52:45 -0400
committerDaniel Sandler <dsandler@android.com>2013-04-22 15:14:55 -0400
commit1a497d3a2b1496c12949e47e55f8e46d8f585be5 (patch)
treef94fde92b7408ac80ff1a2682297e703caad94de /core/java
parent5d1a182a8a2dd9613ef3b1f2de7b6a3d690ae890 (diff)
downloadframeworks_base-1a497d3a2b1496c12949e47e55f8e46d8f585be5.zip
frameworks_base-1a497d3a2b1496c12949e47e55f8e46d8f585be5.tar.gz
frameworks_base-1a497d3a2b1496c12949e47e55f8e46d8f585be5.tar.bz2
Fix concurrency issues when parceling StatusBarNotifications.
Protip: Don't mess with Bundles after you've sent them off for parceling in an RPC. Note that this change reduces the payload size of StatusBarNotification objects received in onNotificationRemoved() callbacks; it scrubs out the RemoteViews and Bitmaps just as the NoMan's internal archive does. [You don't really need that information anyway when hearing about a removed notification; most likely all you need are the other slots on StatusBarNotification, but nulling the whole Notification object breaks a lot of clients.] Bug: 8616295 Change-Id: Ic899045f2352b96dcf064d3e9e51dad52629aea3
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/Notification.java41
-rw-r--r--core/java/android/service/notification/NotificationListenerService.java13
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java11
3 files changed, 54 insertions, 11 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8d994c4..2e328b2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -635,11 +635,16 @@ public class Notification implements Parcelable
@Override
public Notification clone() {
Notification that = new Notification();
- cloneInto(that);
+ cloneInto(that, true);
return that;
}
- private void cloneInto(Notification that) {
+ /**
+ * Copy all (or if heavy is false, all except Bitmaps and RemoteViews) members
+ * of this into that.
+ * @hide
+ */
+ public void cloneInto(Notification that, boolean heavy) {
that.when = this.when;
that.icon = this.icon;
that.number = this.number;
@@ -652,13 +657,13 @@ public class Notification implements Parcelable
if (this.tickerText != null) {
that.tickerText = this.tickerText.toString();
}
- if (this.tickerView != null) {
+ if (heavy && this.tickerView != null) {
that.tickerView = this.tickerView.clone();
}
- if (this.contentView != null) {
+ if (heavy && this.contentView != null) {
that.contentView = this.contentView.clone();
}
- if (this.largeIcon != null) {
+ if (heavy && this.largeIcon != null) {
that.largeIcon = Bitmap.createBitmap(this.largeIcon);
}
that.iconLevel = this.iconLevel;
@@ -690,7 +695,6 @@ public class Notification implements Parcelable
if (this.extras != null) {
that.extras = new Bundle(this.extras);
-
}
if (this.actions != null) {
@@ -700,9 +704,30 @@ public class Notification implements Parcelable
}
}
- if (this.bigContentView != null) {
+ if (heavy && this.bigContentView != null) {
that.bigContentView = this.bigContentView.clone();
}
+
+ if (!heavy) {
+ that.lightenPayload(); // will clean out extras
+ }
+ }
+
+ /**
+ * Removes heavyweight parts of the Notification object for archival or for sending to
+ * listeners when the full contents are not necessary.
+ * @hide
+ */
+ public final void lightenPayload() {
+ tickerView = null;
+ contentView = null;
+ bigContentView = null;
+ largeIcon = null;
+ if (extras != null) {
+ extras.remove(Notification.EXTRA_LARGE_ICON);
+ extras.remove(Notification.EXTRA_LARGE_ICON_BIG);
+ extras.remove(Notification.EXTRA_PICTURE);
+ }
}
public int describeContents() {
@@ -1706,7 +1731,7 @@ public class Notification implements Parcelable
* @hide
*/
public Notification buildInto(Notification n) {
- build().cloneInto(n);
+ build().cloneInto(n, true);
return n;
}
}
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 86bab2a..8b72ca9 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -55,10 +55,17 @@ public abstract class NotificationListenerService extends Service {
* <P>
* This might occur because the user has dismissed the notification using system UI (or another
* notification listener) or because the app has withdrawn the notification.
+ * <P>
+ * NOTE: The {@link StatusBarNotification} object you receive will be "light"; that is, the
+ * {@link StatusBarNotification#notification} member may be missing some heavyweight
+ * fields such as {@link android.app.Notification#contentView} and
+ * {@link android.app.Notification#largeIcon}. However, all other fields on
+ * {@link StatusBarNotification}, sufficient to match this call with a prior call to
+ * {@link #onNotificationPosted(StatusBarNotification)}, will be intact.
*
- * @param sbn A data structure encapsulating the original {@link android.app.Notification}
- * object as well as its identifying information (tag and id) and source
- * (package name).
+ * @param sbn A data structure encapsulating at least the original information (tag and id)
+ * and source (package name) used to post the {@link android.app.Notification} that
+ * was just removed.
*/
public abstract void onNotificationRemoved(StatusBarNotification sbn);
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index ef5f8c4..006518c 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -152,6 +152,17 @@ public class StatusBarNotification implements Parcelable {
}
};
+ /**
+ * @hide
+ */
+ public StatusBarNotification cloneLight() {
+ final Notification no = new Notification();
+ this.notification.cloneInto(no, false); // light copy
+ return new StatusBarNotification(this.pkg, this.basePkg,
+ this.id, this.tag, this.uid, this.initialPid,
+ this.score, no, this.user, this.postTime);
+ }
+
@Override
public StatusBarNotification clone() {
return new StatusBarNotification(this.pkg, this.basePkg,