summaryrefslogtreecommitdiff
path: root/core/java/android/widget/RemoteViews.java
diff options
context:
space:
mode:
authorAdrian Roos <roosa@google.com>2017-10-26 14:49:56 +0200
committerAdrian Roos <roosa@google.com>2017-10-27 15:46:40 +0200
commitfb92184ebc7da516b8cb59932e1be6421879fa0a (patch)
tree80b6ec7483063e25a7b5019f71ca70ed6268a2c8 /core/java/android/widget/RemoteViews.java
parent9b874662672b4fccdcdb82c963bcc0c7028806f8 (diff)
Notification: Fix PendingIntent whitelisting
Fixes several issues with the way PendingIntents are being whitelisted from background check with Notifications. Most visibly, this causes the whitelisting not to work on Notifications that use the DecoratedContentViewStyle, but there are some conditions where the whitelisting breaks for regular notifications too. - After a Notification is rebuilt with Notification.Builder, the set of PendingIntents in the notification was not rebuilt. This broke the whitelisting whenever a PendingIntent is added after the Notification was already sent once. Workaround for broken platform releases: always use a fresh Notification object, or clone before sending. - Fixes PendingIntent.writePendingIntentOrNullToParcel to invoke the OnMarshalListener. This broke whitelisting for any PendingIntents attached to custom RemoteViews. Workaround for broken platform releases: Also attach the PendingIntent to the Notification's extras. - Changes RemoteViews to keep the parcel cookies that were present during unparceling, such that they can be reapplied when it gets cloned. This broke whitelisting for any PendingIntents attached to a DecoratedContentViewStyle *even if added to extras*. Workaround for broken platform releases: none. - Fixes Notification.whitelistToken mistakenly being static. There's an unlikely race condition where the field could be overriden with null by an incoming notification right as another notification is sent out. Workaround for broken platform releases: none. Test: runtest -x core/tests/coretests/src/android/app/NotificationTest.java && runtest -x core/tests/coretests/src/android/widget/RemoteViewsTest.java Bug: 68218899 Change-Id: I02e44040604a1d24422340611ae9e0332a611800
Diffstat (limited to 'core/java/android/widget/RemoteViews.java')
-rw-r--r--core/java/android/widget/RemoteViews.java31
1 files changed, 23 insertions, 8 deletions
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 631f3882104b..e330916130dd 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -81,6 +81,7 @@ import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.Stack;
import java.util.concurrent.Executor;
@@ -185,6 +186,9 @@ public class RemoteViews implements Parcelable, Filter {
*/
private boolean mIsWidgetCollectionChild = false;
+ /** Class cookies of the Parcel this instance was read from. */
+ private final Map<Class, Object> mClassCookies;
+
private static final OnClickHandler DEFAULT_ON_CLICK_HANDLER = new OnClickHandler();
private static final ArrayMap<MethodKey, MethodArgs> sMethods = new ArrayMap<>();
@@ -1505,10 +1509,10 @@ public class RemoteViews implements Parcelable, Filter {
}
ViewGroupActionAdd(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info,
- int depth) {
+ int depth, Map<Class, Object> classCookies) {
viewId = parcel.readInt();
mIndex = parcel.readInt();
- mNestedViews = new RemoteViews(parcel, bitmapCache, info, depth);
+ mNestedViews = new RemoteViews(parcel, bitmapCache, info, depth, classCookies);
}
public void writeToParcel(Parcel dest, int flags) {
@@ -2120,6 +2124,7 @@ public class RemoteViews implements Parcelable, Filter {
mApplication = application;
mLayoutId = layoutId;
mBitmapCache = new BitmapCache();
+ mClassCookies = null;
}
private boolean hasLandscapeAndPortraitLayouts() {
@@ -2149,6 +2154,9 @@ public class RemoteViews implements Parcelable, Filter {
mBitmapCache = new BitmapCache();
configureRemoteViewsAsChild(landscape);
configureRemoteViewsAsChild(portrait);
+
+ mClassCookies = (portrait.mClassCookies != null)
+ ? portrait.mClassCookies : landscape.mClassCookies;
}
/**
@@ -2161,15 +2169,16 @@ public class RemoteViews implements Parcelable, Filter {
mLayoutId = src.mLayoutId;
mIsWidgetCollectionChild = src.mIsWidgetCollectionChild;
mReapplyDisallowed = src.mReapplyDisallowed;
+ mClassCookies = src.mClassCookies;
if (src.hasLandscapeAndPortraitLayouts()) {
mLandscape = new RemoteViews(src.mLandscape);
mPortrait = new RemoteViews(src.mPortrait);
-
}
if (src.mActions != null) {
Parcel p = Parcel.obtain();
+ p.putClassCookies(mClassCookies);
src.writeActionsToParcel(p);
p.setDataPosition(0);
// Since src is already in memory, we do not care about stack overflow as it has
@@ -2189,10 +2198,11 @@ public class RemoteViews implements Parcelable, Filter {
* @param parcel
*/
public RemoteViews(Parcel parcel) {
- this(parcel, null, null, 0);
+ this(parcel, null, null, 0, null);
}
- private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info, int depth) {
+ private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info, int depth,
+ Map<Class, Object> classCookies) {
if (depth > MAX_NESTED_VIEWS
&& (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)) {
throw new IllegalArgumentException("Too many nested views.");
@@ -2204,8 +2214,11 @@ public class RemoteViews implements Parcelable, Filter {
// We only store a bitmap cache in the root of the RemoteViews.
if (bitmapCache == null) {
mBitmapCache = new BitmapCache(parcel);
+ // Store the class cookies such that they are available when we clone this RemoteView.
+ mClassCookies = parcel.copyClassCookies();
} else {
setBitmapCache(bitmapCache);
+ mClassCookies = classCookies;
setNotRoot();
}
@@ -2218,8 +2231,9 @@ public class RemoteViews implements Parcelable, Filter {
readActionsFromParcel(parcel, depth);
} else {
// MODE_HAS_LANDSCAPE_AND_PORTRAIT
- mLandscape = new RemoteViews(parcel, mBitmapCache, info, depth);
- mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication, depth);
+ mLandscape = new RemoteViews(parcel, mBitmapCache, info, depth, mClassCookies);
+ mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication, depth,
+ mClassCookies);
mApplication = mPortrait.mApplication;
mLayoutId = mPortrait.getLayoutId();
}
@@ -2246,7 +2260,8 @@ public class RemoteViews implements Parcelable, Filter {
case REFLECTION_ACTION_TAG:
return new ReflectionAction(parcel);
case VIEW_GROUP_ACTION_ADD_TAG:
- return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth);
+ return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth,
+ mClassCookies);
case VIEW_GROUP_ACTION_REMOVE_TAG:
return new ViewGroupActionRemove(parcel);
case VIEW_CONTENT_NAVIGATION_TAG: