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

Commit e8fda039 authored by Hani Kazmi's avatar Hani Kazmi Committed by Automerger Merge Worker
Browse files

ASM - Use finishing instead of isState() and more logging am: edb6afca

parents 377669b7 edb6afca
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ class ActivitySecurityModelFeatureFlags {
    // TODO(b/230590090): Replace with public documentation once ready
    static final String DOC_LINK = "go/android-asm";

    /** Used to determine which version of the ASM logic was used in logs while we iterate */
    static final int ASM_VERSION = 5;

    private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
    private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
    private static final String KEY_ASM_RESTRICTIONS_ENABLED = KEY_ASM_PREFIX
+99 −15
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TAS

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
@@ -83,6 +82,7 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_SAW_PERMISSION;
import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_VISIBLE_WINDOW;
import static com.android.server.wm.BackgroundActivityStartController.BAL_BLOCK;
import static com.android.server.wm.BackgroundActivityStartController.balCodeToString;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT;
@@ -150,6 +150,9 @@ import com.android.server.wm.TaskFragment.EmbeddingCheckResult;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

/**
@@ -1967,8 +1970,7 @@ class ActivityStarter {

        // ASM rules have failed. Log why
        ActivityRecord targetTopActivity = targetTask == null ? null
                : targetTask.getActivity(ar ->
                        !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
                : targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());

        int action = newTask || mSourceRecord == null
                ? FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__ACTIVITY_START_NEW_TASK
@@ -1999,7 +2001,7 @@ class ActivityStarter {
                /* action */
                action,
                /* version */
                4,
                ActivitySecurityModelFeatureFlags.ASM_VERSION,
                /* multi_window - we have our source not in the target task, but both are visible */
                targetTask != null && mSourceRecord != null
                        && !targetTask.equals(mSourceRecord.getTask()) && targetTask.isVisible(),
@@ -2011,22 +2013,25 @@ class ActivityStarter {
                    .shouldRestrictActivitySwitch(mCallingUid)
                && shouldBlockActivityStart;

        String launchedFromPackageName = r.launchedFromPackage;
        if (ActivitySecurityModelFeatureFlags.shouldShowToast(mCallingUid)) {
            String toastText = ActivitySecurityModelFeatureFlags.DOC_LINK
                    + (blockActivityStartAndFeatureEnabled ? " blocked " : " would block ")
                    + getApplicationLabel(launchedFromPackageName);
            UiThread.getHandler().post(() -> Toast.makeText(mService.mContext,
                    "Activity start from " + r.launchedFromPackage
                            + (blockActivityStartAndFeatureEnabled ? " " : " would be ")
                            + "blocked by " + ActivitySecurityModelFeatureFlags.DOC_LINK,
                    Toast.LENGTH_SHORT).show());
        }
                    toastText, Toast.LENGTH_LONG).show());

            logDebugInfoForActivitySecurity("Launch", r, targetTask, targetTopActivity,
                    blockActivityStartAndFeatureEnabled, /* taskToFront */ taskToFront);
        }

        if (blockActivityStartAndFeatureEnabled) {
            Slog.e(TAG, "Abort Launching r: " + r
            Slog.e(TAG, "[ASM] Abort Launching r: " + r
                    + " as source: "
                    + (mSourceRecord != null ? mSourceRecord : r.launchedFromPackage)
                    + (mSourceRecord != null ? mSourceRecord : launchedFromPackageName)
                    + " is in background. New task: " + newTask
                    + ". Top activity: " + targetTopActivity
                    + ". BAL Code: " + mBalCode);
                    + ". BAL Code: " + balCodeToString(mBalCode));

            return false;
        }
@@ -2034,6 +2039,82 @@ 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,
            boolean taskToFront) {
        final String prefix = "[ASM] ";
        Function<ActivityRecord, String> recordToString = (ar) -> {
            if (ar == null) {
                return null;
            }
            return (ar == mSourceRecord ? " [source]=> "
                    : ar == targetTopActivity ? " [ top  ]=> "
                            : ar == r ? " [target]=> "
                                    : "         => ")
                    + ar
                    + " :: visible=" + ar.isVisible()
                    + ", finishing=" + ar.isFinishing()
                    + ", alwaysOnTop=" + ar.isAlwaysOnTop()
                    + ", taskFragment=" + ar.getTaskFragment();
        };

        StringJoiner joiner = new StringJoiner("\n");
        joiner.add(prefix + "------ Activity Security " + action + " Debug Logging Start ------");
        joiner.add(prefix + "Block Enabled: " + blockActivityStartAndFeatureEnabled);
        joiner.add(prefix + "ASM Version: " + ActivitySecurityModelFeatureFlags.ASM_VERSION);

        boolean targetTaskMatchesSourceTask = targetTask != null
                && mSourceRecord != null && mSourceRecord.getTask() == targetTask;

        if (mSourceRecord == null) {
            joiner.add(prefix + "Source Package: " + r.launchedFromPackage);
            String realCallingPackage = mService.mContext.getPackageManager().getNameForUid(
                    mRealCallingUid);
            joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage);
        } else {
            joiner.add(prefix + "Source Record: " + recordToString.apply(mSourceRecord));
            if (targetTaskMatchesSourceTask) {
                joiner.add(prefix + "Source/Target Task: " + mSourceRecord.getTask());
                joiner.add(prefix + "Source/Target Task Stack: ");
            } else {
                joiner.add(prefix + "Source Task: " + mSourceRecord.getTask());
                joiner.add(prefix + "Source Task Stack: ");
            }
            mSourceRecord.getTask().forAllActivities((Consumer<ActivityRecord>)
                    ar -> joiner.add(prefix + recordToString.apply(ar)));
        }

        joiner.add(prefix + "Target Task Top: " + recordToString.apply(targetTopActivity));
        if (!targetTaskMatchesSourceTask) {
            joiner.add(prefix + "Target Task: " + targetTask);
            if (targetTask != null) {
                joiner.add(prefix + "Target Task Stack: ");
                targetTask.forAllActivities((Consumer<ActivityRecord>)
                        ar -> joiner.add(prefix + recordToString.apply(ar)));
            }
        }

        joiner.add(prefix + "Target Record: " + recordToString.apply(r));
        joiner.add(prefix + "Intent: " + mIntent);
        joiner.add(prefix + "TaskToFront: " + taskToFront);
        joiner.add(prefix + "BalCode: " + balCodeToString(mBalCode));

        joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------");
        Slog.i(TAG, joiner.toString());
    }

    /**
     * Returns whether embedding of {@code starting} is allowed.
     *
@@ -2165,8 +2246,8 @@ class ActivityStarter {
            return;
        }

        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing && (ar.isUid(
                startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
        Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
                && (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));

        // Return early if we know for sure we won't need to clear any activities by just checking
        // the top activity.
@@ -2202,7 +2283,10 @@ class ActivityStarter {
                            ? "Top activities cleared by "
                            : "Top activities would be cleared by ")
                            + ActivitySecurityModelFeatureFlags.DOC_LINK,
                    Toast.LENGTH_SHORT).show());
                    Toast.LENGTH_LONG).show());

            logDebugInfoForActivitySecurity("Clear Top", mStartActivity, targetTask, targetTaskTop,
                    shouldBlockActivityStart, /* taskToFront */ true);
        }
    }

