From 5081c0de54d05f559dd8b09d2dd2ef5018378959 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 26 Feb 2016 16:04:19 -0800 Subject: [PATCH] Fix crash with decorated custom notifications Clones notifications before adding them to remote views so the original stays parcelable on its own. Also prevents the compatibility inflation from triggering when an app uses a decorating style to prevent recursive wrapping. Those styles only exist on N and later anyways. Also fixes the compatibility inflation in listeners. Bug: 27368615 Change-Id: Iedf3036bf315dd9c7b476c7e8bcce57de5b5c9c8 --- core/java/android/app/Notification.java | 13 ++++++++++++- .../notification/NotificationListenerService.java | 14 +++++++++++--- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index aa5e1929b8fe3..98701b59b74c8 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -3525,7 +3525,8 @@ public class Notification implements Parcelable mStyle.buildStyled(mN); } - if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { + if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N + && (mStyle == null || !mStyle.displayCustomViewInline())) { if (mN.contentView == null) { mN.contentView = createContentView(); mN.extras.putInt(EXTRA_REBUILD_CONTENT_VIEW_ACTION_COUNT, @@ -4539,6 +4540,11 @@ public class Notification implements Parcelable private void buildIntoRemoteViewContent(RemoteViews remoteViews, RemoteViews customContent) { remoteViews.removeAllViews(R.id.notification_main_column); + // Need to clone customContent before adding, because otherwise it can no longer be + // parceled independently of remoteViews. + if (customContent != null) { + customContent = customContent.clone(); + } remoteViews.addView(R.id.notification_main_column, customContent); // also update the end margin if there is an image int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize( @@ -4643,6 +4649,11 @@ public class Notification implements Parcelable private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id, RemoteViews customContent) { remoteViews.removeAllViews(id); + // Need to clone customContent before adding, because otherwise it can no longer be + // parceled independently of remoteViews. + if (customContent != null) { + customContent = customContent.clone(); + } remoteViews.addView(id, customContent); return remoteViews; } diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index d48f0c01475a4..b4332e181fc43 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -42,6 +42,7 @@ import android.os.ServiceManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; +import android.widget.RemoteViews; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -754,9 +755,16 @@ public abstract class NotificationListenerService extends Service { private void maybePopulateRemoteViews(Notification notification) { if (getContext().getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) { Builder builder = Builder.recoverBuilder(getContext(), notification); - notification.contentView = builder.createContentView(); - notification.bigContentView = builder.createBigContentView(); - notification.headsUpContentView = builder.createHeadsUpContentView(); + + // Some styles wrap Notification's contentView, bigContentView and headsUpContentView. + // First inflate them all, only then set them to avoid recursive wrapping. + RemoteViews content = builder.createContentView(); + RemoteViews big = builder.createBigContentView(); + RemoteViews headsUp = builder.createHeadsUpContentView(); + + notification.contentView = content; + notification.bigContentView = big; + notification.headsUpContentView = headsUp; } }