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

Commit 51499d41 authored by Nate Myren's avatar Nate Myren Committed by Automerger Merge Worker
Browse files

Merge "Show Notification Permission dialog on (some) task trampolines" into tm-dev am: 7585a958

parents 327b98c7 7585a958
Loading
Loading
Loading
Loading
+4 −1
Original line number Original line Diff line number Diff line
@@ -74,10 +74,13 @@ public abstract class PermissionPolicyInternal {
     *
     *
     * @param taskInfo The task to be checked
     * @param taskInfo The task to be checked
     * @param currPkg The package of the current top visible activity
     * @param currPkg The package of the current top visible activity
     * @param callingPkg The package that started the top visible activity
     * @param intent The intent of the current top visible activity
     * @param intent The intent of the current top visible activity
     * @param activityName The name of the current top visible activity
     */
     */
    public abstract boolean shouldShowNotificationDialogForTask(@Nullable TaskInfo taskInfo,
    public abstract boolean shouldShowNotificationDialogForTask(@Nullable TaskInfo taskInfo,
            @Nullable String currPkg, @Nullable Intent intent);
            @Nullable String currPkg, @Nullable String callingPkg, @Nullable Intent intent,
            @NonNull String activityName);


    /**
    /**
     * @return true if an intent will resolve to a permission request dialog activity
     * @return true if an intent will resolve to a permission request dialog activity
+56 −11
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager;
@@ -1166,7 +1167,8 @@ public final class PermissionPolicyService extends SystemService {
                            ActivityInterceptorInfo info) {
                            ActivityInterceptorInfo info) {
                        super.onActivityLaunched(taskInfo, activityInfo, info);
                        super.onActivityLaunched(taskInfo, activityInfo, info);
                        if (!shouldShowNotificationDialogOrClearFlags(taskInfo,
                        if (!shouldShowNotificationDialogOrClearFlags(taskInfo,
                                activityInfo.packageName, info.intent, info.checkedOptions, true)
                                activityInfo.packageName, info.callingPackage, info.intent,
                                info.checkedOptions, activityInfo.name, true)
                                || isNoDisplayActivity(activityInfo)) {
                                || isNoDisplayActivity(activityInfo)) {
                            return;
                            return;
                        }
                        }
@@ -1237,9 +1239,9 @@ public final class PermissionPolicyService extends SystemService {


        @Override
        @Override
        public boolean shouldShowNotificationDialogForTask(TaskInfo taskInfo, String currPkg,
        public boolean shouldShowNotificationDialogForTask(TaskInfo taskInfo, String currPkg,
                Intent intent) {
                String callingPkg, Intent intent, String activityName) {
            return shouldShowNotificationDialogOrClearFlags(
            return shouldShowNotificationDialogOrClearFlags(taskInfo, currPkg, callingPkg, intent,
                    taskInfo, currPkg, intent, null, false);
                    null, activityName, false);
        }
        }


        private boolean isNoDisplayActivity(@NonNull ActivityInfo aInfo) {
        private boolean isNoDisplayActivity(@NonNull ActivityInfo aInfo) {
@@ -1265,23 +1267,61 @@ public final class PermissionPolicyService extends SystemService {
         * 1. The isEligibleForLegacyPermissionPrompt ActivityOption is set, or
         * 1. The isEligibleForLegacyPermissionPrompt ActivityOption is set, or
         * 2. The intent is a launcher intent (action is ACTION_MAIN, category is LAUNCHER), or
         * 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
         * 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
         * originally, and the task was started with a launcher intent, or
         * 4. The activity is the first activity in a new task, and was started by the app the
         * activity belongs to, and that app has another task that is currently focused, which was
         * started with a launcher intent. This case seeks to identify cases where an app launches,
         * then immediately trampolines to a new activity and task.
         * @param taskInfo The task to be checked
         * @param taskInfo The task to be checked
         * @param currPkg The package of the current top visible activity
         * @param currPkg The package of the current top visible activity
         * @param callingPkg The package that initiated this dialog action
         * @param intent The intent of the current top visible activity
         * @param intent The intent of the current top visible activity
         * @param options The ActivityOptions of the newly started activity, if this is called due
         *                to an activity start
         * @param startedActivity The ActivityInfo of the newly started activity, if this is called
         *                        due to an activity start
         */
         */
        private boolean shouldShowNotificationDialogOrClearFlags(TaskInfo taskInfo, String currPkg,
        private boolean shouldShowNotificationDialogOrClearFlags(TaskInfo taskInfo, String currPkg,
                Intent intent, ActivityOptions options, boolean activityStart) {
                String callingPkg, Intent intent, ActivityOptions options,
            if (intent == null || currPkg == null || taskInfo == null
                String topActivityName, boolean startedActivity) {
            if (intent == null || currPkg == null || taskInfo == null || topActivityName == null
                    || (!(taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning)
                    || (!(taskInfo.isFocused && taskInfo.isVisible && taskInfo.isRunning)
                    && !activityStart)) {
                    && !startedActivity)) {
                return false;
                return false;
            }
            }

            return isLauncherIntent(intent)
            return isLauncherIntent(intent)
                    || (options != null && options.isEligibleForLegacyPermissionPrompt())
                    || (options != null && options.isEligibleForLegacyPermissionPrompt())
                    || (currPkg.equals(taskInfo.baseActivity.getPackageName())
                    || isTaskStartedFromLauncher(currPkg, taskInfo)
                    && isLauncherIntent(taskInfo.baseIntent));
                    || (isTaskPotentialTrampoline(topActivityName, currPkg, callingPkg, taskInfo,
                    intent)
                    && (!startedActivity || pkgHasRunningLauncherTask(currPkg, taskInfo)));
        }

        private boolean isTaskPotentialTrampoline(String activityName, String currPkg,
                String callingPkg, TaskInfo taskInfo, Intent intent) {
            return currPkg.equals(callingPkg) && taskInfo.baseIntent.filterEquals(intent)
                    && taskInfo.numActivities == 1
                    && activityName.equals(taskInfo.topActivityInfo.name);
        }

        private boolean pkgHasRunningLauncherTask(String currPkg, TaskInfo taskInfo) {
            ActivityTaskManagerInternal m =
                    LocalServices.getService(ActivityTaskManagerInternal.class);
            try {
                // TODO(b/230616478) Investigate alternatives like ActivityMetricsLaunchObserver
                List<ActivityManager.AppTask> tasks =
                        m.getAppTasks(currPkg, mPackageManager.getPackageUid(currPkg, 0));
                for (int i = 0; i < tasks.size(); i++) {
                    TaskInfo other = tasks.get(i).getTaskInfo();
                    if (other.taskId != taskInfo.taskId && other.isFocused && other.isRunning
                            && isTaskStartedFromLauncher(currPkg, other)) {
                        return true;
                    }
                }
            } catch (PackageManager.NameNotFoundException e) {
                // Fall through
            }
            return false;
        }
        }


        private boolean isLauncherIntent(Intent intent) {
        private boolean isLauncherIntent(Intent intent) {
@@ -1292,6 +1332,11 @@ public final class PermissionPolicyService extends SystemService {
                    || intent.getCategories().contains(Intent.CATEGORY_CAR_LAUNCHER));
                    || intent.getCategories().contains(Intent.CATEGORY_CAR_LAUNCHER));
        }
        }


        private boolean isTaskStartedFromLauncher(String currPkg, TaskInfo taskInfo) {
            return currPkg.equals(taskInfo.baseActivity.getPackageName())
                    && isLauncherIntent(taskInfo.baseIntent);
        }

        private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle user) {
        private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle user) {
            if ((mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, packageName, user)
            if ((mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, packageName, user)
                    & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
                    & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
+9 −7
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@ import android.os.Binder;
import android.os.Bundle;
import android.os.Bundle;
import android.os.IBinder;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserHandle;


@@ -48,8 +49,9 @@ class AppTaskImpl extends IAppTask.Stub {
        mCallingUid = callingUid;
        mCallingUid = callingUid;
    }
    }


    private void checkCaller() {
    private void checkCallerOrSystemOrRoot() {
        if (mCallingUid != Binder.getCallingUid()) {
        if (mCallingUid != Binder.getCallingUid() && Process.SYSTEM_UID != Binder.getCallingUid()
                && Process.ROOT_UID != Binder.getCallingUid()) {
            throw new SecurityException("Caller " + mCallingUid
            throw new SecurityException("Caller " + mCallingUid
                    + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
                    + " does not match caller of getAppTasks(): " + Binder.getCallingUid());
        }
        }
@@ -67,7 +69,7 @@ class AppTaskImpl extends IAppTask.Stub {


    @Override
    @Override
    public void finishAndRemoveTask() {
    public void finishAndRemoveTask() {
        checkCaller();
        checkCallerOrSystemOrRoot();


        synchronized (mService.mGlobalLock) {
        synchronized (mService.mGlobalLock) {
            final long origId = Binder.clearCallingIdentity();
            final long origId = Binder.clearCallingIdentity();
@@ -85,7 +87,7 @@ class AppTaskImpl extends IAppTask.Stub {


    @Override
    @Override
    public ActivityManager.RecentTaskInfo getTaskInfo() {
    public ActivityManager.RecentTaskInfo getTaskInfo() {
        checkCaller();
        checkCallerOrSystemOrRoot();


        synchronized (mService.mGlobalLock) {
        synchronized (mService.mGlobalLock) {
            final long origId = Binder.clearCallingIdentity();
            final long origId = Binder.clearCallingIdentity();
@@ -105,7 +107,7 @@ class AppTaskImpl extends IAppTask.Stub {


    @Override
    @Override
    public void moveToFront(IApplicationThread appThread, String callingPackage) {
    public void moveToFront(IApplicationThread appThread, String callingPackage) {
        checkCaller();
        checkCallerOrSystemOrRoot();
        // Will bring task to front if it already has a root activity.
        // Will bring task to front if it already has a root activity.
        final int callingPid = Binder.getCallingPid();
        final int callingPid = Binder.getCallingPid();
        final int callingUid = Binder.getCallingUid();
        final int callingUid = Binder.getCallingUid();
@@ -136,7 +138,7 @@ class AppTaskImpl extends IAppTask.Stub {
    @Override
    @Override
    public int startActivity(IBinder whoThread, String callingPackage, String callingFeatureId,
    public int startActivity(IBinder whoThread, String callingPackage, String callingFeatureId,
            Intent intent, String resolvedType, Bundle bOptions) {
            Intent intent, String resolvedType, Bundle bOptions) {
        checkCaller();
        checkCallerOrSystemOrRoot();
        mService.assertPackageMatchesCallingUid(callingPackage);
        mService.assertPackageMatchesCallingUid(callingPackage);


        int callingUser = UserHandle.getCallingUserId();
        int callingUser = UserHandle.getCallingUserId();
@@ -167,7 +169,7 @@ class AppTaskImpl extends IAppTask.Stub {


    @Override
    @Override
    public void setExcludeFromRecents(boolean exclude) {
    public void setExcludeFromRecents(boolean exclude) {
        checkCaller();
        checkCallerOrSystemOrRoot();


        synchronized (mService.mGlobalLock) {
        synchronized (mService.mGlobalLock) {
            final long origId = Binder.clearCallingIdentity();
            final long origId = Binder.clearCallingIdentity();
+1 −1
Original line number Original line Diff line number Diff line
@@ -3382,7 +3382,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
            if (record != null && record.isUid(uid)
            if (record != null && record.isUid(uid)
                    && Objects.equals(pkgName, record.packageName)
                    && Objects.equals(pkgName, record.packageName)
                    && pPi.shouldShowNotificationDialogForTask(record.getTask().getTaskInfo(),
                    && pPi.shouldShowNotificationDialogForTask(record.getTask().getTaskInfo(),
                    pkgName, record.intent)) {
                    pkgName, record.launchedFromPackage, record.intent, record.getName())) {
                validTaskId[0] = record.getTask().mTaskId;
                validTaskId[0] = record.getTask().mTaskId;
                return true;
                return true;
            }
            }