Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 95dbff5e authored by Julia Reynolds's avatar Julia Reynolds Committed by Android (Google) Code Review
Browse files

Merge "Better handle notification uid resolution for missing pkgs"

parents 73f02fce a46a7694
Loading
Loading
Loading
Loading
+17 −7
Original line number Diff line number Diff line
@@ -315,7 +315,7 @@ public class NotificationManagerService extends SystemService {

    static final int VIBRATE_PATTERN_MAXLEN = 8 * 2 + 1; // up to eight bumps

    static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
    static final int INVALID_UID = -1;

    static final boolean ENABLE_BLOCKED_TOASTS = true;

@@ -4699,6 +4699,12 @@ public class NotificationManagerService extends SystemService {
        // ensure opPkg is delegate if does not match pkg
        int uid = resolveNotificationUid(opPkg, pkg, callingUid, userId);

        if (uid == INVALID_UID) {
            Slog.w(TAG, opPkg + ":" + callingUid + " trying to cancel notification "
                    + "for nonexistent pkg " + pkg + " in user " + userId);
            return;
        }

        // if opPkg is not the same as pkg, make sure the notification given was posted
        // by opPkg
        if (!Objects.equals(pkg, opPkg)) {
@@ -4743,6 +4749,11 @@ public class NotificationManagerService extends SystemService {
        // as "pkg"
        final int notificationUid = resolveNotificationUid(opPkg, pkg, callingUid, userId);

        if (notificationUid == INVALID_UID) {
            throw new SecurityException("Caller " + opPkg + ":" + callingUid
                    + " trying to post for invalid pkg " + pkg + " in user " + incomingUserId);
        }

        checkRestrictedCategories(notification);

        // Fix the notification as best we can.
@@ -5063,8 +5074,7 @@ public class NotificationManagerService extends SystemService {
    }

    @VisibleForTesting
    int resolveNotificationUid(String callingPkg, String targetPkg,
            int callingUid, int userId) {
    int resolveNotificationUid(String callingPkg, String targetPkg, int callingUid, int userId) {
        if (userId == UserHandle.USER_ALL) {
            userId = USER_SYSTEM;
        }
@@ -5075,16 +5085,16 @@ public class NotificationManagerService extends SystemService {
            return callingUid;
        }

        int targetUid = -1;
        int targetUid = INVALID_UID;
        try {
            targetUid = mPackageManagerClient.getPackageUidAsUser(targetPkg, userId);
        } catch (NameNotFoundException e) {
            /* ignore */
            /* ignore, handled by caller */
        }
        // posted from app A on behalf of app B
        if (targetUid != -1 && (isCallerAndroid(callingPkg, callingUid)
        if (isCallerAndroid(callingPkg, callingUid)
                || mPreferencesHelper.isDelegateAllowed(
                        targetPkg, targetUid, callingPkg, callingUid))) {
                        targetPkg, targetUid, callingPkg, callingUid)) {
            return targetUid;
        }

+35 −6
Original line number Diff line number Diff line
@@ -181,12 +181,6 @@ import java.util.function.Consumer;
@RunWithLooper
public class NotificationManagerServiceTest extends UiServiceTestCase {
    private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
    private static final String CLEAR_DEVICE_CONFIG_KEY_CMD =
            "device_config delete " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
                    + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;
    private static final String SET_DEFAULT_ASSISTANT_DEVICE_CONFIG_CMD =
            "device_config put " + DeviceConfig.NAMESPACE_SYSTEMUI + " "
                    + SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE;

    private final int mUid = Binder.getCallingUid();
    private TestableNotificationManagerService mService;
@@ -4039,6 +4033,41 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
        assertEquals(expectedUid, mService.resolveNotificationUid("android", "target", 0, 0));
    }

    @Test
    public void testPostFromAndroidForNonExistentPackage() throws Exception {
        final String notReal = "NOT REAL";
        when(mPackageManagerClient.getPackageUidAsUser(anyString(), anyInt())).thenThrow(
                PackageManager.NameNotFoundException.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.uid = -1;
        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);

        final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
        try {
            mInternalService.enqueueNotification(notReal, "android", 0, 0, "tag",
                    sbn.getId(), sbn.getNotification(), sbn.getUserId());
            fail("can't post notifications for nonexistent packages, even if you exist");
        } catch (SecurityException e) {
            // yay
        }
    }

    @Test
    public void testCancelFromAndroidForNonExistentPackage() throws Exception {
        final String notReal = "NOT REAL";
        when(mPackageManagerClient.getPackageUidAsUser(eq(notReal), anyInt())).thenThrow(
                PackageManager.NameNotFoundException.class);
        ApplicationInfo ai = new ApplicationInfo();
        ai.uid = -1;
        when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt())).thenReturn(ai);

        // unlike the post case, ignore instead of throwing
        final StatusBarNotification sbn = generateNotificationRecord(null).sbn;

        mInternalService.cancelNotification(notReal, "android", 0, 0, "tag",
                sbn.getId(), sbn.getUserId());
    }

    @Test
    public void testResolveNotificationUid_delegateNotAllowed() throws Exception {
        when(mPackageManagerClient.getPackageUidAsUser("target", 0)).thenReturn(123);