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

Commit c4293b56 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Restrict what activity launches show permission prompts" into tm-dev

parents 1cb90227 eb4e3d20
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -155,8 +155,10 @@ package android.app {

  public class ActivityOptions {
    method @NonNull public static android.app.ActivityOptions fromBundle(@NonNull android.os.Bundle);
    method public boolean isEligibleForLegacyPermissionPrompt();
    method @NonNull public static android.app.ActivityOptions makeCustomAnimation(@NonNull android.content.Context, int, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
    method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
    method public void setEligibleForLegacyPermissionPrompt(boolean);
    method public static void setExitTransitionTimeout(long);
    method public void setLaunchActivityType(int);
    method public void setLaunchWindowingMode(int);
+33 −0
Original line number Diff line number Diff line
@@ -173,6 +173,13 @@ public class ActivityOptions extends ComponentOptions {
     */
    public static final String KEY_SPLASH_SCREEN_THEME = "android.activity.splashScreenTheme";

    /**
     * Indicates that this activity launch is eligible to show a legacy permission prompt
     * @hide
     */
    public static final String KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE =
            "android:activity.legacyPermissionPromptEligible";

    /**
     * Callback for when the last frame of the animation is played.
     * @hide
@@ -445,6 +452,7 @@ public class ActivityOptions extends ComponentOptions {
    private String mSplashScreenThemeResName;
    @SplashScreen.SplashScreenStyle
    private int mSplashScreenStyle = SplashScreen.SPLASH_SCREEN_STYLE_UNDEFINED;
    private boolean mIsEligibleForLegacyPermissionPrompt;
    private boolean mRemoveWithTaskOrganizer;
    private boolean mLaunchedFromBubble;
    private boolean mTransientLaunch;
@@ -1243,6 +1251,8 @@ public class ActivityOptions extends ComponentOptions {
        mTransientLaunch = opts.getBoolean(KEY_TRANSIENT_LAUNCH);
        mSplashScreenStyle = opts.getInt(KEY_SPLASH_SCREEN_STYLE);
        mLaunchIntoPipParams = opts.getParcelable(KEY_LAUNCH_INTO_PIP_PARAMS);
        mIsEligibleForLegacyPermissionPrompt =
                opts.getBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE);
    }

    /**
@@ -1473,6 +1483,24 @@ public class ActivityOptions extends ComponentOptions {
        return this;
    }

    /**
     * Whether the activity is eligible to show a legacy permission prompt
     * @hide
     */
    @TestApi
    public boolean isEligibleForLegacyPermissionPrompt() {
        return mIsEligibleForLegacyPermissionPrompt;
    }

    /**
     * Sets whether the activity is eligible to show a legacy permission prompt
     * @hide
     */
    @TestApi
    public void setEligibleForLegacyPermissionPrompt(boolean eligible) {
        mIsEligibleForLegacyPermissionPrompt = eligible;
    }

    /**
     * Sets whether the activity is to be launched into LockTask mode.
     *
@@ -1909,6 +1937,7 @@ public class ActivityOptions extends ComponentOptions {
        mSpecsFuture = otherOptions.mSpecsFuture;
        mRemoteAnimationAdapter = otherOptions.mRemoteAnimationAdapter;
        mLaunchIntoPipParams = otherOptions.mLaunchIntoPipParams;
        mIsEligibleForLegacyPermissionPrompt = otherOptions.mIsEligibleForLegacyPermissionPrompt;
    }

    /**
@@ -2084,6 +2113,10 @@ public class ActivityOptions extends ComponentOptions {
        if (mLaunchIntoPipParams != null) {
            b.putParcelable(KEY_LAUNCH_INTO_PIP_PARAMS, mLaunchIntoPipParams);
        }
        if (mIsEligibleForLegacyPermissionPrompt) {
            b.putBoolean(KEY_LEGACY_PERMISSION_PROMPT_ELIGIBLE,
                    mIsEligibleForLegacyPermissionPrompt);
        }
        return b;
    }

+8 −2
Original line number Diff line number Diff line
@@ -3972,8 +3972,14 @@ public class CentralSurfaces extends CoreStartable implements

                mActivityLaunchAnimator.startPendingIntentWithAnimation(
                        controller, animate, intent.getCreatorPackage(),
                        (animationAdapter) -> intent.sendAndReturnResult(null, 0, null, null, null,
                                null, getActivityOptions(mDisplayId, animationAdapter)));
                        (animationAdapter) -> {
                            ActivityOptions options = new ActivityOptions(
                                    getActivityOptions(mDisplayId, animationAdapter));
                            // TODO b/221255671: restrict this to only be set for notifications
                            options.setEligibleForLegacyPermissionPrompt(true);
                            return intent.sendAndReturnResult(null, 0, null, null, null,
                                    null, options.toBundle());
                        });
            } catch (PendingIntent.CanceledException e) {
                // the stack trace isn't very helpful here.
                // Just log the exception message.
+42 −12
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.AppOpsManagerInternal;
import android.app.KeyguardManager;
import android.app.TaskInfo;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
@@ -150,6 +151,7 @@ public final class PermissionPolicyService extends SystemService {
    private Context mContext;
    private PackageManagerInternal mPackageManagerInternal;
    private NotificationManagerInternal mNotificationManager;
    private final KeyguardManager mKeyguardManager;
    private final PackageManager mPackageManager;

    public PermissionPolicyService(@NonNull Context context) {
@@ -157,6 +159,7 @@ public final class PermissionPolicyService extends SystemService {

        mContext = context;
        mPackageManager = context.getPackageManager();
        mKeyguardManager = context.getSystemService(KeyguardManager.class);
        LocalServices.addService(PermissionPolicyInternal.class, new Internal());
    }

@@ -1046,13 +1049,22 @@ public final class PermissionPolicyService extends SystemService {
                    }

                    @Override
                    public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo) {
                        super.onActivityLaunched(taskInfo, activityInfo);
                        clearNotificationReviewFlagsIfNeeded(activityInfo.packageName,
                                UserHandle.of(taskInfo.userId));
                    public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo,
                            ActivityInterceptorInfo info) {
                        super.onActivityLaunched(taskInfo, activityInfo, info);
                        if (!shouldShowNotificationDialogOrClearFlags(info.intent,
                                info.checkedOptions)) {
                            return;
                        }
                        UserHandle user = UserHandle.of(taskInfo.userId);
                        if (CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID,
                                activityInfo.packageName, user)) {
                            clearNotificationReviewFlagsIfNeeded(activityInfo.packageName, user);
                        } else {
                            showNotificationPromptIfNeeded(activityInfo.packageName,
                                    taskInfo.userId, taskInfo.taskId);
                        }
                    }
                };

        private void onActivityManagerReady() {
@@ -1092,10 +1104,28 @@ public final class PermissionPolicyService extends SystemService {
            launchNotificationPermissionRequestDialog(packageName, user, taskId);
        }

        /**
         * 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:
         * 1. The isEligibleForLegacyPermissionPrompt ActivityOption is set, or
         * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER)
         */
        private boolean shouldShowNotificationDialogOrClearFlags(Intent intent,
                ActivityOptions options) {
            if ((options != null && options.isEligibleForLegacyPermissionPrompt())) {
                return true;
            }

            return Intent.ACTION_MAIN.equals(intent.getAction())
                    && intent.getCategories() != null
                    && (intent.getCategories().contains(Intent.CATEGORY_LAUNCHER)
                    || intent.getCategories().contains(Intent.CATEGORY_LEANBACK_LAUNCHER)
                    || intent.getCategories().contains(Intent.CATEGORY_CAR_LAUNCHER));
        }

        private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle user) {
            if (!CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID, packageName, user)
                    || ((mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, packageName, user)
                    & FLAG_PERMISSION_REVIEW_REQUIRED) == 0)) {
            if ((mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, packageName, user)
                    & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
                return;
            }
            try {
@@ -1210,8 +1240,8 @@ public final class PermissionPolicyService extends SystemService {
            }

            if (!pkg.getRequestedPermissions().contains(POST_NOTIFICATIONS)
                    || CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID,
                    pkg.getPackageName(), user)) {
                    || CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID, pkgName, user)
                    || mKeyguardManager.isKeyguardLocked()) {
                return false;
            }

@@ -1220,7 +1250,7 @@ public final class PermissionPolicyService extends SystemService {
                mNotificationManager = LocalServices.getService(NotificationManagerInternal.class);
            }
            boolean hasCreatedNotificationChannels = mNotificationManager
                    .getNumNotificationChannelsForPackage(pkg.getPackageName(), uid, true) > 0;
                    .getNumNotificationChannelsForPackage(pkgName, uid, true) > 0;
            int flags = mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, pkgName, user);
            boolean explicitlySet = (flags & PermissionManager.EXPLICIT_SET_FLAGS) != 0;
            boolean needsReview = (flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
+6 −2
Original line number Diff line number Diff line
@@ -43,9 +43,13 @@ public abstract class ActivityInterceptorCallback {
    public abstract @Nullable ActivityInterceptResult intercept(ActivityInterceptorInfo info);

    /**
     * Called when an activity is successfully launched.
     * Called when an activity is successfully launched. The intent included in the
     * ActivityInterceptorInfo may have changed from the one sent in
     * {@link #intercept(ActivityInterceptorInfo)}, due to the return from
     * {@link #intercept(ActivityInterceptorInfo)}.
     */
    public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo) {
    public void onActivityLaunched(TaskInfo taskInfo, ActivityInfo activityInfo,
            ActivityInterceptorInfo info) {
    }

    /**
Loading