diff options
| author | 2025-03-03 06:21:43 -0800 | |
|---|---|---|
| committer | 2025-03-03 06:21:43 -0800 | |
| commit | d8a050cbc1e12f3512490b51ca11f8b0789f2e87 (patch) | |
| tree | 25f14d1cfcbbb038bc3a09db404ab1005913d16a | |
| parent | 94d03ec535258b5ab17615cc062f37de82ed8179 (diff) | |
| parent | 494dd981aa026ecafeddbe71aa0bd7df0f0fdbe5 (diff) | |
Merge changes Iaf59e345,I18ab8227 into main
* changes:
Revert "Check sound Uri permission when creating a notification channel"
Revert "Cleanup flag for notification sound Uri permission check"
6 files changed, 36 insertions, 140 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 60371d751c4a..0f1d28db8d82 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2809,7 +2809,6 @@ public class NotificationManagerService extends SystemService { mNotificationChannelLogger, mAppOps, mUserProfiles, - mUgmInternal, mShowReviewPermissionsNotification, Clock.systemUTC()); mRankingHelper = new RankingHelper(getContext(), mRankingHandler, mPreferencesHelper, @@ -7210,7 +7209,13 @@ public class NotificationManagerService extends SystemService { final Uri originalSoundUri = (originalChannel != null) ? originalChannel.getSound() : null; if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) { - PermissionHelper.grantUriPermission(mUgmInternal, soundUri, sourceUid); + Binder.withCleanCallingIdentity(() -> { + mUgmInternal.checkGrantUriPermission(sourceUid, null, + ContentProvider.getUriWithoutUserId(soundUri), + Intent.FLAG_GRANT_READ_URI_PERMISSION, + ContentProvider.getUserIdFromUri(soundUri, + UserHandle.getUserId(sourceUid))); + }); } } diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index 5a58f457ba08..398894bf5273 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -37,7 +37,10 @@ import android.app.KeyguardManager; import android.app.Notification; import android.app.NotificationChannel; import android.app.Person; +import android.content.ContentProvider; +import android.content.ContentResolver; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.ShortcutInfo; @@ -46,6 +49,7 @@ import android.media.AudioAttributes; import android.media.AudioSystem; import android.metrics.LogMaker; import android.net.Uri; +import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.IBinder; @@ -1532,15 +1536,21 @@ 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 visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) { + if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return; + if (mGrantableUris != null && mGrantableUris.contains(uri)) { return; // already verified this URI } final int sourceUid = getSbn().getUid(); + final long ident = Binder.clearCallingIdentity(); try { - PermissionHelper.grantUriPermission(mUgmInternal, uri, sourceUid); + // This will throw a SecurityException if the caller can't grant. + mUgmInternal.checkGrantUriPermission(sourceUid, null, + ContentProvider.getUriWithoutUserId(uri), + Intent.FLAG_GRANT_READ_URI_PERMISSION, + ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid))); if (mGrantableUris == null) { mGrantableUris = new ArraySet<>(); @@ -1560,6 +1570,8 @@ public final class NotificationRecord { } } } + } finally { + Binder.restoreCallingIdentity(ident); } } diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java index 1464d481311a..b6f48890c528 100644 --- a/services/core/java/com/android/server/notification/PermissionHelper.java +++ b/services/core/java/com/android/server/notification/PermissionHelper.java @@ -25,25 +25,19 @@ 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; @@ -64,7 +58,7 @@ public final class PermissionHelper { private final IPermissionManager mPermManager; public PermissionHelper(Context context, IPackageManager packageManager, - IPermissionManager permManager) { + IPermissionManager permManager) { mContext = context; mPackageManager = packageManager; mPermManager = permManager; @@ -304,19 +298,6 @@ 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; diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 46ff7983bb2d..b26b4571b07a 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -100,7 +100,6 @@ 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; @@ -228,7 +227,6 @@ 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; @@ -247,7 +245,6 @@ 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; @@ -258,7 +255,6 @@ public class PreferencesHelper implements RankingConfig { mNotificationChannelLogger = notificationChannelLogger; mAppOps = appOpsManager; mUserProfiles = userProfiles; - mUgmInternal = ugmInternal; mShowReviewPermissionsNotification = showReviewPermissionsNotification; mIsMediaNotificationFilteringEnabled = context.getResources() .getBoolean(R.bool.config_quickSettingsShowMediaPlayer); @@ -1195,11 +1191,6 @@ 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} - PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid); - channel.setImportanceLockedByCriticalDeviceFunction( r.defaultAppLockedImportance || r.fixedImportance); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 3727bbefb1d3..dd5c601619a0 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -5211,41 +5211,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test - public void - updateNotificationChannelFromPrivilegedListener_oldSoundNoUriPerm_newSoundHasUriPerm() - throws Exception { - mService.setPreferencesHelper(mPreferencesHelper); - when(mCompanionMgr.getAssociations(mPkg, mUserId)) - .thenReturn(singletonList(mock(AssociationInfo.class))); - when(mPreferencesHelper.getNotificationChannel(eq(mPkg), anyInt(), - eq(mTestNotificationChannel.getId()), anyBoolean())) - .thenReturn(mTestNotificationChannel); - - // Missing Uri permissions for the old channel sound - final Uri oldSoundUri = Settings.System.DEFAULT_NOTIFICATION_URI; - doThrow(new SecurityException("no access")).when(mUgmInternal) - .checkGrantUriPermission(eq(Process.myUid()), any(), eq(oldSoundUri), - anyInt(), eq(Process.myUserHandle().getIdentifier())); - - // Has Uri permissions for the old channel sound - final Uri newSoundUri = Uri.parse("content://media/test/sound/uri"); - final NotificationChannel updatedNotificationChannel = new NotificationChannel( - TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); - updatedNotificationChannel.setSound(newSoundUri, - updatedNotificationChannel.getAudioAttributes()); - - mBinderService.updateNotificationChannelFromPrivilegedListener( - null, mPkg, Process.myUserHandle(), updatedNotificationChannel); - - verify(mPreferencesHelper, times(1)).updateNotificationChannel( - anyString(), anyInt(), any(), anyBoolean(), anyInt(), anyBoolean()); - - verify(mListeners, never()).notifyNotificationChannelChanged(eq(mPkg), - eq(Process.myUserHandle()), eq(mTestNotificationChannel), - eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); - } - - @Test public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); when(mCompanionMgr.getAssociations(mPkg, mUserId)) diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java index 752910d6d3c1..a02f628ce9b7 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java @@ -46,13 +46,11 @@ import static android.app.NotificationManager.IMPORTANCE_MAX; import static android.app.NotificationManager.IMPORTANCE_NONE; import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE; -import static android.content.ContentResolver.SCHEME_ANDROID_RESOURCE; -import static android.content.ContentResolver.SCHEME_CONTENT; -import static android.content.ContentResolver.SCHEME_FILE; import static android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION; import static android.media.AudioAttributes.USAGE_NOTIFICATION; import static android.os.UserHandle.USER_ALL; import static android.os.UserHandle.USER_SYSTEM; + import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT; import static android.service.notification.Adjustment.TYPE_CONTENT_RECOMMENDATION; import static android.service.notification.Adjustment.TYPE_NEWS; @@ -66,6 +64,7 @@ import static com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.No import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__DENIED; import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__GRANTED; import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES__FSI_STATE__NOT_REQUESTED; +import static com.android.server.notification.Flags.FLAG_ALL_NOTIFS_NEED_TTL; import static com.android.server.notification.Flags.FLAG_PERSIST_INCOMPLETE_RESTORE_DATA; import static com.android.server.notification.NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED_BY_USER; import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE; @@ -92,7 +91,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -385,10 +383,10 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); mXmlHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); resetZenModeHelper(); mAudioAttributes = new AudioAttributes.Builder() @@ -803,7 +801,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testReadXml_oldXml_migrates() throws Exception { mXmlHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, /* showReviewPermissionsNotification= */ true, mClock); + /* showReviewPermissionsNotification= */ true, mClock); String xml = "<ranking version=\"2\">\n" + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1 @@ -939,7 +937,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception { mXmlHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, /* showReviewPermissionsNotification= */ true, mClock); + /* showReviewPermissionsNotification= */ true, mClock); String xml = "<ranking version=\"3\">\n" + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" @@ -998,7 +996,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testReadXml_newXml_permissionNotificationOff() throws Exception { mHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, /* showReviewPermissionsNotification= */ false, mClock); + /* showReviewPermissionsNotification= */ false, mClock); String xml = "<ranking version=\"3\">\n" + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" @@ -1057,7 +1055,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception { mHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, /* showReviewPermissionsNotification= */ true, mClock); + /* showReviewPermissionsNotification= */ true, mClock); String xml = "<ranking version=\"4\">\n" + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" @@ -1655,7 +1653,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // simulate load after reboot mXmlHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); loadByteArrayXml(baos.toByteArray(), false, USER_ALL); // Trigger 2nd restore pass @@ -1710,7 +1708,7 @@ public class PreferencesHelperTest extends UiServiceTestCase { // simulate load after reboot mXmlHelper = new TestPreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); loadByteArrayXml(xml.getBytes(), false, USER_ALL); // Trigger 2nd restore pass @@ -1788,10 +1786,10 @@ public class PreferencesHelperTest extends UiServiceTestCase { mHelper = new TestPreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); mXmlHelper = new TestPreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper, mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUserProfiles, - mUgmInternal, false, mClock); + false, mClock); NotificationChannel channel = new NotificationChannel("id", "name", IMPORTANCE_LOW); @@ -3263,61 +3261,6 @@ public class PreferencesHelperTest extends UiServiceTestCase { } @Test - public void testCreateChannel_noSoundUriPermission_contentSchemeVerified() { - final Uri sound = Uri.parse(SCHEME_CONTENT + "://media/test/sound/uri"); - - doThrow(new SecurityException("no access")).when(mUgmInternal) - .checkGrantUriPermission(eq(UID_N_MR1), any(), eq(sound), - anyInt(), eq(UserHandle.getUserId(UID_N_MR1))); - - final NotificationChannel channel = new NotificationChannel("id2", "name2", - NotificationManager.IMPORTANCE_DEFAULT); - channel.setSound(sound, mAudioAttributes); - - assertThrows(SecurityException.class, - () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, - true, false, UID_N_MR1, false)); - assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true)) - .isNull(); - } - - @Test - public void testCreateChannel_noSoundUriPermission_fileSchemaIgnored() { - final Uri sound = Uri.parse(SCHEME_FILE + "://path/sound"); - - doThrow(new SecurityException("no access")).when(mUgmInternal) - .checkGrantUriPermission(eq(UID_N_MR1), any(), any(), - anyInt(), eq(UserHandle.getUserId(UID_N_MR1))); - - final NotificationChannel channel = new NotificationChannel("id2", "name2", - NotificationManager.IMPORTANCE_DEFAULT); - channel.setSound(sound, mAudioAttributes); - - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false, UID_N_MR1, - false); - assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true) - .getSound()).isEqualTo(sound); - } - - @Test - public void testCreateChannel_noSoundUriPermission_resourceSchemaIgnored() { - final Uri sound = Uri.parse(SCHEME_ANDROID_RESOURCE + "://resId/sound"); - - doThrow(new SecurityException("no access")).when(mUgmInternal) - .checkGrantUriPermission(eq(UID_N_MR1), any(), any(), - anyInt(), eq(UserHandle.getUserId(UID_N_MR1))); - - final NotificationChannel channel = new NotificationChannel("id2", "name2", - NotificationManager.IMPORTANCE_DEFAULT); - channel.setSound(sound, mAudioAttributes); - - mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false, UID_N_MR1, - false); - assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true) - .getSound()).isEqualTo(sound); - } - - @Test public void testPermanentlyDeleteChannels() throws Exception { NotificationChannel channel1 = new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); @@ -7086,10 +7029,9 @@ public class PreferencesHelperTest extends UiServiceTestCase { ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager, NotificationChannelLogger notificationChannelLogger, AppOpsManager appOpsManager, ManagedServices.UserProfiles userProfiles, - UriGrantsManagerInternal ugmInternal, boolean showReviewPermissionsNotification, Clock clock) { super(context, pm, rankingHandler, zenHelper, permHelper, permManager, - notificationChannelLogger, appOpsManager, userProfiles, ugmInternal, + notificationChannelLogger, appOpsManager, userProfiles, showReviewPermissionsNotification, clock); } |