Loading services/core/java/com/android/server/notification/NotificationManagerService.java +2 −7 Original line number Diff line number Diff line Loading @@ -2579,6 +2579,7 @@ public class NotificationManagerService extends SystemService { mNotificationChannelLogger, mAppOps, mUserProfiles, mUgmInternal, mShowReviewPermissionsNotification, Clock.systemUTC()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, Loading Loading @@ -6672,13 +6673,7 @@ public class NotificationManagerService extends SystemService { final Uri originalSoundUri = (originalChannel != null) ? originalChannel.getSound() : null; if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) { Binder.withCleanCallingIdentity(() -> { mUgmInternal.checkGrantUriPermission(sourceUid, null, ContentProvider.getUriWithoutUserId(soundUri), Intent.FLAG_GRANT_READ_URI_PERMISSION, ContentProvider.getUserIdFromUri(soundUri, UserHandle.getUserId(sourceUid))); }); PermissionHelper.grantUriPermission(mUgmInternal, soundUri, sourceUid); } } Loading services/core/java/com/android/server/notification/NotificationRecord.java +52 −4 Original line number Diff line number Diff line Loading @@ -1493,14 +1493,23 @@ public final class NotificationRecord { final Notification notification = getNotification(); notification.visitUris((uri) -> { if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) { visitGrantableUri(uri, false, false); } else { oldVisitGrantableUri(uri, false, false); } }); if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null) { if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) { visitGrantableUri(channel.getSound(), (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) != 0, true); } else { oldVisitGrantableUri(channel.getSound(), (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) != 0, true); } } } } finally { Loading @@ -1516,7 +1525,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 visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { private void oldVisitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; if (mGrantableUris != null && mGrantableUris.contains(uri)) { Loading Loading @@ -1555,6 +1564,45 @@ public final class NotificationRecord { } } /** * Note the presence of a {@link Uri} that should have permission granted to * whoever will be rendering it. * <p> * If the enqueuing app has the ability to grant access, it will be added to * {@link #mGrantableUris}. Otherwise, this will either log or throw * {@link SecurityException} depending on target SDK of enqueuing app. */ private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { if (mGrantableUris != null && mGrantableUris.contains(uri)) { return; // already verified this URI } final int sourceUid = getSbn().getUid(); try { PermissionHelper.grantUriPermission(mUgmInternal, uri, sourceUid); if (mGrantableUris == null) { mGrantableUris = new ArraySet<>(); } mGrantableUris.add(uri); } catch (SecurityException e) { if (!userOverriddenUri) { if (isSound) { mSound = Settings.System.DEFAULT_NOTIFICATION_URI; Log.w(TAG, "Replacing " + uri + " from " + sourceUid + ": " + e.getMessage()); } else { if (mTargetSdkVersion >= Build.VERSION_CODES.P) { throw e; } else { Log.w(TAG, "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage()); } } } } } public LogMaker getLogMaker(long now) { LogMaker lm = getSbn().getLogMaker() .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance) Loading services/core/java/com/android/server/notification/PermissionHelper.java +20 −1 Original line number Diff line number Diff line Loading @@ -25,19 +25,25 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.companion.virtual.VirtualDeviceManager; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; import android.permission.IPermissionManager; import android.util.ArrayMap; import android.util.Pair; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.server.uri.UriGrantsManagerInternal; import java.util.Collections; import java.util.HashSet; Loading Loading @@ -298,6 +304,19 @@ public final class PermissionHelper { return false; } static void grantUriPermission(final UriGrantsManagerInternal ugmInternal, Uri uri, int sourceUid) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; Binder.withCleanCallingIdentity(() -> { // This will throw a SecurityException if the caller can't grant. ugmInternal.checkGrantUriPermission(sourceUid, null, ContentProvider.getUriWithoutUserId(uri), Intent.FLAG_GRANT_READ_URI_PERMISSION, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid))); }); } public static class PackagePermission { public final String packageName; public final @UserIdInt int userId; Loading services/core/java/com/android/server/notification/PreferencesHelper.java +11 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.notification.PermissionHelper.PackagePermission; import com.android.server.uri.UriGrantsManagerInternal; import org.json.JSONArray; import org.json.JSONException; Loading Loading @@ -219,6 +220,7 @@ public class PreferencesHelper implements RankingConfig { private final NotificationChannelLogger mNotificationChannelLogger; private final AppOpsManager mAppOps; private final ManagedServices.UserProfiles mUserProfiles; private final UriGrantsManagerInternal mUgmInternal; private SparseBooleanArray mBadgingEnabled; private SparseBooleanArray mBubblesEnabled; Loading @@ -239,6 +241,7 @@ public class PreferencesHelper implements RankingConfig { ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager, NotificationChannelLogger notificationChannelLogger, AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles, UriGrantsManagerInternal ugmInternal, boolean showReviewPermissionsNotification, Clock clock) { mContext = context; mZenModeHelper = zenHelper; Loading @@ -249,6 +252,7 @@ public class PreferencesHelper implements RankingConfig { mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; mUserProfiles = userProfiles; mUgmInternal = ugmInternal; mShowReviewPermissionsNotification = showReviewPermissionsNotification; mIsMediaNotificationFilteringEnabled = context.getResources() .getBoolean(R.bool.config_quickSettingsShowMediaPlayer); Loading Loading @@ -1169,6 +1173,13 @@ public class PreferencesHelper implements RankingConfig { } clearLockedFieldsLocked(channel); // Verify that the app has permission to read the sound Uri // Only check for new channels, as regular apps can only set sound // before creating. See: {@link NotificationChannel#setSound} if (Flags.notificationVerifyChannelSoundUri()) { PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid); } channel.setImportanceLockedByCriticalDeviceFunction( r.defaultAppLockedImportance || r.fixedImportance); Loading services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -170,3 +170,13 @@ flag { description: "This flag enables sound uri with vibration source" bug: "358524009" } flag { name: "notification_verify_channel_sound_uri" namespace: "systemui" description: "Verify Uri permission for sound when creating a notification channel" bug: "337775777" metadata { purpose: PURPOSE_BUGFIX } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +2 −7 Original line number Diff line number Diff line Loading @@ -2579,6 +2579,7 @@ public class NotificationManagerService extends SystemService { mNotificationChannelLogger, mAppOps, mUserProfiles, mUgmInternal, mShowReviewPermissionsNotification, Clock.systemUTC()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, Loading Loading @@ -6672,13 +6673,7 @@ public class NotificationManagerService extends SystemService { final Uri originalSoundUri = (originalChannel != null) ? originalChannel.getSound() : null; if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) { Binder.withCleanCallingIdentity(() -> { mUgmInternal.checkGrantUriPermission(sourceUid, null, ContentProvider.getUriWithoutUserId(soundUri), Intent.FLAG_GRANT_READ_URI_PERMISSION, ContentProvider.getUserIdFromUri(soundUri, UserHandle.getUserId(sourceUid))); }); PermissionHelper.grantUriPermission(mUgmInternal, soundUri, sourceUid); } } Loading
services/core/java/com/android/server/notification/NotificationRecord.java +52 −4 Original line number Diff line number Diff line Loading @@ -1493,14 +1493,23 @@ public final class NotificationRecord { final Notification notification = getNotification(); notification.visitUris((uri) -> { if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) { visitGrantableUri(uri, false, false); } else { oldVisitGrantableUri(uri, false, false); } }); if (notification.getChannelId() != null) { NotificationChannel channel = getChannel(); if (channel != null) { if (com.android.server.notification.Flags.notificationVerifyChannelSoundUri()) { visitGrantableUri(channel.getSound(), (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) != 0, true); } else { oldVisitGrantableUri(channel.getSound(), (channel.getUserLockedFields() & NotificationChannel.USER_LOCKED_SOUND) != 0, true); } } } } finally { Loading @@ -1516,7 +1525,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 visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { private void oldVisitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; if (mGrantableUris != null && mGrantableUris.contains(uri)) { Loading Loading @@ -1555,6 +1564,45 @@ public final class NotificationRecord { } } /** * Note the presence of a {@link Uri} that should have permission granted to * whoever will be rendering it. * <p> * If the enqueuing app has the ability to grant access, it will be added to * {@link #mGrantableUris}. Otherwise, this will either log or throw * {@link SecurityException} depending on target SDK of enqueuing app. */ private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { if (mGrantableUris != null && mGrantableUris.contains(uri)) { return; // already verified this URI } final int sourceUid = getSbn().getUid(); try { PermissionHelper.grantUriPermission(mUgmInternal, uri, sourceUid); if (mGrantableUris == null) { mGrantableUris = new ArraySet<>(); } mGrantableUris.add(uri); } catch (SecurityException e) { if (!userOverriddenUri) { if (isSound) { mSound = Settings.System.DEFAULT_NOTIFICATION_URI; Log.w(TAG, "Replacing " + uri + " from " + sourceUid + ": " + e.getMessage()); } else { if (mTargetSdkVersion >= Build.VERSION_CODES.P) { throw e; } else { Log.w(TAG, "Ignoring " + uri + " from " + sourceUid + ": " + e.getMessage()); } } } } } public LogMaker getLogMaker(long now) { LogMaker lm = getSbn().getLogMaker() .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance) Loading
services/core/java/com/android/server/notification/PermissionHelper.java +20 −1 Original line number Diff line number Diff line Loading @@ -25,19 +25,25 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.companion.virtual.VirtualDeviceManager; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.net.Uri; import android.os.Binder; import android.os.RemoteException; import android.os.UserHandle; import android.permission.IPermissionManager; import android.util.ArrayMap; import android.util.Pair; import android.util.Slog; import com.android.internal.util.ArrayUtils; import com.android.server.uri.UriGrantsManagerInternal; import java.util.Collections; import java.util.HashSet; Loading Loading @@ -298,6 +304,19 @@ public final class PermissionHelper { return false; } static void grantUriPermission(final UriGrantsManagerInternal ugmInternal, Uri uri, int sourceUid) { if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; Binder.withCleanCallingIdentity(() -> { // This will throw a SecurityException if the caller can't grant. ugmInternal.checkGrantUriPermission(sourceUid, null, ContentProvider.getUriWithoutUserId(uri), Intent.FLAG_GRANT_READ_URI_PERMISSION, ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid))); }); } public static class PackagePermission { public final String packageName; public final @UserIdInt int userId; Loading
services/core/java/com/android/server/notification/PreferencesHelper.java +11 −0 Original line number Diff line number Diff line Loading @@ -94,6 +94,7 @@ import com.android.internal.util.XmlUtils; import com.android.modules.utils.TypedXmlPullParser; import com.android.modules.utils.TypedXmlSerializer; import com.android.server.notification.PermissionHelper.PackagePermission; import com.android.server.uri.UriGrantsManagerInternal; import org.json.JSONArray; import org.json.JSONException; Loading Loading @@ -219,6 +220,7 @@ public class PreferencesHelper implements RankingConfig { private final NotificationChannelLogger mNotificationChannelLogger; private final AppOpsManager mAppOps; private final ManagedServices.UserProfiles mUserProfiles; private final UriGrantsManagerInternal mUgmInternal; private SparseBooleanArray mBadgingEnabled; private SparseBooleanArray mBubblesEnabled; Loading @@ -239,6 +241,7 @@ public class PreferencesHelper implements RankingConfig { ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager, NotificationChannelLogger notificationChannelLogger, AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles, UriGrantsManagerInternal ugmInternal, boolean showReviewPermissionsNotification, Clock clock) { mContext = context; mZenModeHelper = zenHelper; Loading @@ -249,6 +252,7 @@ public class PreferencesHelper implements RankingConfig { mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; mUserProfiles = userProfiles; mUgmInternal = ugmInternal; mShowReviewPermissionsNotification = showReviewPermissionsNotification; mIsMediaNotificationFilteringEnabled = context.getResources() .getBoolean(R.bool.config_quickSettingsShowMediaPlayer); Loading Loading @@ -1169,6 +1173,13 @@ public class PreferencesHelper implements RankingConfig { } clearLockedFieldsLocked(channel); // Verify that the app has permission to read the sound Uri // Only check for new channels, as regular apps can only set sound // before creating. See: {@link NotificationChannel#setSound} if (Flags.notificationVerifyChannelSoundUri()) { PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid); } channel.setImportanceLockedByCriticalDeviceFunction( r.defaultAppLockedImportance || r.fixedImportance); Loading
services/core/java/com/android/server/notification/flags.aconfig +10 −0 Original line number Diff line number Diff line Loading @@ -170,3 +170,13 @@ flag { description: "This flag enables sound uri with vibration source" bug: "358524009" } flag { name: "notification_verify_channel_sound_uri" namespace: "systemui" description: "Verify Uri permission for sound when creating a notification channel" bug: "337775777" metadata { purpose: PURPOSE_BUGFIX } }