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

Commit e75a45ec authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge "Add early exits to visitGrantableUri/calculateGrantableUris." into udc-qpr-dev

parents 8c45339d 7deb904f
Loading
Loading
Loading
Loading
+27 −20
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@ import static android.service.notification.NotificationListenerService.Ranking.U
import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;

import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -48,6 +46,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.Trace;
import android.os.UserHandle;
import android.os.VibrationEffect;
import android.provider.Settings;
@@ -98,8 +97,7 @@ public final class NotificationRecord {
    // the period after which a notification is updated where it can make sound
    private static final int MAX_SOUND_DELAY_MS = 2000;
    private final StatusBarNotification sbn;
    IActivityManager mAm;
    UriGrantsManagerInternal mUgmInternal;
    private final UriGrantsManagerInternal mUgmInternal;
    final int mTargetSdkVersion;
    final int mOriginalFlags;
    private final Context mContext;
@@ -223,7 +221,6 @@ public final class NotificationRecord {
        this.sbn = sbn;
        mTargetSdkVersion = LocalServices.getService(PackageManagerInternal.class)
                .getPackageTargetSdkVersion(sbn.getPackageName());
        mAm = ActivityManager.getService();
        mUgmInternal = LocalServices.getService(UriGrantsManagerInternal.class);
        mOriginalFlags = sbn.getNotification().flags;
        mRankingTimeMs = calculateRankingTimeMs(0L);
@@ -1387,7 +1384,13 @@ public final class NotificationRecord {
     * Collect all {@link Uri} that should have permission granted to whoever
     * will be rendering it.
     */
    protected void calculateGrantableUris() {
    private void calculateGrantableUris() {
        Trace.beginSection("NotificationRecord.calculateGrantableUris");
        try {
            // We can't grant URI permissions from system.
            final int sourceUid = getSbn().getUid();
            if (sourceUid == android.os.Process.SYSTEM_UID) return;

            final Notification notification = getNotification();
            notification.visitUris((uri) -> {
                visitGrantableUri(uri, false, false);
@@ -1400,6 +1403,9 @@ public final class NotificationRecord {
                            & NotificationChannel.USER_LOCKED_SOUND) != 0, true);
                }
            }
        } finally {
            Trace.endSection();
        }
    }

    /**
@@ -1413,13 +1419,14 @@ public final class NotificationRecord {
    private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) {
        if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;

        // We can't grant Uri permissions from system
        final int sourceUid = getSbn().getUid();
        if (sourceUid == android.os.Process.SYSTEM_UID) return;
        if (mGrantableUris != null && mGrantableUris.contains(uri)) {
            return; // already verified this URI
        }

        final int sourceUid = getSbn().getUid();
        final long ident = Binder.clearCallingIdentity();
        try {
            // This will throw SecurityException if caller can't grant
            // This will throw a SecurityException if the caller can't grant.
            mUgmInternal.checkGrantUriPermission(sourceUid, null,
                    ContentProvider.getUriWithoutUserId(uri),
                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
+21 −27
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.fail;
import static org.junit.Assert.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
@@ -44,7 +44,6 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.app.ActivityManager;
import android.app.IActivityManager;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationChannel;
@@ -76,6 +75,7 @@ import androidx.test.runner.AndroidJUnit4;

import com.android.internal.R;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.server.LocalServices;
import com.android.server.UiServiceTestCase;
import com.android.server.uri.UriGrantsManagerInternal;

@@ -850,84 +850,78 @@ public class NotificationRecordTest extends UiServiceTestCase {

    @Test
    public void testCalculateGrantableUris_PappProvided() {
        IActivityManager am = mock(IActivityManager.class);
        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
                anyInt(), anyInt())).thenThrow(new SecurityException());

        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
        LocalServices.addService(UriGrantsManagerInternal.class, ugm);

        channel.setSound(null, null);
        Notification n = new Notification.Builder(mContext, channel.getId())
                .setSmallIcon(Icon.createWithContentUri(Uri.parse("content://something")))
                .build();
        StatusBarNotification sbn =
                new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
        record.mAm = am;
        record.mUgmInternal = ugm;

        try {
            record.calculateGrantableUris();
            fail("App provided uri for p targeting app should throw exception");
        } catch (SecurityException e) {
            // expected
        }
        assertThrows("App provided uri for p targeting app should throw exception",
                SecurityException.class,
                () -> new NotificationRecord(mMockContext, sbn, channel));
    }

    @Test
    public void testCalculateGrantableUris_PappProvided_invalidSound() {
        IActivityManager am = mock(IActivityManager.class);
        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
                anyInt(), anyInt())).thenThrow(new SecurityException());

        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
        LocalServices.addService(UriGrantsManagerInternal.class, ugm);

        channel.setSound(Uri.parse("content://something"), mock(AudioAttributes.class));

        Notification n = mock(Notification.class);
        when(n.getChannelId()).thenReturn(channel.getId());
        StatusBarNotification sbn =
                new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
        record.mAm = am;
        record.mUgmInternal = ugm;

        record.calculateGrantableUris();
        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
        assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
    }

    @Test
    public void testCalculateGrantableUris_PuserOverridden() {
        IActivityManager am = mock(IActivityManager.class);
        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
                anyInt(), anyInt())).thenThrow(new SecurityException());

        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
        LocalServices.addService(UriGrantsManagerInternal.class, ugm);

        channel.lockFields(NotificationChannel.USER_LOCKED_SOUND);
        Notification n = mock(Notification.class);
        when(n.getChannelId()).thenReturn(channel.getId());
        StatusBarNotification sbn =
                new StatusBarNotification(PKG_P, PKG_P, id1, tag1, uid, uid, n, mUser, null, uid);
        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
        record.mAm = am;

        record.calculateGrantableUris();
        new NotificationRecord(mMockContext, sbn, channel); // should not throw
    }

    @Test
    public void testCalculateGrantableUris_prePappProvided() {
        IActivityManager am = mock(IActivityManager.class);
        UriGrantsManagerInternal ugm = mock(UriGrantsManagerInternal.class);
        when(ugm.checkGrantUriPermission(anyInt(), eq(null), any(Uri.class),
                anyInt(), anyInt())).thenThrow(new SecurityException());

        LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
        LocalServices.addService(UriGrantsManagerInternal.class, ugm);

        Notification n = mock(Notification.class);
        when(n.getChannelId()).thenReturn(channel.getId());
        StatusBarNotification sbn =
                new StatusBarNotification(PKG_O, PKG_O, id1, tag1, uid, uid, n, mUser, null, uid);
        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
        record.mAm = am;

        record.calculateGrantableUris();
        // should not throw
        new NotificationRecord(mMockContext, sbn, channel); // should not throw
    }

    @Test