Loading core/java/android/app/Notification.java +3 −4 Original line number Diff line number Diff line Loading @@ -1055,11 +1055,10 @@ public class Notification implements Parcelable /** * {@link #extras} key: A * {@link android.content.ContentUris content URI} pointing to an image that can be displayed * in the background when the notification is selected. The URI must point to an image stream * suitable for passing into * in the background when the notification is selected. Used on television platforms. * The URI must point to an image stream suitable for passing into * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream) * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider * URI used for this purpose must require no permissions to read the image data. * BitmapFactory.decodeStream}; all other content types will be ignored. */ public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; Loading core/java/android/app/NotificationManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.graphics.drawable.Icon; import android.net.Uri; Loading Loading @@ -350,6 +351,14 @@ public class NotificationManager { * the same tag and id has already been posted by your application and has not yet been * canceled, it will be replaced by the updated information. * * All {@link android.service.notification.NotificationListenerService listener services} will * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris} * provided on this notification or the * {@link NotificationChannel} this notification is posted to using * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the * notification is canceled, or you can revoke permissions with * {@link Context#revokeUriPermission(Uri, int)}. * * @param tag A string identifier for this notification. May be {@code null}. * @param id An identifier for this notification. The pair (tag, id) must be unique * within your application. Loading @@ -370,11 +379,13 @@ public class NotificationManager { String pkg = mContext.getPackageName(); // Fix the notification as best we can. Notification.addFieldsFromContext(mContext, notification); if (notification.sound != null) { notification.sound = notification.sound.getCanonicalUri(); if (StrictMode.vmFileUriExposureEnabled()) { notification.sound.checkFileUriExposed("Notification.sound"); } } fixLegacySmallIcon(notification, pkg); if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { Loading @@ -385,6 +396,7 @@ public class NotificationManager { } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); notification.reduceImageSizes(mContext); ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); boolean isLowRam = am.isLowRamDevice(); final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam); Loading services/core/java/com/android/server/notification/ManagedServices.java +4 −4 Original line number Diff line number Diff line Loading @@ -376,9 +376,7 @@ abstract public class ManagedServices { protected void upgradeXml(final int xmlVersion, final int userId) {} private void loadAllowedComponentsFromSettings() { UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); for (UserInfo user : userManager.getUsers()) { for (UserInfo user : mUm.getUsers()) { final ContentResolver cr = mContext.getContentResolver(); addApprovedList(Settings.Secure.getStringForUser( cr, Loading Loading @@ -482,7 +480,9 @@ abstract public class ManagedServices { for (int i = 0; i < allowedByType.size(); i++) { final ArraySet<String> allowed = allowedByType.valueAt(i); allowedPackages.addAll( allowed.stream().map(this::getPackageName).collect(Collectors.toList())); allowed.stream().map(this::getPackageName). filter(value -> !TextUtils.isEmpty(value)) .collect(Collectors.toList())); } return allowedPackages; } Loading services/core/java/com/android/server/notification/NotificationManagerService.java +81 −12 Original line number Diff line number Diff line Loading @@ -25,7 +25,9 @@ import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.notification.NotificationListenerService .HINT_HOST_DISABLE_CALL_EFFECTS; import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS; Loading Loading @@ -88,6 +90,7 @@ import android.app.usage.UsageStatsManagerInternal; import android.companion.ICompanionDeviceManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading Loading @@ -115,6 +118,7 @@ import android.os.IDeviceIdleController; import android.os.IInterface; import android.os.Looper; import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; Loading Loading @@ -206,6 +210,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; Loading Loading @@ -288,6 +293,7 @@ public class NotificationManagerService extends SystemService { private ICompanionDeviceManager mCompanionManager; private AccessibilityManager mAccessibilityManager; private IDeviceIdleController mDeviceIdleController; private IBinder mPermissionOwner; final IBinder mForegroundToken = new Binder(); private WorkerHandler mHandler; Loading Loading @@ -524,7 +530,7 @@ public class NotificationManagerService extends SystemService { } catch (FileNotFoundException e) { // No data yet // Load default managed services approvals readDefaultApprovedServices(UserHandle.USER_SYSTEM); readDefaultApprovedServices(USER_SYSTEM); } catch (IOException e) { Log.wtf(TAG, "Unable to read notification policy", e); } catch (NumberFormatException e) { Loading Loading @@ -974,7 +980,7 @@ public class NotificationManagerService extends SystemService { final int enabled = mPackageManager.getApplicationEnabledSetting( pkgName, changeUserId != UserHandle.USER_ALL ? changeUserId : UserHandle.USER_SYSTEM); USER_SYSTEM); if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { cancelNotifications = false; Loading Loading @@ -1061,6 +1067,7 @@ public class NotificationManagerService extends SystemService { } } else if (action.equals(Intent.ACTION_USER_REMOVED)) { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); mUserProfiles.updateCache(context); mZenModeHelper.onUserRemoved(user); mRankingHelper.onUserRemoved(user); mListeners.onUserRemoved(user); Loading Loading @@ -1268,7 +1275,7 @@ public class NotificationManagerService extends SystemService { NotificationAssistants notificationAssistants, ConditionProviders conditionProviders, ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper, NotificationUsageStats usageStats, AtomicFile policyFile, ActivityManager activityManager, GroupHelper groupHelper) { ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am) { Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, Loading @@ -1276,7 +1283,7 @@ public class NotificationManagerService extends SystemService { mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mAm = ActivityManager.getService(); mAm = am; mPackageManager = packageManager; mPackageManagerClient = packageManagerClient; mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); Loading @@ -1287,6 +1294,11 @@ public class NotificationManagerService extends SystemService { mActivityManager = activityManager; mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); try { mPermissionOwner = mAm.newUriPermissionOwner("notification"); } catch (RemoteException e) { Slog.w(TAG, "AM dead", e); } mHandler = new WorkerHandler(looper); mRankingThread.start(); Loading Loading @@ -1415,7 +1427,7 @@ public class NotificationManagerService extends SystemService { null, snoozeHelper, new NotificationUsageStats(getContext()), new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"), (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE), getGroupHelper()); getGroupHelper(), ActivityManager.getService()); // register for various Intents IntentFilter filter = new IntentFilter(); Loading Loading @@ -1749,7 +1761,7 @@ public class NotificationManagerService extends SystemService { protected void reportSeen(NotificationRecord r) { final int userId = r.sbn.getUserId(); mAppUsageStats.reportEvent(r.sbn.getPackageName(), userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM userId == UserHandle.USER_ALL ? USER_SYSTEM : userId, UsageEvents.Event.NOTIFICATION_SEEN); } Loading Loading @@ -2894,7 +2906,7 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); if (DBG) Slog.d(TAG, "getBackupPayload u=" + user); //TODO: http://b/22388012 if (user != UserHandle.USER_SYSTEM) { if (user != USER_SYSTEM) { Slog.w(TAG, "getBackupPayload: cannot backup policy for user " + user); return null; } Loading @@ -2920,7 +2932,7 @@ public class NotificationManagerService extends SystemService { return; } //TODO: http://b/22388012 if (user != UserHandle.USER_SYSTEM) { if (user != USER_SYSTEM) { Slog.w(TAG, "applyRestore: cannot restore policy for user " + user); return; } Loading Loading @@ -3678,7 +3690,7 @@ public class NotificationManagerService extends SystemService { sbn.getNotification().flags = (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE); mRankingHelper.sort(mNotificationList); mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */); mListeners.notifyPostedLocked(r, sbn /* oldSbn */); } }; Loading Loading @@ -3707,7 +3719,7 @@ public class NotificationManagerService extends SystemService { try { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId); (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Notification.addFieldsFromContext(ai, notification); int canColorize = mPackageManagerClient.checkPermission( Loading Loading @@ -4126,6 +4138,8 @@ public class NotificationManagerService extends SystemService { // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; // revoke uri permissions for changed uris revokeUriPermissions(r, old); r.isUpdate = true; } Loading @@ -4147,7 +4161,7 @@ public class NotificationManagerService extends SystemService { if (notification.getSmallIcon() != null) { StatusBarNotification oldSbn = (old != null) ? old.sbn : null; mListeners.notifyPostedLocked(n, oldSbn); mListeners.notifyPostedLocked(r, oldSbn); if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) { mHandler.post(new Runnable() { @Override Loading Loading @@ -4912,6 +4926,9 @@ public class NotificationManagerService extends SystemService { r.recordDismissalSurface(NotificationStats.DISMISSAL_OTHER); } // Revoke permissions revokeUriPermissions(null, r); // tell the app if (sendDelete) { if (r.getNotification().deleteIntent != null) { Loading Loading @@ -5009,6 +5026,30 @@ public class NotificationManagerService extends SystemService { r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now), listenerName); } void revokeUriPermissions(NotificationRecord newRecord, NotificationRecord oldRecord) { Set<Uri> oldUris = oldRecord.getNotificationUris(); Set<Uri> newUris = newRecord == null ? new HashSet<>() : newRecord.getNotificationUris(); oldUris.removeAll(newUris); long ident = Binder.clearCallingIdentity(); try { for (Uri uri : oldUris) { if (uri != null) { int notiUserId = oldRecord.getUserId(); int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM : ContentProvider.getUserIdFromUri(uri, notiUserId); uri = ContentProvider.getUriWithoutUserId(uri); mAm.revokeUriPermissionFromOwner(mPermissionOwner, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId); } } } catch (RemoteException e) { Log.e(TAG, "Count not revoke uri permissions", e); } finally { Binder.restoreCallingIdentity(ident); } } /** * Cancels a notification ONLY if it has all of the {@code mustHaveFlags} * and none of the {@code mustNotHaveFlags}. Loading Loading @@ -5851,10 +5892,13 @@ public class NotificationManagerService extends SystemService { * but isn't anymore. */ @GuardedBy("mNotificationLock") public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) { public void notifyPostedLocked(NotificationRecord r, StatusBarNotification oldSbn) { // Lazily initialized snapshots of the notification. StatusBarNotification sbn = r.sbn; TrimCache trimCache = new TrimCache(sbn); Set<Uri> uris = r.getNotificationUris(); for (final ManagedServiceInfo info : getServices()) { boolean sbnVisible = isVisibleToListener(sbn, info); boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false; Loading @@ -5877,6 +5921,9 @@ public class NotificationManagerService extends SystemService { continue; } grantUriPermissions(uris, sbn.getUserId(), info.component.getPackageName(), info.userid); final StatusBarNotification sbnToPost = trimCache.ForListener(info); mHandler.post(new Runnable() { @Override Loading @@ -5887,6 +5934,28 @@ public class NotificationManagerService extends SystemService { } } private void grantUriPermissions(Set<Uri> uris, int notiUserId, String listenerPkg, int listenerUserId) { long ident = Binder.clearCallingIdentity(); try { for (Uri uri : uris) { if (uri != null) { int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM : ContentProvider.getUserIdFromUri(uri, notiUserId); uri = ContentProvider.getUriWithoutUserId(uri); mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), listenerPkg, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, listenerUserId == USER_ALL ? USER_SYSTEM : listenerUserId); } } } catch (RemoteException e) { Log.e(TAG, "Count not grant uri permission to " + listenerPkg, e); } finally { Binder.restoreCallingIdentity(ident); } } /** * asynchronously notify all listeners about a removed notification */ Loading services/core/java/com/android/server/notification/NotificationRecord.java +39 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.Adjustment; Loading @@ -47,6 +48,7 @@ import android.service.notification.NotificationStats; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.TimeUtils; Loading @@ -64,6 +66,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; /** * Holds data about notifications that should not be shared with the Loading Loading @@ -929,6 +932,42 @@ public final class NotificationRecord { mStats.setViewedSettings(); } public Set<Uri> getNotificationUris() { Notification notification = getNotification(); Set<Uri> uris = new ArraySet<>(); if (notification.sound != null) { uris.add(notification.sound); } if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null && channel.getSound() != null) { uris.add(channel.getSound()); } } if (notification.extras.containsKey(Notification.EXTRA_AUDIO_CONTENTS_URI)) { uris.add(notification.extras.getParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI)); } if (notification.extras.containsKey(Notification.EXTRA_BACKGROUND_IMAGE_URI)) { uris.add(notification.extras.getParcelable(Notification.EXTRA_BACKGROUND_IMAGE_URI)); } if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) { Parcelable[] newMessages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES); List<Notification.MessagingStyle.Message> messages = Notification.MessagingStyle.Message.getMessagesFromBundleArray(newMessages); Parcelable[] histMessages = notification.extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES); messages.addAll( Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages)); for (Notification.MessagingStyle.Message message : messages) { uris.add(message.getDataUri()); } } return uris; } public LogMaker getLogMaker(long now) { if (mLogMaker == null) { // initialize fields that only change on update (so a new record) Loading Loading
core/java/android/app/Notification.java +3 −4 Original line number Diff line number Diff line Loading @@ -1055,11 +1055,10 @@ public class Notification implements Parcelable /** * {@link #extras} key: A * {@link android.content.ContentUris content URI} pointing to an image that can be displayed * in the background when the notification is selected. The URI must point to an image stream * suitable for passing into * in the background when the notification is selected. Used on television platforms. * The URI must point to an image stream suitable for passing into * {@link android.graphics.BitmapFactory#decodeStream(java.io.InputStream) * BitmapFactory.decodeStream}; all other content types will be ignored. The content provider * URI used for this purpose must require no permissions to read the image data. * BitmapFactory.decodeStream}; all other content types will be ignored. */ public static final String EXTRA_BACKGROUND_IMAGE_URI = "android.backgroundImageUri"; Loading
core/java/android/app/NotificationManager.java +12 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.annotation.TestApi; import android.app.Notification.Builder; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ParceledListSlice; import android.graphics.drawable.Icon; import android.net.Uri; Loading Loading @@ -350,6 +351,14 @@ public class NotificationManager { * the same tag and id has already been posted by your application and has not yet been * canceled, it will be replaced by the updated information. * * All {@link android.service.notification.NotificationListenerService listener services} will * be granted {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} access to any {@link Uri uris} * provided on this notification or the * {@link NotificationChannel} this notification is posted to using * {@link Context#grantUriPermission(String, Uri, int)}. Permission will be revoked when the * notification is canceled, or you can revoke permissions with * {@link Context#revokeUriPermission(Uri, int)}. * * @param tag A string identifier for this notification. May be {@code null}. * @param id An identifier for this notification. The pair (tag, id) must be unique * within your application. Loading @@ -370,11 +379,13 @@ public class NotificationManager { String pkg = mContext.getPackageName(); // Fix the notification as best we can. Notification.addFieldsFromContext(mContext, notification); if (notification.sound != null) { notification.sound = notification.sound.getCanonicalUri(); if (StrictMode.vmFileUriExposureEnabled()) { notification.sound.checkFileUriExposed("Notification.sound"); } } fixLegacySmallIcon(notification, pkg); if (mContext.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { Loading @@ -385,6 +396,7 @@ public class NotificationManager { } if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")"); notification.reduceImageSizes(mContext); ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); boolean isLowRam = am.isLowRamDevice(); final Notification copy = Builder.maybeCloneStrippedForDelivery(notification, isLowRam); Loading
services/core/java/com/android/server/notification/ManagedServices.java +4 −4 Original line number Diff line number Diff line Loading @@ -376,9 +376,7 @@ abstract public class ManagedServices { protected void upgradeXml(final int xmlVersion, final int userId) {} private void loadAllowedComponentsFromSettings() { UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); for (UserInfo user : userManager.getUsers()) { for (UserInfo user : mUm.getUsers()) { final ContentResolver cr = mContext.getContentResolver(); addApprovedList(Settings.Secure.getStringForUser( cr, Loading Loading @@ -482,7 +480,9 @@ abstract public class ManagedServices { for (int i = 0; i < allowedByType.size(); i++) { final ArraySet<String> allowed = allowedByType.valueAt(i); allowedPackages.addAll( allowed.stream().map(this::getPackageName).collect(Collectors.toList())); allowed.stream().map(this::getPackageName). filter(value -> !TextUtils.isEmpty(value)) .collect(Collectors.toList())); } return allowedPackages; } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +81 −12 Original line number Diff line number Diff line Loading @@ -25,7 +25,9 @@ import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_NULL; import static android.os.UserHandle.USER_SYSTEM; import static android.service.notification.NotificationListenerService .HINT_HOST_DISABLE_CALL_EFFECTS; import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS; Loading Loading @@ -88,6 +90,7 @@ import android.app.usage.UsageStatsManagerInternal; import android.companion.ICompanionDeviceManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; Loading Loading @@ -115,6 +118,7 @@ import android.os.IDeviceIdleController; import android.os.IInterface; import android.os.Looper; import android.os.Message; import android.os.Parcelable; import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; Loading Loading @@ -206,6 +210,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map.Entry; Loading Loading @@ -288,6 +293,7 @@ public class NotificationManagerService extends SystemService { private ICompanionDeviceManager mCompanionManager; private AccessibilityManager mAccessibilityManager; private IDeviceIdleController mDeviceIdleController; private IBinder mPermissionOwner; final IBinder mForegroundToken = new Binder(); private WorkerHandler mHandler; Loading Loading @@ -524,7 +530,7 @@ public class NotificationManagerService extends SystemService { } catch (FileNotFoundException e) { // No data yet // Load default managed services approvals readDefaultApprovedServices(UserHandle.USER_SYSTEM); readDefaultApprovedServices(USER_SYSTEM); } catch (IOException e) { Log.wtf(TAG, "Unable to read notification policy", e); } catch (NumberFormatException e) { Loading Loading @@ -974,7 +980,7 @@ public class NotificationManagerService extends SystemService { final int enabled = mPackageManager.getApplicationEnabledSetting( pkgName, changeUserId != UserHandle.USER_ALL ? changeUserId : UserHandle.USER_SYSTEM); USER_SYSTEM); if (enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED || enabled == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { cancelNotifications = false; Loading Loading @@ -1061,6 +1067,7 @@ public class NotificationManagerService extends SystemService { } } else if (action.equals(Intent.ACTION_USER_REMOVED)) { final int user = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); mUserProfiles.updateCache(context); mZenModeHelper.onUserRemoved(user); mRankingHelper.onUserRemoved(user); mListeners.onUserRemoved(user); Loading Loading @@ -1268,7 +1275,7 @@ public class NotificationManagerService extends SystemService { NotificationAssistants notificationAssistants, ConditionProviders conditionProviders, ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper, NotificationUsageStats usageStats, AtomicFile policyFile, ActivityManager activityManager, GroupHelper groupHelper) { ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am) { Resources resources = getContext().getResources(); mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(), Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE, Loading @@ -1276,7 +1283,7 @@ public class NotificationManagerService extends SystemService { mAccessibilityManager = (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); mAm = ActivityManager.getService(); mAm = am; mPackageManager = packageManager; mPackageManagerClient = packageManagerClient; mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE); Loading @@ -1287,6 +1294,11 @@ public class NotificationManagerService extends SystemService { mActivityManager = activityManager; mDeviceIdleController = IDeviceIdleController.Stub.asInterface( ServiceManager.getService(Context.DEVICE_IDLE_CONTROLLER)); try { mPermissionOwner = mAm.newUriPermissionOwner("notification"); } catch (RemoteException e) { Slog.w(TAG, "AM dead", e); } mHandler = new WorkerHandler(looper); mRankingThread.start(); Loading Loading @@ -1415,7 +1427,7 @@ public class NotificationManagerService extends SystemService { null, snoozeHelper, new NotificationUsageStats(getContext()), new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"), (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE), getGroupHelper()); getGroupHelper(), ActivityManager.getService()); // register for various Intents IntentFilter filter = new IntentFilter(); Loading Loading @@ -1749,7 +1761,7 @@ public class NotificationManagerService extends SystemService { protected void reportSeen(NotificationRecord r) { final int userId = r.sbn.getUserId(); mAppUsageStats.reportEvent(r.sbn.getPackageName(), userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM userId == UserHandle.USER_ALL ? USER_SYSTEM : userId, UsageEvents.Event.NOTIFICATION_SEEN); } Loading Loading @@ -2894,7 +2906,7 @@ public class NotificationManagerService extends SystemService { checkCallerIsSystem(); if (DBG) Slog.d(TAG, "getBackupPayload u=" + user); //TODO: http://b/22388012 if (user != UserHandle.USER_SYSTEM) { if (user != USER_SYSTEM) { Slog.w(TAG, "getBackupPayload: cannot backup policy for user " + user); return null; } Loading @@ -2920,7 +2932,7 @@ public class NotificationManagerService extends SystemService { return; } //TODO: http://b/22388012 if (user != UserHandle.USER_SYSTEM) { if (user != USER_SYSTEM) { Slog.w(TAG, "applyRestore: cannot restore policy for user " + user); return; } Loading Loading @@ -3678,7 +3690,7 @@ public class NotificationManagerService extends SystemService { sbn.getNotification().flags = (r.mOriginalFlags & ~Notification.FLAG_FOREGROUND_SERVICE); mRankingHelper.sort(mNotificationList); mListeners.notifyPostedLocked(sbn, sbn /* oldSbn */); mListeners.notifyPostedLocked(r, sbn /* oldSbn */); } }; Loading Loading @@ -3707,7 +3719,7 @@ public class NotificationManagerService extends SystemService { try { final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser( pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, (userId == UserHandle.USER_ALL) ? UserHandle.USER_SYSTEM : userId); (userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId); Notification.addFieldsFromContext(ai, notification); int canColorize = mPackageManagerClient.checkPermission( Loading Loading @@ -4126,6 +4138,8 @@ public class NotificationManagerService extends SystemService { // Make sure we don't lose the foreground service state. notification.flags |= old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE; // revoke uri permissions for changed uris revokeUriPermissions(r, old); r.isUpdate = true; } Loading @@ -4147,7 +4161,7 @@ public class NotificationManagerService extends SystemService { if (notification.getSmallIcon() != null) { StatusBarNotification oldSbn = (old != null) ? old.sbn : null; mListeners.notifyPostedLocked(n, oldSbn); mListeners.notifyPostedLocked(r, oldSbn); if (oldSbn == null || !Objects.equals(oldSbn.getGroup(), n.getGroup())) { mHandler.post(new Runnable() { @Override Loading Loading @@ -4912,6 +4926,9 @@ public class NotificationManagerService extends SystemService { r.recordDismissalSurface(NotificationStats.DISMISSAL_OTHER); } // Revoke permissions revokeUriPermissions(null, r); // tell the app if (sendDelete) { if (r.getNotification().deleteIntent != null) { Loading Loading @@ -5009,6 +5026,30 @@ public class NotificationManagerService extends SystemService { r.getLifespanMs(now), r.getFreshnessMs(now), r.getExposureMs(now), listenerName); } void revokeUriPermissions(NotificationRecord newRecord, NotificationRecord oldRecord) { Set<Uri> oldUris = oldRecord.getNotificationUris(); Set<Uri> newUris = newRecord == null ? new HashSet<>() : newRecord.getNotificationUris(); oldUris.removeAll(newUris); long ident = Binder.clearCallingIdentity(); try { for (Uri uri : oldUris) { if (uri != null) { int notiUserId = oldRecord.getUserId(); int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM : ContentProvider.getUserIdFromUri(uri, notiUserId); uri = ContentProvider.getUriWithoutUserId(uri); mAm.revokeUriPermissionFromOwner(mPermissionOwner, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId); } } } catch (RemoteException e) { Log.e(TAG, "Count not revoke uri permissions", e); } finally { Binder.restoreCallingIdentity(ident); } } /** * Cancels a notification ONLY if it has all of the {@code mustHaveFlags} * and none of the {@code mustNotHaveFlags}. Loading Loading @@ -5851,10 +5892,13 @@ public class NotificationManagerService extends SystemService { * but isn't anymore. */ @GuardedBy("mNotificationLock") public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) { public void notifyPostedLocked(NotificationRecord r, StatusBarNotification oldSbn) { // Lazily initialized snapshots of the notification. StatusBarNotification sbn = r.sbn; TrimCache trimCache = new TrimCache(sbn); Set<Uri> uris = r.getNotificationUris(); for (final ManagedServiceInfo info : getServices()) { boolean sbnVisible = isVisibleToListener(sbn, info); boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info) : false; Loading @@ -5877,6 +5921,9 @@ public class NotificationManagerService extends SystemService { continue; } grantUriPermissions(uris, sbn.getUserId(), info.component.getPackageName(), info.userid); final StatusBarNotification sbnToPost = trimCache.ForListener(info); mHandler.post(new Runnable() { @Override Loading @@ -5887,6 +5934,28 @@ public class NotificationManagerService extends SystemService { } } private void grantUriPermissions(Set<Uri> uris, int notiUserId, String listenerPkg, int listenerUserId) { long ident = Binder.clearCallingIdentity(); try { for (Uri uri : uris) { if (uri != null) { int sourceUserId = notiUserId == USER_ALL ? USER_SYSTEM : ContentProvider.getUserIdFromUri(uri, notiUserId); uri = ContentProvider.getUriWithoutUserId(uri); mAm.grantUriPermissionFromOwner(mPermissionOwner, Process.myUid(), listenerPkg, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, sourceUserId, listenerUserId == USER_ALL ? USER_SYSTEM : listenerUserId); } } } catch (RemoteException e) { Log.e(TAG, "Count not grant uri permission to " + listenerPkg, e); } finally { Binder.restoreCallingIdentity(ident); } } /** * asynchronously notify all listeners about a removed notification */ Loading
services/core/java/com/android/server/notification/NotificationRecord.java +39 −0 Original line number Diff line number Diff line Loading @@ -38,6 +38,7 @@ import android.metrics.LogMaker; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.os.UserHandle; import android.provider.Settings; import android.service.notification.Adjustment; Loading @@ -47,6 +48,7 @@ import android.service.notification.NotificationStats; import android.service.notification.SnoozeCriterion; import android.service.notification.StatusBarNotification; import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; import android.util.Slog; import android.util.TimeUtils; Loading @@ -64,6 +66,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; /** * Holds data about notifications that should not be shared with the Loading Loading @@ -929,6 +932,42 @@ public final class NotificationRecord { mStats.setViewedSettings(); } public Set<Uri> getNotificationUris() { Notification notification = getNotification(); Set<Uri> uris = new ArraySet<>(); if (notification.sound != null) { uris.add(notification.sound); } if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null && channel.getSound() != null) { uris.add(channel.getSound()); } } if (notification.extras.containsKey(Notification.EXTRA_AUDIO_CONTENTS_URI)) { uris.add(notification.extras.getParcelable(Notification.EXTRA_AUDIO_CONTENTS_URI)); } if (notification.extras.containsKey(Notification.EXTRA_BACKGROUND_IMAGE_URI)) { uris.add(notification.extras.getParcelable(Notification.EXTRA_BACKGROUND_IMAGE_URI)); } if (Notification.MessagingStyle.class.equals(notification.getNotificationStyle())) { Parcelable[] newMessages = notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES); List<Notification.MessagingStyle.Message> messages = Notification.MessagingStyle.Message.getMessagesFromBundleArray(newMessages); Parcelable[] histMessages = notification.extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES); messages.addAll( Notification.MessagingStyle.Message.getMessagesFromBundleArray(histMessages)); for (Notification.MessagingStyle.Message message : messages) { uris.add(message.getDataUri()); } } return uris; } public LogMaker getLogMaker(long now) { if (mLogMaker == null) { // initialize fields that only change on update (so a new record) Loading