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
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index aa5e192..98701b5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -3525,7 +3525,8 @@
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 @@
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 @@
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 d48f0c0..b4332e1 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -42,6 +42,7 @@
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 @@
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;
}
}