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

Commit 2903f3d5 authored by Hani Kazmi's avatar Hani Kazmi Committed by Cherrypicker Worker
Browse files

Update ASM clear task to only conisder present DisplayArea

If a task is not associated with a DisplayArea, that could throw a NPE.
We now exit early if that is the case.

Extrated the ASM logic to a separate method to make it easier to follow,
and minor updates to logging to match activity starts.

Bug: 270118065
Test: atest CtsAppTestCases
Change-Id: Iabd7c7c3ca503c354014e4fe73d449570cf4ceb5
(cherry picked from commit 6e9e524b)
Merged-In: Iabd7c7c3ca503c354014e4fe73d449570cf4ceb5
parent edb6afca
Loading
Loading
Loading
Loading
+3 −12
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
import static com.android.server.wm.ActivityTaskSupervisor.getApplicationLabel;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_COMPONENT;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ALLOWLISTED_UID;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT;
@@ -2017,7 +2018,8 @@ class ActivityStarter {
        if (ActivitySecurityModelFeatureFlags.shouldShowToast(mCallingUid)) {
            String toastText = ActivitySecurityModelFeatureFlags.DOC_LINK
                    + (blockActivityStartAndFeatureEnabled ? " blocked " : " would block ")
                    + getApplicationLabel(launchedFromPackageName);
                    + getApplicationLabel(mService.mContext.getPackageManager(),
                        launchedFromPackageName);
            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                    toastText, Toast.LENGTH_LONG).show());

