ASM - Bug fixes for clearTopIfNeeded
This includes the following changes: 1. activity starts with UID 0 could fail - they do not have a corresponding packageName, resulting in a NPE in the feature flag allowlist. We now both explicitely allow UID 0, and check for nulls. 2. We no longer exclude finishing activities in the check. While this is generally a no-op, it resulted in noisy logs/toasts. E.G, an activity finishes itself and launches a new one with NEW_TASK at the same time would result in clearTop being called, even though there is nothing to clear. This is net-neutral for security - the finishing activity could have already morphed itself rather than finishing. 3. We move the home task to front of the finishing tas in checkActivitySecurityForTaskClear, rather than to front of display area. For multi-window scenarios, this could result in one app forcing a home switch for the other. 4. Allow launches from top of stack, even if finishing or alwaysOnTop. This supports tasks which are always set to alwaysOnTop, if they try to start or finish activities Bug: 271417931 Test: ABTD with all WM tests and InputMethod tests Change-Id: I966319723b17f1affd92e141791596e5da644050
This commit is contained in:
@@ -43,7 +43,7 @@ class ActivitySecurityModelFeatureFlags {
|
||||
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 = 6;
|
||||
static final int ASM_VERSION = 7;
|
||||
|
||||
private static final String NAMESPACE = NAMESPACE_WINDOW_MANAGER;
|
||||
private static final String KEY_ASM_PREFIX = "ActivitySecurity__";
|
||||
@@ -89,6 +89,9 @@ class ActivitySecurityModelFeatureFlags {
|
||||
|
||||
if (flagEnabled) {
|
||||
String[] packageNames = sPm.getPackagesForUid(uid);
|
||||
if (packageNames == null) {
|
||||
return true;
|
||||
}
|
||||
for (int i = 0; i < packageNames.length; i++) {
|
||||
if (sExcludedPackageNames.contains(packageNames[i])) {
|
||||
return false;
|
||||
|
||||
@@ -2249,13 +2249,14 @@ class ActivityStarter {
|
||||
*/
|
||||
private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int realCallingUid,
|
||||
int startingUid, int launchFlags) {
|
||||
if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK) {
|
||||
// Launch is from the same task, so must be a top or privileged UID
|
||||
if ((launchFlags & FLAG_ACTIVITY_NEW_TASK) != FLAG_ACTIVITY_NEW_TASK
|
||||
|| mBalCode == BAL_ALLOW_ALLOWLISTED_UID) {
|
||||
// Launch is from the same task, (a top or privileged UID), or is directly privileged.
|
||||
return;
|
||||
}
|
||||
|
||||
Predicate<ActivityRecord> isLaunchingOrLaunched = ar -> !ar.finishing
|
||||
&& (ar.isUid(startingUid) || ar.isUid(callingUid) || ar.isUid(realCallingUid));
|
||||
Predicate<ActivityRecord> isLaunchingOrLaunched = ar ->
|
||||
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.
|
||||
|
||||
@@ -1666,7 +1666,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
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.
|
||||
if (callingUid == SYSTEM_UID) {
|
||||
if (callingUid == SYSTEM_UID || !task.isVisible() || task.inMultiWindowMode()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1772,13 +1772,19 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
|
||||
return new Pair<>(true, true);
|
||||
}
|
||||
|
||||
// Always allow actual top activity to clear task
|
||||
ActivityRecord topActivity = task.getTopMostActivity();
|
||||
if (topActivity != null && topActivity.isUid(uid)) {
|
||||
return new Pair<>(true, true);
|
||||
}
|
||||
|
||||
// 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.finishing && !ar.isAlwaysOnTop());
|
||||
|
||||
// Check top of stack (or the first task fragment for embedding).
|
||||
ActivityRecord topActivity = task.getActivity(topOfStackPredicate);
|
||||
topActivity = task.getActivity(topOfStackPredicate);
|
||||
if (topActivity == null) {
|
||||
return new Pair<>(false, false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user