From c8f33a9527526ce25fe7c39d79c16bb9f96e9104 Mon Sep 17 00:00:00 2001 From: Jay Thomas Sullivan Date: Wed, 27 Sep 2023 17:48:09 -0700 Subject: [Role Logic Move] Make setNotificationListenerAccessGranted user-aware This operation currently assumes that the calling user is the user for which the operation should target. Instead, pull the userId from NotificationManager's context, and pass this to NotificationService. Mark NotificationManager method as @UserHandleAware, which informs the caller that the operation will instead target the user passed into the context used to initialize NotificationManager. This change is needed to support the Role Business Logic Move project, because the caller of this method will be moving from a per-user app into SystemServer. Bug: 302563478 Test: atest CtsRoleTestCases NotificationListenerCheckTest NotificationManagerTest Change-Id: Ic590a9ab40a87be4817cd32c13d7248fc15a154b --- core/java/android/app/NotificationManager.java | 29 +++++++++++++++++++--- .../notification/NotificationManagerService.java | 12 ++++++--- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 79b68c1456c7..b8bea9d102e1 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -25,8 +25,12 @@ import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.annotation.UserHandleAware; import android.annotation.WorkerThread; import android.app.Notification.Builder; +import android.app.compat.CompatChanges; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; @@ -1658,24 +1662,43 @@ public class NotificationManager { setNotificationListenerAccessGranted(listener, granted, true); } + /** + * For apps targeting {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and above, the + * {@code setNotificationListenerAccessGranted} method will use the user contained within the + * context. + * For apps targeting an SDK version below this, the user of the calling process will + * be used (Process.myUserHandle()). + * + * @hide + */ + @ChangeId + @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) + public static final long SET_LISTENER_ACCESS_GRANTED_IS_USER_AWARE = 302563478L; + /** * Grants/revokes Notification Listener access to the given component for current user. * To grant access for a particular user, obtain this service by using the {@link Context} * provided by {@link Context#createPackageContextAsUser} * * @param listener Name of component to grant/revoke access - * @param granted Grant/revoke access - * @param userSet Whether the action was triggered explicitly by user + * @param granted Grant/revoke access + * @param userSet Whether the action was triggered explicitly by user * @hide */ @SystemApi @TestApi + @UserHandleAware(enabledSinceTargetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) @RequiresPermission(android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS) public void setNotificationListenerAccessGranted( @NonNull ComponentName listener, boolean granted, boolean userSet) { INotificationManager service = getService(); try { - service.setNotificationListenerAccessGranted(listener, granted, userSet); + if (CompatChanges.isChangeEnabled(SET_LISTENER_ACCESS_GRANTED_IS_USER_AWARE)) { + service.setNotificationListenerAccessGrantedForUser(listener, mContext.getUserId(), + granted, userSet); + } else { + service.setNotificationListenerAccessGranted(listener, granted, userSet); + } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 87c30674bfb7..5fc8ded200d8 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5730,13 +5730,18 @@ public class NotificationManagerService extends SystemService { public void setNotificationListenerAccessGrantedForUser(ComponentName listener, int userId, boolean granted, boolean userSet) { Objects.requireNonNull(listener); + if (UserHandle.getCallingUserId() != userId) { + getContext().enforceCallingOrSelfPermission( + android.Manifest.permission.INTERACT_ACROSS_USERS, + "setNotificationListenerAccessGrantedForUser for user " + userId); + } checkNotificationListenerAccess(); if (granted && listener.flattenToString().length() > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) { throw new IllegalArgumentException( "Component name too long: " + listener.flattenToString()); } - if (!userSet && isNotificationListenerAccessUserSet(listener)) { + if (!userSet && isNotificationListenerAccessUserSet(listener, userId)) { // Don't override user's choice return; } @@ -5762,9 +5767,8 @@ public class NotificationManagerService extends SystemService { } } - private boolean isNotificationListenerAccessUserSet(ComponentName listener) { - return mListeners.isPackageOrComponentUserSet(listener.flattenToString(), - getCallingUserHandle().getIdentifier()); + private boolean isNotificationListenerAccessUserSet(ComponentName listener, int userId) { + return mListeners.isPackageOrComponentUserSet(listener.flattenToString(), userId); } @Override -- cgit v1.2.3-59-g8ed1b