Merge "ASM Rule and Debug Updates." into main
diff --git a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
index f1a2159..db27f60 100644
--- a/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
+++ b/services/core/java/com/android/server/wm/ActivitySecurityModelFeatureFlags.java
@@ -43,7 +43,7 @@
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 = 8;
+ static final int ASM_VERSION = 9;
private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index f6d77ea..d6f52b8 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2053,8 +2053,8 @@
}
if (!mSupervisor.getBackgroundActivityLaunchController().checkActivityAllowedToStart(
- mSourceRecord, r, newTask, targetTask, mLaunchFlags, mBalCode, mCallingUid,
- mRealCallingUid)) {
+ mSourceRecord, r, newTask, avoidMoveToFront(), targetTask, mLaunchFlags, mBalCode,
+ mCallingUid, mRealCallingUid)) {
return START_ABORTED;
}
diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
index 0f36d8e..39dd77e 100644
--- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
+++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java
@@ -57,6 +57,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Process;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.ArraySet;
@@ -1042,8 +1043,9 @@
* create a new task or bring an existing one into the foreground
*/
boolean checkActivityAllowedToStart(@Nullable ActivityRecord sourceRecord,
- @NonNull ActivityRecord targetRecord, boolean newTask, @NonNull Task targetTask,
- int launchFlags, int balCode, int callingUid, int realCallingUid) {
+ @NonNull ActivityRecord targetRecord, boolean newTask, boolean avoidMoveTaskToFront,
+ @Nullable Task targetTask, int launchFlags, int balCode, int callingUid,
+ int realCallingUid) {
// BAL Exception allowed in all cases
if (balCode == BAL_ALLOW_ALLOWLISTED_UID) {
return true;
@@ -1067,14 +1069,36 @@
}
if (balCode == BAL_ALLOW_GRACE_PERIOD) {
+ // Allow if launching into new task, and caller matches most recently finished activity
if (taskToFront && mTopFinishedActivity != null
&& mTopFinishedActivity.mUid == callingUid) {
return true;
- } else if (!taskToFront) {
- FinishedActivityEntry finishedEntry =
- mTaskIdToFinishedActivity.get(targetTask.mTaskId);
- if (finishedEntry != null && finishedEntry.mUid == callingUid) {
- return true;
+ }
+
+ // Launching into existing task - allow if matches most recently finished activity
+ // within the task.
+ // We can reach here multiple ways:
+ // 1. activity in fg fires intent (taskToFront = false, sourceRecord is available)
+ // 2. activity in bg fires intent (taskToFront = false, sourceRecord is available)
+ // 3. activity in bg fires intent with NEW_FLAG (taskToFront = true,
+ // avoidMoveTaskToFront = true, sourceRecord is available)
+ // 4. activity in bg fires PI (taskToFront = true, avoidMoveTaskToFront = true,
+ // sourceRecord is not available, targetTask may be available)
+ if (!taskToFront || avoidMoveTaskToFront) {
+ if (targetTask != null) {
+ FinishedActivityEntry finishedEntry =
+ mTaskIdToFinishedActivity.get(targetTask.mTaskId);
+ if (finishedEntry != null && finishedEntry.mUid == callingUid) {
+ return true;
+ }
+ }
+
+ if (sourceRecord != null) {
+ FinishedActivityEntry finishedEntry =
+ mTaskIdToFinishedActivity.get(sourceRecord.getTask().mTaskId);
+ if (finishedEntry != null && finishedEntry.mUid == callingUid) {
+ return true;
+ }
}
}
}
@@ -1098,7 +1122,7 @@
bas = isTopActivityMatchingUidAbsentForAsm(taskToCheck, sourceRecord.getUid(),
sourceRecord);
}
- } else if (!taskToFront) {
+ } else if (targetTask != null && (!taskToFront || avoidMoveTaskToFront)) {
// We don't have a sourceRecord, and we're launching into an existing task.
// Allow if callingUid is top of stack.
bas = isTopActivityMatchingUidAbsentForAsm(targetTask, callingUid,
@@ -1111,12 +1135,14 @@
// ASM rules have failed. Log why
return logAsmFailureAndCheckFeatureEnabled(sourceRecord, callingUid, realCallingUid,
- newTask, targetTask, targetRecord, balCode, launchFlags, bas, taskToFront);
+ newTask, avoidMoveTaskToFront, targetTask, targetRecord, balCode, launchFlags,
+ bas, taskToFront);
}
private boolean logAsmFailureAndCheckFeatureEnabled(ActivityRecord sourceRecord, int callingUid,
- int realCallingUid, boolean newTask, Task targetTask, ActivityRecord targetRecord,
- @BalCode int balCode, int launchFlags, BlockActivityStart bas, boolean taskToFront) {
+ int realCallingUid, boolean newTask, boolean avoidMoveTaskToFront, Task targetTask,
+ ActivityRecord targetRecord, @BalCode int balCode, int launchFlags,
+ BlockActivityStart bas, boolean taskToFront) {
ActivityRecord targetTopActivity = targetTask == null ? null
: targetTask.getActivity(ar -> !ar.finishing && !ar.isAlwaysOnTop());
@@ -1133,7 +1159,7 @@
String asmDebugInfo = getDebugInfoForActivitySecurity("Launch", sourceRecord,
targetRecord, targetTask, targetTopActivity, realCallingUid, balCode,
- blockActivityStartAndFeatureEnabled, taskToFront);
+ blockActivityStartAndFeatureEnabled, taskToFront, avoidMoveTaskToFront);
FrameworkStatsLog.write(FrameworkStatsLog.ACTIVITY_ACTION_BLOCKED,
/* caller_uid */
@@ -1265,7 +1291,7 @@
Slog.i(TAG, getDebugInfoForActivitySecurity("Clear Top", sourceRecord, targetRecord,
targetTask, targetTaskTop, realCallingUid, balCode, shouldBlockActivityStart,
- /* taskToFront */ true));
+ /* taskToFront */ true, /* avoidMoveTaskToFront */ false));
}
}
@@ -1379,7 +1405,7 @@
private BlockActivityStart isTopActivityMatchingUidAbsentForAsm(@NonNull Task task,
int uid, @Nullable ActivityRecord sourceRecord) {
// If the source is visible, consider it 'top'.
- if (sourceRecord != null && sourceRecord.isVisible()) {
+ if (sourceRecord != null && sourceRecord.isVisibleRequested()) {
return new BlockActivityStart(false, false);
}
@@ -1389,6 +1415,12 @@
return new BlockActivityStart(false, false);
}
+ // If UID is visible in target task, allow launch
+ if (task.forAllActivities((Predicate<ActivityRecord>)
+ ar -> ar.isUid(uid) && ar.isVisibleRequested())) {
+ return new BlockActivityStart(false, false);
+ }
+
// Consider the source activity, whether or not it is finishing. Do not consider any other
// finishing activity.
Predicate<ActivityRecord> topOfStackPredicate = (ar) -> ar.equals(sourceRecord)
@@ -1480,27 +1512,26 @@
@Nullable ActivityRecord sourceRecord, @NonNull ActivityRecord targetRecord,
@Nullable Task targetTask, @Nullable ActivityRecord targetTopActivity,
int realCallingUid, @BalCode int balCode,
- boolean blockActivityStartAndFeatureEnabled, boolean taskToFront) {
+ boolean blockActivityStartAndFeatureEnabled, boolean taskToFront,
+ boolean avoidMoveTaskToFront) {
final String prefix = "[ASM] ";
Function<ActivityRecord, String> recordToString = (ar) -> {
if (ar == null) {
return null;
}
- return (ar == sourceRecord ? " [source]=> "
+
+ return (ar == sourceRecord ? " [source]=> "
: ar == targetTopActivity ? " [ top ]=> "
- : ar == targetRecord ? " [target]=> "
- : " => ")
- + ar
- + " :: visible=" + ar.isVisible()
- + ", finishing=" + ar.isFinishing()
- + ", alwaysOnTop=" + ar.isAlwaysOnTop()
- + ", taskFragment=" + ar.getTaskFragment();
+ : ar == targetRecord ? " [target]=> "
+ : " => ")
+ + getDebugStringForActivityRecord(ar);
};
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);
+ joiner.add(prefix + "System Time: " + SystemClock.uptimeMillis());
boolean targetTaskMatchesSourceTask = targetTask != null
&& sourceRecord != null && sourceRecord.getTask() == targetTask;
@@ -1512,6 +1543,8 @@
joiner.add(prefix + "Real Calling Uid Package: " + realCallingPackage);
} else {
joiner.add(prefix + "Source Record: " + recordToString.apply(sourceRecord));
+ joiner.add(prefix + "Source Launch Package: " + sourceRecord.launchedFromPackage);
+ joiner.add(prefix + "Source Launch Intent: " + sourceRecord.intent);
if (targetTaskMatchesSourceTask) {
joiner.add(prefix + "Source/Target Task: " + sourceRecord.getTask());
joiner.add(prefix + "Source/Target Task Stack: ");
@@ -1536,7 +1569,30 @@
joiner.add(prefix + "Target Record: " + recordToString.apply(targetRecord));
joiner.add(prefix + "Intent: " + targetRecord.intent);
joiner.add(prefix + "TaskToFront: " + taskToFront);
+ joiner.add(prefix + "AvoidMoveToFront: " + avoidMoveTaskToFront);
joiner.add(prefix + "BalCode: " + balCodeToString(balCode));
+ joiner.add(prefix + "LastResumedActivity: "
+ + recordToString.apply(mService.mLastResumedActivity));
+
+ if (mTopFinishedActivity != null) {
+ joiner.add(prefix + "TopFinishedActivity: " + mTopFinishedActivity.mDebugInfo);
+ }
+
+ if (!mTaskIdToFinishedActivity.isEmpty()) {
+ joiner.add(prefix + "TaskIdToFinishedActivity: ");
+ mTaskIdToFinishedActivity.values().forEach(
+ (fae) -> joiner.add(prefix + " " + fae.mDebugInfo));
+ }
+
+ if (balCode == BAL_ALLOW_VISIBLE_WINDOW || balCode == BAL_ALLOW_NON_APP_VISIBLE_WINDOW
+ || balCode == BAL_ALLOW_FOREGROUND) {
+ Task task = sourceRecord != null ? sourceRecord.getTask() : targetTask;
+ if (task != null && task.getDisplayArea() != null) {
+ joiner.add(prefix + "Tasks: ");
+ task.getDisplayArea().forAllTasks((Consumer<Task>)
+ t -> joiner.add(prefix + " T: " + t.toFullString()));
+ }
+ }
joiner.add(prefix + "------ Activity Security " + action + " Debug Logging End ------");
return joiner.toString();
@@ -1620,7 +1676,7 @@
return;
}
- if (!finishActivity.mVisibleRequested
+ if (!finishActivity.isVisibleRequested()
&& finishActivity != finishActivity.getTask().getTopMostActivity()) {
return;
}
@@ -1666,10 +1722,22 @@
}
}
+ private static String getDebugStringForActivityRecord(ActivityRecord ar) {
+ return ar
+ + " :: visible=" + ar.isVisible()
+ + ", visibleRequested=" + ar.isVisibleRequested()
+ + ", finishing=" + ar.isFinishing()
+ + ", alwaysOnTop=" + ar.isAlwaysOnTop()
+ + ", lastLaunchTime=" + ar.lastLaunchTime
+ + ", lastVisibleTime=" + ar.lastVisibleTime
+ + ", taskFragment=" + ar.getTaskFragment();
+ }
+
private class FinishedActivityEntry {
int mUid;
int mTaskId;
int mLaunchCount;
+ String mDebugInfo;
FinishedActivityEntry(ActivityRecord ar) {
FinishedActivityEntry entry = mTaskIdToFinishedActivity.get(ar.getTask().mTaskId);
@@ -1677,6 +1745,7 @@
this.mUid = ar.getUid();
this.mTaskId = taskId;
this.mLaunchCount = entry == null || !ar.isUid(entry.mUid) ? 1 : entry.mLaunchCount + 1;
+ this.mDebugInfo = getDebugStringForActivityRecord(ar);
mService.mH.postDelayed(() -> {
synchronized (mService.mGlobalLock) {