diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 3eee572e82f32..ac5b2d5258262 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -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 rankings = new ArrayList<>(); @@ -10804,7 +10804,7 @@ public class NotificationManagerService extends SystemService { TrimCache trimCache = new TrimCache(sbn); for (final ManagedServiceInfo info : getServices()) { - boolean sbnVisible = isVisibleToListener(sbn, r. getNotificationType(), info); + boolean sbnVisible = isVisibleToListener(sbn, r.getNotificationType(), info); boolean oldSbnVisible = (oldSbn != null) && isVisibleToListener(oldSbn, old.getNotificationType(), info); // This notification hasn't been and still isn't visible -> ignore. @@ -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)); } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java index f4b9e258f7e06..4a1305090c497 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java @@ -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 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); + } }