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

Commit 76ed84a5 authored by Nate Myren's avatar Nate Myren Committed by Android (Google) Code Review
Browse files

Merge "Check all tasks for good intent launch when creating channels" into tm-dev

parents ea151cda 0c99b791
Loading
Loading
Loading
Loading
+5 −13
Original line number Diff line number Diff line
@@ -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));
@@ -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
            }
+15 −2
Original line number Diff line number Diff line
@@ -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
@@ -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.
+45 −19
Original line number Diff line number Diff line
@@ -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;
@@ -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;
                        }
@@ -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))
@@ -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);
@@ -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;
            }
@@ -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)
@@ -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());
@@ -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.
+11 −0
Original line number Diff line number Diff line
@@ -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);
}
+8 −0
Original line number Diff line number Diff line
@@ -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