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

Commit aa749b8a authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Add implicit grants to NLSes

So they can query packages they are receiving notifications
from without needing to hold QUERY_ALL_PACKAGES.

Test: NotificationListenersTest, manual with test app
Fixes: 184736797
Change-Id: I8071d5a03515cc05cbd3f8598997e6236d306052
Merged-In: I8071d5a03515cc05cbd3f8598997e6236d306052
parent 6117e9ff
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -491,7 +491,7 @@ public class NotificationManagerService extends SystemService {
    private ActivityManagerInternal mAmi;
    private IPackageManager mPackageManager;
    private PackageManager mPackageManagerClient;
    private PackageManagerInternal mPackageManagerInternal;
    PackageManagerInternal mPackageManagerInternal;
    private PermissionPolicyInternal mPermissionPolicyInternal;
    AudioManager mAudioManager;
    AudioManagerInternal mAudioManagerInternal;
@@ -9697,7 +9697,7 @@ public class NotificationManagerService extends SystemService {
     * notifications visible to the given listener.
     */
    @GuardedBy("mNotificationLock")
    private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
    NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
        final int N = mNotificationList.size();
        final ArrayList<NotificationListenerService.Ranking> rankings = new ArrayList<>();
@@ -10834,12 +10834,17 @@ public class NotificationManagerService extends SystemService {
                                info, oldSbnLightClone, update, null, REASON_USER_STOPPED));
                        continue;
                    }
                    // Grant access before listener is notified
                    final int targetUserId = (info.userid == UserHandle.USER_ALL)
                            ? UserHandle.USER_SYSTEM : info.userid;
                    updateUriPermissions(r, old, info.component.getPackageName(), targetUserId);
                    mPackageManagerInternal.grantImplicitAccess(
                            targetUserId, null /* intent */,
                            UserHandle.getAppId(info.uid),
                            sbn.getUid(),
                            false /* direct */, false /* retainOnUpdate */);
                    final StatusBarNotification sbnToPost = trimCache.ForListener(info);
                    mHandler.post(() -> notifyPosted(info, sbnToPost, update));
                }
+42 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doNothing;
@@ -37,15 +38,23 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.pm.VersionedPackage;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IInterface;
import android.os.UserHandle;
import android.service.notification.NotificationListenerFilter;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.testing.TestableContext;
import android.util.ArraySet;
import android.util.Pair;
@@ -55,6 +64,8 @@ import android.util.Xml;

import com.android.server.UiServiceTestCase;

import com.google.common.collect.ImmutableList;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -64,6 +75,7 @@ import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.List;

public class NotificationListenersTest extends UiServiceTestCase {

@@ -388,4 +400,34 @@ public class NotificationListenersTest extends UiServiceTestCase {
        verify(mContext).sendBroadcastAsUser(
                any(), eq(UserHandle.of(userId)), nullable(String.class));
    }

    @Test
    public void testImplicitGrant() {
        String pkg = "pkg";
        int uid = 9;
        NotificationChannel channel = new NotificationChannel("id", "name",
                NotificationManager.IMPORTANCE_HIGH);
        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
                .setContentTitle("foo")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .setTimeoutAfter(1);

        StatusBarNotification sbn = new StatusBarNotification(pkg, pkg, 8, "tag", uid, 0,
                nb.build(), UserHandle.getUserHandleForUid(uid), null, 0);
        NotificationRecord r = new NotificationRecord(mContext, sbn, channel);

        ManagedServices.ManagedServiceInfo info = mListeners.new ManagedServiceInfo(
                null, new ComponentName("a", "a"), sbn.getUserId(), false, null, 33, 33);
        List<ManagedServices.ManagedServiceInfo> services = ImmutableList.of(info);
        when(mListeners.getServices()).thenReturn(services);

        when(mNm.isVisibleToListener(any(), anyInt(), any())).thenReturn(true);
        when(mNm.makeRankingUpdateLocked(info)).thenReturn(mock(NotificationRankingUpdate.class));
        mNm.mPackageManagerInternal = mPmi;

        mListeners.notifyPostedLocked(r, null);

        verify(mPmi).grantImplicitAccess(sbn.getUserId(), null, UserHandle.getAppId(33),
                sbn.getUid(), false, false);
    }
}