Loading services/core/java/com/android/server/notification/NotificationManagerService.java +5 −13 Original line number Diff line number Diff line Loading @@ -3746,6 +3746,10 @@ public class NotificationManagerService extends SystemService { if (!hadChannel && hasChannel && !hasRequestedNotificationPermission && startingTaskId != ActivityTaskManager.INVALID_TASK_ID) { hasRequestedNotificationPermission = true; if (mPermissionPolicyInternal == null) { mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); } mHandler.post(new ShowNotificationPermissionPromptRunnable(pkg, UserHandle.getUserId(uid), startingTaskId, mPermissionPolicyInternal)); Loading @@ -3764,19 +3768,7 @@ public class NotificationManagerService extends SystemService { try { int uid = mPackageManager.getPackageUid(pkg, 0, UserHandle.getUserId(Binder.getCallingUid())); List<ActivityManager.AppTask> tasks = mAtm.getAppTasks(pkg, uid); for (int i = 0; i < tasks.size(); i++) { ActivityManager.RecentTaskInfo task = tasks.get(i).getTaskInfo(); if (mPermissionPolicyInternal == null) { mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); } if (mPermissionPolicyInternal != null && mPermissionPolicyInternal.canShowPermissionPromptForTask(task)) { taskId = task.taskId; break; } } taskId = mAtm.getTaskToShowPermissionDialogOn(pkg, uid); } catch (RemoteException e) { // Do nothing } Loading services/core/java/com/android/server/policy/PermissionPolicyInternal.java +15 −2 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ public abstract class PermissionPolicyInternal { * prompt should be shown if the app targets S-, is currently running in a visible, focused * task, has the REVIEW_REQUIRED flag set on its implicit notification permission, and has * created at least one notification channel (even if it has since been deleted). * * @param packageName The package whose permission is being checked * @param userId The user for whom the package is being started * @param taskId The task the notification prompt should be attached to Loading @@ -66,10 +67,22 @@ public abstract class PermissionPolicyInternal { /** * Determine if a particular task is in the proper state to show a system-triggered permission * prompt. A prompt can be shown if the task is focused, visible, and running. * prompt. A prompt can be shown if the task is focused, visible, and running and * 1. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER), or * 2. The activity belongs to the same package as the one which launched the task originally, * and the task was started with a launcher intent * * @param taskInfo The task to be checked * @param currPkg The package of the current top visible activity * @param intent The intent of the current top visible activity */ public abstract boolean shouldShowNotificationDialogForTask(@Nullable TaskInfo taskInfo, @Nullable String currPkg, @Nullable Intent intent); /** * @return true if an intent will resolve to a permission request dialog activity */ public abstract boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo); public abstract boolean isIntentToPermissionDialog(@NonNull Intent intent); /** * @return Whether the policy is initialized for a user. Loading services/core/java/com/android/server/policy/PermissionPolicyService.java +45 −19 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; Loading Loading @@ -1016,7 +1018,7 @@ public final class PermissionPolicyService extends SystemService { ActivityInterceptorInfo info) { String action = info.intent.getAction(); ActivityInterceptResult result = null; if (!PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action) if (!ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action) && !PackageManager.ACTION_REQUEST_PERMISSIONS.equals(action)) { return null; } Loading @@ -1033,7 +1035,7 @@ public final class PermissionPolicyService extends SystemService { && !mContinueNotifGrantMessageUids.contains(info.realCallingUid)) { return result; } if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)) { if (ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)) { String otherPkg = info.intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); if (otherPkg == null || (mPackageManager.getPermissionFlags( POST_NOTIFICATIONS, otherPkg, UserHandle.of(info.userId)) Loading @@ -1052,8 +1054,8 @@ public final class PermissionPolicyService extends SystemService { public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo, ActivityInterceptorInfo info) { super.onActivityLaunched(taskInfo, activityInfo, info); if (!shouldShowNotificationDialogOrClearFlags(info.intent, info.checkedOptions)) { if (!shouldShowNotificationDialogOrClearFlags(taskInfo, activityInfo.packageName, info.intent, info.checkedOptions, true)) { return; } UserHandle user = UserHandle.of(taskInfo.userId); Loading Loading @@ -1085,7 +1087,7 @@ public final class PermissionPolicyService extends SystemService { return false; } if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(intent.getAction()) if (ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(intent.getAction()) && (callingUid != Process.SYSTEM_UID || !SYSTEM_PKG.equals(callingPackage))) { return false; } Loading @@ -1104,18 +1106,48 @@ public final class PermissionPolicyService extends SystemService { launchNotificationPermissionRequestDialog(packageName, user, taskId); } @Override public boolean isIntentToPermissionDialog(@NonNull Intent intent) { return Objects.equals(intent.getPackage(), mPackageManager.getPermissionControllerPackageName()) && (Objects.equals(intent.getAction(), ACTION_REQUEST_PERMISSIONS_FOR_OTHER) || Objects.equals(intent.getAction(), ACTION_REQUEST_PERMISSIONS)); } @Override public boolean shouldShowNotificationDialogForTask(TaskInfo taskInfo, String currPkg, Intent intent) { return shouldShowNotificationDialogOrClearFlags( taskInfo, currPkg, intent, null, false); } /** * Determine if we should show a notification dialog, or clear the REVIEW_REQUIRED flag, * from a particular package for a particular intent. Returns true if: * Determine if a particular task is in the proper state to show a system-triggered * permission prompt. A prompt can be shown if the task is just starting, or the task is * currently focused, visible, and running, and, * 1. The isEligibleForLegacyPermissionPrompt ActivityOption is set, or * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER) * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER), or * 3. The activity belongs to the same package as the one which launched the task * originally, and the task was started with a launcher intent * @param taskInfo The task to be checked * @param currPkg The package of the current top visible activity * @param intent The intent of the current top visible activity */ private boolean shouldShowNotificationDialogOrClearFlags(Intent intent, ActivityOptions options) { if ((options != null && options.isEligibleForLegacyPermissionPrompt())) { return true; private boolean shouldShowNotificationDialogOrClearFlags(TaskInfo taskInfo, String currPkg, Intent intent, ActivityOptions options, boolean activityStart) { if (intent == null || currPkg == null || taskInfo == null || (!(taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning) && !activityStart)) { return false; } return isLauncherIntent(intent) || (options != null && options.isEligibleForLegacyPermissionPrompt()) || (currPkg.equals(taskInfo.baseActivity.getPackageName()) && isLauncherIntent(taskInfo.baseIntent)); } private boolean isLauncherIntent(Intent intent) { return Intent.ACTION_MAIN.equals(intent.getAction()) && intent.getCategories() != null && (intent.getCategories().contains(Intent.CATEGORY_LAUNCHER) Loading Loading @@ -1144,7 +1176,7 @@ public final class PermissionPolicyService extends SystemService { Intent grantPermission = mPackageManager .buildRequestPermissionsIntent(new String[] { POST_NOTIFICATIONS }); grantPermission.setAction( PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER); ACTION_REQUEST_PERMISSIONS_FOR_OTHER); grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName); ActivityOptions options = new ActivityOptions(new Bundle()); Loading @@ -1170,12 +1202,6 @@ public final class PermissionPolicyService extends SystemService { } } @Override public boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo) { return taskInfo != null && taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning; } /** * Check if the intent action is removed for the calling package (often based on target SDK * version). If the action is removed, we'll silently cancel the activity launch. Loading services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +11 −0 Original line number Diff line number Diff line Loading @@ -680,4 +680,15 @@ public abstract class ActivityTaskManagerInternal { /** Get the app tasks for a package */ public abstract List<ActivityManager.AppTask> getAppTasks(String pkgName, int uid); /** * Determine if there exists a task which meets the criteria set by the PermissionPolicyService * to show a system-owned permission dialog over, for a given package * @see PermissionPolicyInternal.shouldShowNotificationDialogForTask * * @param pkgName The package whose activity must be top * @param uid The uid that must have a top activity * @return a task ID if a valid task ID is found. Otherwise, return INVALID_TASK_ID */ public abstract int getTaskToShowPermissionDialogOn(String pkgName, int uid); } services/core/java/com/android/server/wm/ActivityTaskManagerService.java +8 −0 Original line number Diff line number Diff line Loading @@ -6754,5 +6754,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } return tasks; } @Override public int getTaskToShowPermissionDialogOn(String pkgName, int uid) { synchronized (ActivityTaskManagerService.this.mGlobalLock) { return ActivityTaskManagerService.this.mRootWindowContainer .getTaskToShowPermissionDialogOn(pkgName, uid); } } } } Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +5 −13 Original line number Diff line number Diff line Loading @@ -3746,6 +3746,10 @@ public class NotificationManagerService extends SystemService { if (!hadChannel && hasChannel && !hasRequestedNotificationPermission && startingTaskId != ActivityTaskManager.INVALID_TASK_ID) { hasRequestedNotificationPermission = true; if (mPermissionPolicyInternal == null) { mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); } mHandler.post(new ShowNotificationPermissionPromptRunnable(pkg, UserHandle.getUserId(uid), startingTaskId, mPermissionPolicyInternal)); Loading @@ -3764,19 +3768,7 @@ public class NotificationManagerService extends SystemService { try { int uid = mPackageManager.getPackageUid(pkg, 0, UserHandle.getUserId(Binder.getCallingUid())); List<ActivityManager.AppTask> tasks = mAtm.getAppTasks(pkg, uid); for (int i = 0; i < tasks.size(); i++) { ActivityManager.RecentTaskInfo task = tasks.get(i).getTaskInfo(); if (mPermissionPolicyInternal == null) { mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class); } if (mPermissionPolicyInternal != null && mPermissionPolicyInternal.canShowPermissionPromptForTask(task)) { taskId = task.taskId; break; } } taskId = mAtm.getTaskToShowPermissionDialogOn(pkg, uid); } catch (RemoteException e) { // Do nothing } Loading
services/core/java/com/android/server/policy/PermissionPolicyInternal.java +15 −2 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ public abstract class PermissionPolicyInternal { * prompt should be shown if the app targets S-, is currently running in a visible, focused * task, has the REVIEW_REQUIRED flag set on its implicit notification permission, and has * created at least one notification channel (even if it has since been deleted). * * @param packageName The package whose permission is being checked * @param userId The user for whom the package is being started * @param taskId The task the notification prompt should be attached to Loading @@ -66,10 +67,22 @@ public abstract class PermissionPolicyInternal { /** * Determine if a particular task is in the proper state to show a system-triggered permission * prompt. A prompt can be shown if the task is focused, visible, and running. * prompt. A prompt can be shown if the task is focused, visible, and running and * 1. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER), or * 2. The activity belongs to the same package as the one which launched the task originally, * and the task was started with a launcher intent * * @param taskInfo The task to be checked * @param currPkg The package of the current top visible activity * @param intent The intent of the current top visible activity */ public abstract boolean shouldShowNotificationDialogForTask(@Nullable TaskInfo taskInfo, @Nullable String currPkg, @Nullable Intent intent); /** * @return true if an intent will resolve to a permission request dialog activity */ public abstract boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo); public abstract boolean isIntentToPermissionDialog(@NonNull Intent intent); /** * @return Whether the policy is initialized for a user. Loading
services/core/java/com/android/server/policy/PermissionPolicyService.java +45 −19 Original line number Diff line number Diff line Loading @@ -21,6 +21,8 @@ import static android.app.AppOpsManager.MODE_ALLOWED; import static android.app.AppOpsManager.MODE_FOREGROUND; import static android.app.AppOpsManager.MODE_IGNORED; import static android.app.AppOpsManager.OP_NONE; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER; import static android.content.pm.PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED; import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT; Loading Loading @@ -1016,7 +1018,7 @@ public final class PermissionPolicyService extends SystemService { ActivityInterceptorInfo info) { String action = info.intent.getAction(); ActivityInterceptResult result = null; if (!PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action) if (!ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action) && !PackageManager.ACTION_REQUEST_PERMISSIONS.equals(action)) { return null; } Loading @@ -1033,7 +1035,7 @@ public final class PermissionPolicyService extends SystemService { && !mContinueNotifGrantMessageUids.contains(info.realCallingUid)) { return result; } if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)) { if (ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)) { String otherPkg = info.intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME); if (otherPkg == null || (mPackageManager.getPermissionFlags( POST_NOTIFICATIONS, otherPkg, UserHandle.of(info.userId)) Loading @@ -1052,8 +1054,8 @@ public final class PermissionPolicyService extends SystemService { public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo, ActivityInterceptorInfo info) { super.onActivityLaunched(taskInfo, activityInfo, info); if (!shouldShowNotificationDialogOrClearFlags(info.intent, info.checkedOptions)) { if (!shouldShowNotificationDialogOrClearFlags(taskInfo, activityInfo.packageName, info.intent, info.checkedOptions, true)) { return; } UserHandle user = UserHandle.of(taskInfo.userId); Loading Loading @@ -1085,7 +1087,7 @@ public final class PermissionPolicyService extends SystemService { return false; } if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(intent.getAction()) if (ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(intent.getAction()) && (callingUid != Process.SYSTEM_UID || !SYSTEM_PKG.equals(callingPackage))) { return false; } Loading @@ -1104,18 +1106,48 @@ public final class PermissionPolicyService extends SystemService { launchNotificationPermissionRequestDialog(packageName, user, taskId); } @Override public boolean isIntentToPermissionDialog(@NonNull Intent intent) { return Objects.equals(intent.getPackage(), mPackageManager.getPermissionControllerPackageName()) && (Objects.equals(intent.getAction(), ACTION_REQUEST_PERMISSIONS_FOR_OTHER) || Objects.equals(intent.getAction(), ACTION_REQUEST_PERMISSIONS)); } @Override public boolean shouldShowNotificationDialogForTask(TaskInfo taskInfo, String currPkg, Intent intent) { return shouldShowNotificationDialogOrClearFlags( taskInfo, currPkg, intent, null, false); } /** * Determine if we should show a notification dialog, or clear the REVIEW_REQUIRED flag, * from a particular package for a particular intent. Returns true if: * Determine if a particular task is in the proper state to show a system-triggered * permission prompt. A prompt can be shown if the task is just starting, or the task is * currently focused, visible, and running, and, * 1. The isEligibleForLegacyPermissionPrompt ActivityOption is set, or * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER) * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER), or * 3. The activity belongs to the same package as the one which launched the task * originally, and the task was started with a launcher intent * @param taskInfo The task to be checked * @param currPkg The package of the current top visible activity * @param intent The intent of the current top visible activity */ private boolean shouldShowNotificationDialogOrClearFlags(Intent intent, ActivityOptions options) { if ((options != null && options.isEligibleForLegacyPermissionPrompt())) { return true; private boolean shouldShowNotificationDialogOrClearFlags(TaskInfo taskInfo, String currPkg, Intent intent, ActivityOptions options, boolean activityStart) { if (intent == null || currPkg == null || taskInfo == null || (!(taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning) && !activityStart)) { return false; } return isLauncherIntent(intent) || (options != null && options.isEligibleForLegacyPermissionPrompt()) || (currPkg.equals(taskInfo.baseActivity.getPackageName()) && isLauncherIntent(taskInfo.baseIntent)); } private boolean isLauncherIntent(Intent intent) { return Intent.ACTION_MAIN.equals(intent.getAction()) && intent.getCategories() != null && (intent.getCategories().contains(Intent.CATEGORY_LAUNCHER) Loading Loading @@ -1144,7 +1176,7 @@ public final class PermissionPolicyService extends SystemService { Intent grantPermission = mPackageManager .buildRequestPermissionsIntent(new String[] { POST_NOTIFICATIONS }); grantPermission.setAction( PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER); ACTION_REQUEST_PERMISSIONS_FOR_OTHER); grantPermission.putExtra(Intent.EXTRA_PACKAGE_NAME, pkgName); ActivityOptions options = new ActivityOptions(new Bundle()); Loading @@ -1170,12 +1202,6 @@ public final class PermissionPolicyService extends SystemService { } } @Override public boolean canShowPermissionPromptForTask(@Nullable TaskInfo taskInfo) { return taskInfo != null && taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning; } /** * Check if the intent action is removed for the calling package (often based on target SDK * version). If the action is removed, we'll silently cancel the activity launch. Loading
services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java +11 −0 Original line number Diff line number Diff line Loading @@ -680,4 +680,15 @@ public abstract class ActivityTaskManagerInternal { /** Get the app tasks for a package */ public abstract List<ActivityManager.AppTask> getAppTasks(String pkgName, int uid); /** * Determine if there exists a task which meets the criteria set by the PermissionPolicyService * to show a system-owned permission dialog over, for a given package * @see PermissionPolicyInternal.shouldShowNotificationDialogForTask * * @param pkgName The package whose activity must be top * @param uid The uid that must have a top activity * @return a task ID if a valid task ID is found. Otherwise, return INVALID_TASK_ID */ public abstract int getTaskToShowPermissionDialogOn(String pkgName, int uid); }
services/core/java/com/android/server/wm/ActivityTaskManagerService.java +8 −0 Original line number Diff line number Diff line Loading @@ -6754,5 +6754,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } return tasks; } @Override public int getTaskToShowPermissionDialogOn(String pkgName, int uid) { synchronized (ActivityTaskManagerService.this.mGlobalLock) { return ActivityTaskManagerService.this.mRootWindowContainer .getTaskToShowPermissionDialogOn(pkgName, uid); } } } }