+8 −6
Original line number Diff line number Diff line
@@ -51,7 +51,6 @@ import static android.view.WindowManager.TRANSIT_TO_FRONT;

import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
import static com.android.server.wm.ActivityRecord.State.FINISHING;
import static com.android.server.wm.ActivityRecord.State.PAUSED;
import static com.android.server.wm.ActivityRecord.State.PAUSING;
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
@@ -1649,7 +1648,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
            wouldBlockActivitySwitchIgnoringFlags = !pair.second;
            if (wouldBlockActivitySwitchIgnoringFlags) {
                ActivityRecord topActivity =  task.getActivity(ar ->
                        !ar.isState(FINISHING) && !ar.isAlwaysOnTop());
                        !ar.finishing && !ar.isAlwaysOnTop());
                FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
                        /* caller_uid */
                        callingUid,
@@ -1672,7 +1671,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
                        /* action */
                        FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED__ACTION__FINISH_TASK,
                        /* version */
                        3,
                        ActivitySecurityModelFeatureFlags.ASM_VERSION,
                        /* multi_window */
                        false,
                        /* bal_code */
@@ -1700,16 +1699,19 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
                                    ? "Returning home due to "
                                    : "Would return home due to ")
                                    + ActivitySecurityModelFeatureFlags.DOC_LINK,
                            Toast.LENGTH_SHORT).show());
                            Toast.LENGTH_LONG).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, "Return to home as source uid: " + callingUid
                    Slog.w(TAG, "[ASM] Return to home as source uid: " + callingUid
                            + "is not on top of task t: " + task);
                    task.getTaskDisplayArea().moveHomeActivityToTop("taskRemoved");
                } else {
                    Slog.i(TAG, "[ASM] Would return to home as source uid: " + callingUid
                            + "is not on top of task t: " + task);
                }
            }
        } finally {
@@ -1743,7 +1745,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
        // Consider the source activity, whether or not it is finishing. Do not consider any other
        // finishing activity.
        Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
                || (!ar.isState(FINISHING) && !ar.isAlwaysOnTop());
                || (!ar.finishing && !ar.isAlwaysOnTop());

        // Check top of stack (or the first task fragment for embedding).
        ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
+29 −0
Original line number Diff line number Diff line
@@ -114,6 +114,35 @@ public class BackgroundActivityStartController {
    /** Process belongs to a SDK sandbox */
    static final int BAL_ALLOW_SDK_SANDBOX = 10;

    static String balCodeToString(@BalCode int balCode) {
        switch (balCode) {
            case BAL_ALLOW_ALLOWLISTED_COMPONENT:
                return "BAL_ALLOW_ALLOWLISTED_COMPONENT";
            case BAL_ALLOW_ALLOWLISTED_UID:
                return "BAL_ALLOW_ALLOWLISTED_UID";
            case BAL_ALLOW_DEFAULT:
                return "BAL_ALLOW_DEFAULT";
            case BAL_ALLOW_FOREGROUND:
                return "BAL_ALLOW_FOREGROUND";
            case BAL_ALLOW_GRACE_PERIOD:
                return "BAL_ALLOW_GRACE_PERIOD";
            case BAL_ALLOW_PENDING_INTENT:
                return "BAL_ALLOW_PENDING_INTENT";
            case BAL_ALLOW_PERMISSION:
                return "BAL_ALLOW_PERMISSION";
            case BAL_ALLOW_SAW_PERMISSION:
                return "BAL_ALLOW_SAW_PERMISSION";
            case BAL_ALLOW_SDK_SANDBOX:
                return "BAL_ALLOW_SDK_SANDBOX";
            case BAL_ALLOW_VISIBLE_WINDOW:
                return "BAL_ALLOW_VISIBLE_WINDOW";
            case BAL_BLOCK:
                return "BAL_BLOCK";
            default:
                throw new IllegalArgumentException("Unexpected value: " + balCode);
        }
    }

    BackgroundActivityStartController(
            final ActivityTaskManagerService service, final ActivityTaskSupervisor supervisor) {
        mService = service;