@@ -2039,17 +2041,6 @@ class ActivityStarter {
        return true;
    }

    private CharSequence getApplicationLabel(String packageName) {
        try {
            PackageManager packageManager = mService.mContext.getPackageManager();
            ApplicationInfo launchedFromPackageInfo = packageManager.getApplicationInfo(
                    packageName, PackageManager.ApplicationInfoFlags.of(0));
            return packageManager.getApplicationLabel(launchedFromPackageInfo);
        } catch (PackageManager.NameNotFoundException e) {
            return packageName;
        }
    }

    /** Only called when an activity launch may be blocked, which should happen very rarely */
    private void logDebugInfoForActivitySecurity(String action, ActivityRecord r, Task targetTask,
            ActivityRecord targetTopActivity, boolean blockActivityStartAndFeatureEnabled,
+106 −69
Original line number Diff line number Diff line
@@ -1635,20 +1635,50 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            // Prevent recursion.
            return;
        }
        boolean shouldBlockActivitySwitchIfFeatureEnabled = false;
        boolean wouldBlockActivitySwitchIgnoringFlags = false;
        task.mTransitionController.requestCloseTransitionIfNeeded(task);
        task.mInRemoveTask = true;
        try {
            task.removeActivities(reason, false /* excludingTaskOverlay */);
            cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents);
            mService.getLockTaskController().clearLockedTask(task);
            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
            if (task.isPersistable) {
                mService.notifyTaskPersisterLocked(null, true);
            }
            checkActivitySecurityForTaskClear(callingUid, task, callerActivityClassName);
        } finally {
            task.mInRemoveTask = false;
        }
    }

    // TODO(b/263368846) Move to live with the rest of the ASM logic.
    /**
     * Returns home if the passed in callingUid is not top of the stack, rather than returning to
     * previous task.
     */
    private void checkActivitySecurityForTaskClear(int callingUid, Task task,
            String callerActivityClassName) {
        // We may have already checked that the callingUid has additional clearTask privileges, and
        // cleared the calling identify. If so, we infer we do not need further restrictions here.
        // TODO(b/263368846) Move to live with the rest of the ASM logic.
        if (callingUid != SYSTEM_UID) {
            Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task,
                    callingUid,
                    null);
            shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
            wouldBlockActivitySwitchIgnoringFlags = !pair.second;
            if (wouldBlockActivitySwitchIgnoringFlags) {
                ActivityRecord topActivity =  task.getActivity(ar ->
                        !ar.finishing && !ar.isAlwaysOnTop());
        if (callingUid == SYSTEM_UID) {
            return;
        }

        TaskDisplayArea displayArea = task.getTaskDisplayArea();
        if (displayArea == null) {
            // If there is no associated display area, we can not return home.
            return;
        }

        Pair<Boolean, Boolean> pair = doesTopActivityMatchingUidExistForAsm(task, callingUid, null);
        boolean shouldBlockActivitySwitchIfFeatureEnabled = !pair.first;
        boolean wouldBlockActivitySwitchIgnoringFlags = !pair.second;

        if (!wouldBlockActivitySwitchIgnoringFlags) {
            return;
        }

        ActivityRecord topActivity = task.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
        FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
                /* caller_uid */
                callingUid,
@@ -1677,47 +1707,44 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
                /* bal_code */
                -1
        );
            }
        }
        task.mTransitionController.requestCloseTransitionIfNeeded(task);
        task.mInRemoveTask = true;
        try {
            task.removeActivities(reason, false /* excludingTaskOverlay */);
            cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents);
            mService.getLockTaskController().clearLockedTask(task);
            mService.getTaskChangeNotificationController().notifyTaskStackChanged();
            if (task.isPersistable) {
                mService.notifyTaskPersisterLocked(null, true);
            }
            if (wouldBlockActivitySwitchIgnoringFlags) {

        boolean restrictActivitySwitch = ActivitySecurityModelFeatureFlags
                .shouldRestrictActivitySwitch(callingUid)
                && shouldBlockActivitySwitchIfFeatureEnabled;

        PackageManager pm = mService.mContext.getPackageManager();
        String callingPackage = pm.getNameForUid(callingUid);
        final CharSequence callingLabel;
        if (callingPackage == null) {
            callingPackage = String.valueOf(callingUid);
            callingLabel = callingPackage;
        } else {
            callingLabel = getApplicationLabel(pm, callingPackage);
        }

        if (ActivitySecurityModelFeatureFlags.shouldShowToast(callingUid)) {
                    UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                            (restrictActivitySwitch
                                    ? "Returning home due to "
                                    : "Would return home due to ")
                                    + ActivitySecurityModelFeatureFlags.DOC_LINK,
                            Toast.LENGTH_LONG).show());
            Toast toast = Toast.makeText(mService.mContext,
                    (ActivitySecurityModelFeatureFlags.DOC_LINK
                            + (restrictActivitySwitch
                            ? "returned home due to "
                            : "would return home due to ")
                            + callingLabel),
                    Toast.LENGTH_LONG);
            UiThread.getHandler().post(toast::show);
        }

        // If the activity switch should be restricted, return home rather than the
        // previously top task, to prevent users from being confused which app they're
        // viewing
        if (restrictActivitySwitch) {
                    Slog.w(TAG, "[ASM] Return to home as source uid: " + callingUid
            Slog.w(TAG, "[ASM] Return to home as source: " + callingPackage
                    + " is not on top of task t: " + task);
                    task.getTaskDisplayArea().moveHomeActivityToTop("taskRemoved");
            displayArea.moveHomeActivityToTop("taskRemoved");
        } else {
                    Slog.i(TAG, "[ASM] Would return to home as source uid: " + callingUid
            Slog.i(TAG, "[ASM] Would return to home as source: " + callingPackage
                    + " is not on top of task t: " + task);
        }
    }
        } finally {
            task.mInRemoveTask = false;
        }
    }

    /**
     *  For the purpose of ASM, ‘Top UID” for a task is defined as an activity UID
@@ -1779,6 +1806,16 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        return topActivity.allowCrossUidActivitySwitchFromBelow(uid);
    }

    static CharSequence getApplicationLabel(PackageManager pm, String packageName) {
        try {
            ApplicationInfo launchedFromPackageInfo = pm.getApplicationInfo(
                    packageName, PackageManager.ApplicationInfoFlags.of(0));
            return pm.getApplicationLabel(launchedFromPackageInfo);
        } catch (PackageManager.NameNotFoundException e) {
            return packageName;
        }
    }

    void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) {
        if (removeFromRecents) {
            mRecentTasks.remove(task);