diff options
| author | 2018-04-18 21:32:12 -0600 | |
|---|---|---|
| committer | 2018-04-18 21:40:47 -0600 | |
| commit | 23b3118f288d2beff0519ca294baac8093995989 (patch) | |
| tree | 80cabef85b9c9e3632e1f01fe3cf6514963cf83a | |
| parent | 56487413b75e09100d9aabb9a8c1cf83b39ef34c (diff) | |
Visit Uris in RemoteViews for granting purposes.
RemoteViews end up passing around Uris, so we need to extend Uri
permission grants for them to ensure the recipient of a Notification
object is able to render its contents.
Bug: 9069730
Test: atest frameworks/base/services/tests/uiservicestests/src/com/android/server/notification
Change-Id: Id31b5adaf2ee66113a1b503e32126aeddbf97b28
| -rw-r--r-- | core/java/android/app/Notification.java | 40 | ||||
| -rw-r--r-- | core/java/android/widget/RemoteViews.java | 50 | ||||
| -rw-r--r-- | services/core/java/com/android/server/notification/NotificationRecord.java | 40 |
3 files changed, 95 insertions, 35 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 22da924d1b8f..4f88a03db435 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -91,6 +91,7 @@ import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.function.Consumer; /** * A class that represents how a persistent notification is to be presented to @@ -2306,6 +2307,45 @@ public class Notification implements Parcelable } /** + * Note all {@link Uri} that are referenced internally, with the expectation + * that Uri permission grants will need to be issued to ensure the recipient + * of this object is able to render its contents. + * + * @hide + */ + public void visitUris(@NonNull Consumer<Uri> visitor) { + visitor.accept(sound); + + if (tickerView != null) tickerView.visitUris(visitor); + if (contentView != null) contentView.visitUris(visitor); + if (bigContentView != null) bigContentView.visitUris(visitor); + if (headsUpContentView != null) headsUpContentView.visitUris(visitor); + + if (extras != null) { + visitor.accept(extras.getParcelable(EXTRA_AUDIO_CONTENTS_URI)); + visitor.accept(extras.getParcelable(EXTRA_BACKGROUND_IMAGE_URI)); + } + + if (MessagingStyle.class.equals(getNotificationStyle()) && extras != null) { + final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); + if (!ArrayUtils.isEmpty(messages)) { + for (MessagingStyle.Message message : MessagingStyle.Message + .getMessagesFromBundleArray(messages)) { + visitor.accept(message.getDataUri()); + } + } + + final Parcelable[] historic = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES); + if (!ArrayUtils.isEmpty(historic)) { + for (MessagingStyle.Message message : MessagingStyle.Message + .getMessagesFromBundleArray(historic)) { + visitor.accept(message.getDataUri()); + } + } + } + } + + /** * Removes heavyweight parts of the Notification object for archival or for sending to * listeners when the full contents are not necessary. * @hide diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index a34bd093e655..b6bd14ed5efd 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -83,6 +83,7 @@ import java.util.Map; import java.util.Objects; import java.util.Stack; import java.util.concurrent.Executor; +import java.util.function.Consumer; /** * A class that describes a view hierarchy that can be displayed in @@ -444,6 +445,10 @@ public class RemoteViews implements Parcelable, Filter { return true; } + public void visitUris(@NonNull Consumer<Uri> visitor) { + // Nothing to visit by default + } + int viewId; } @@ -517,6 +522,27 @@ public class RemoteViews implements Parcelable, Filter { setBitmapCache(mBitmapCache); } + /** + * Note all {@link Uri} that are referenced internally, with the expectation + * that Uri permission grants will need to be issued to ensure the recipient + * of this object is able to render its contents. + * + * @hide + */ + public void visitUris(@NonNull Consumer<Uri> visitor) { + if (mActions != null) { + for (int i = 0; i < mActions.size(); i++) { + mActions.get(i).visitUris(visitor); + } + } + } + + private static void visitIconUri(Icon icon, @NonNull Consumer<Uri> visitor) { + if (icon != null && icon.getType() == Icon.TYPE_URI) { + visitor.accept(icon.getUri()); + } + } + private static class RemoteViewsContextWrapper extends ContextWrapper { private final Context mContextForResources; @@ -1485,6 +1511,20 @@ public class RemoteViews implements Parcelable, Filter { public boolean prefersAsyncApply() { return this.type == URI || this.type == ICON; } + + @Override + public void visitUris(@NonNull Consumer<Uri> visitor) { + switch (this.type) { + case URI: + final Uri uri = (Uri) this.value; + visitor.accept(uri); + break; + case ICON: + final Icon icon = (Icon) this.value; + visitIconUri(icon, visitor); + break; + } + } } /** @@ -1849,6 +1889,16 @@ public class RemoteViews implements Parcelable, Filter { return TEXT_VIEW_DRAWABLE_ACTION_TAG; } + @Override + public void visitUris(@NonNull Consumer<Uri> visitor) { + if (useIcons) { + visitIconUri(i1, visitor); + visitIconUri(i2, visitor); + visitIconUri(i3, visitor); + visitIconUri(i4, visitor); + } + } + boolean isRelative = false; boolean useIcons = false; int d1, d2, d3, d4; diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 72a1a71b8959..2aec3eaf757c 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -15,10 +15,6 @@ */ package com.android.server.notification; -import static android.app.Notification.EXTRA_AUDIO_CONTENTS_URI; -import static android.app.Notification.EXTRA_BACKGROUND_IMAGE_URI; -import static android.app.Notification.EXTRA_HISTORIC_MESSAGES; -import static android.app.Notification.EXTRA_MESSAGES; import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.IMPORTANCE_HIGH; @@ -32,10 +28,8 @@ import static android.service.notification.NotificationListenerService.Ranking import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.ActivityManagerInternal; import android.app.IActivityManager; import android.app.Notification; -import android.app.Notification.MessagingStyle; import android.app.NotificationChannel; import android.content.ContentProvider; import android.content.ContentResolver; @@ -55,7 +49,6 @@ import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; -import android.os.Parcelable; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; @@ -75,7 +68,6 @@ import android.widget.RemoteViews; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; -import com.android.internal.util.ArrayUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; @@ -1029,36 +1021,14 @@ public final class NotificationRecord { */ private void calculateGrantableUris() { final Notification notification = getNotification(); + notification.visitUris((uri) -> { + visitGrantableUri(uri); + }); - noteGrantableUri(notification.sound); if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null) { - noteGrantableUri(channel.getSound()); - } - } - - final Bundle extras = notification.extras; - if (extras != null) { - noteGrantableUri(extras.getParcelable(EXTRA_AUDIO_CONTENTS_URI)); - noteGrantableUri(extras.getParcelable(EXTRA_BACKGROUND_IMAGE_URI)); - } - - if (MessagingStyle.class.equals(notification.getNotificationStyle()) && extras != null) { - final Parcelable[] messages = extras.getParcelableArray(EXTRA_MESSAGES); - if (!ArrayUtils.isEmpty(messages)) { - for (MessagingStyle.Message message : MessagingStyle.Message - .getMessagesFromBundleArray(messages)) { - noteGrantableUri(message.getDataUri()); - } - } - - final Parcelable[] historic = extras.getParcelableArray(EXTRA_HISTORIC_MESSAGES); - if (!ArrayUtils.isEmpty(historic)) { - for (MessagingStyle.Message message : MessagingStyle.Message - .getMessagesFromBundleArray(historic)) { - noteGrantableUri(message.getDataUri()); - } + visitGrantableUri(channel.getSound()); } } } @@ -1071,7 +1041,7 @@ public final class NotificationRecord { * {@link #mGrantableUris}. Otherwise, this will either log or throw * {@link SecurityException} depending on target SDK of enqueuing app. */ - private void noteGrantableUri(Uri uri) { + private void visitGrantableUri(Uri uri) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; // We can't grant Uri permissions from system |