Loading services/core/java/com/android/server/wm/ActivityStarter.java +58 −49 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; 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.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; Loading Loading @@ -148,6 +149,7 @@ import com.android.server.wm.TaskFragment.EmbeddingCheckResult; import java.io.PrintWriter; import java.text.DateFormat; import java.util.Date; import java.util.function.Predicate; /** * Controller for interpreting how and then launching an activity. Loading Loading @@ -189,6 +191,7 @@ class ActivityStarter { ActivityRecord mStartActivity; private Intent mIntent; private int mCallingUid; private int mRealCallingUid; private ActivityOptions mOptions; // If it is BAL_BLOCK, background activity can only be started in an existing task that contains Loading Loading @@ -611,6 +614,7 @@ class ActivityStarter { mStartActivity = starter.mStartActivity; mIntent = starter.mIntent; mCallingUid = starter.mCallingUid; mRealCallingUid = starter.mRealCallingUid; mOptions = starter.mOptions; mBalCode = starter.mBalCode; Loading Loading @@ -1272,7 +1276,7 @@ class ActivityStarter { mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, checkedOptions, inTask, inTaskFragment, balCode, intentGrants); inTask, inTaskFragment, balCode, intentGrants, realCallingUid); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; Loading Loading @@ -1423,7 +1427,7 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, @BalCode int balCode, NeededUriGrants intentGrants) { NeededUriGrants intentGrants, int realCallingUid) { int result = START_CANCELED; final Task startedActivityRootTask; Loading @@ -1443,7 +1447,7 @@ class ActivityStarter { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, options, inTask, inTaskFragment, balCode, intentGrants); intentGrants, realCallingUid); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startedActivityRootTask = handleStartResult(r, options, result, newTransition, Loading Loading @@ -1590,9 +1594,9 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, @BalCode int balCode, NeededUriGrants intentGrants) { NeededUriGrants intentGrants, int realCallingUid) { setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord, voiceSession, voiceInteractor, balCode); voiceSession, voiceInteractor, balCode, realCallingUid); computeLaunchingTaskFlags(); mIntent.setFlags(mLaunchFlags); Loading Loading @@ -1938,7 +1942,9 @@ class ActivityStarter { if (taskToFront) { if (mBalCode == BAL_ALLOW_ALLOWLISTED_COMPONENT || mBalCode == BAL_ALLOW_PERMISSION || mBalCode == BAL_ALLOW_PENDING_INTENT) { || mBalCode == BAL_ALLOW_PENDING_INTENT || mBalCode == BAL_ALLOW_SAW_PERMISSION || mBalCode == BAL_ALLOW_VISIBLE_WINDOW) { return true; } } Loading @@ -1948,12 +1954,6 @@ class ActivityStarter { return true; } // TODO(b/230590090): Revisit this - ideally we would not rely on visibility, but rather // have an explicit api for activities to opt-out of ASM protection if they need to. if (mBalCode == BAL_ALLOW_VISIBLE_WINDOW) { return true; } // ASM rules have failed. Log why ActivityRecord targetTopActivity = targetTask == null ? null : targetTask.getActivity(ar -> Loading Loading @@ -1988,7 +1988,7 @@ class ActivityStarter { /* action */ action, /* version */ 3, 4, /* 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(), Loading Loading @@ -2106,7 +2106,8 @@ class ActivityStarter { reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants); if (mAddingToTask) { clearTopIfNeeded(targetTask, mCallingUid, mStartActivity.getUid(), mLaunchFlags); clearTopIfNeeded(targetTask, mCallingUid, mRealCallingUid, mStartActivity.getUid(), mLaunchFlags); return START_SUCCESS; } Loading Loading @@ -2139,38 +2140,45 @@ class ActivityStarter { } /** * If the top activity uid does not match the launched activity, and the launch was not * requested from the top uid, we want to clear out all non matching activities to prevent the * top activity being sandwiched. * If the top activity uid does not match the launching or launched activity, and the launch was * not requested from the top uid, we want to clear out all non matching activities to prevent * the top activity being sandwiched. * * Both creator and sender UID are considered for the launching activity. */ private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int startingUid, int launchFlags) { 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 return; } ActivityRecord targetTaskTop = targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null && targetTaskTop.getUid() != startingUid) { 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. ActivityRecord targetTaskTop = targetTask.getTopMostActivity(); if (targetTaskTop == null || isLaunchingOrLaunched.test(targetTaskTop)) { return; } // Find the first activity which matches a safe UID and is not finishing. Clear everything // above it boolean shouldBlockActivityStart = ActivitySecurityModelFeatureFlags .shouldRestrictActivitySwitch(callingUid); int[] finishCount = new int[0]; if (shouldBlockActivityStart) { ActivityRecord activity = targetTask.getActivity( ar -> !ar.finishing && ar.isUid(startingUid)); ActivityRecord activity = targetTask.getActivity(isLaunchingOrLaunched); if (activity == null) { // mStartActivity is not in task, so clear everything activity = mStartActivity; } finishCount = new int[1]; if (activity != null) { targetTask.performClearTop(activity, launchFlags, finishCount); } if (finishCount[0] > 0) { Slog.w(TAG, "Clearing top n: " + finishCount[0] + " activities from task t: " Slog.w(TAG, "Cleared top n: " + finishCount[0] + " activities from task t: " + targetTask + " not matching top uid: " + callingUid); } } Loading @@ -2185,7 +2193,6 @@ class ActivityStarter { Toast.LENGTH_SHORT).show()); } } } /** * Check if the activity being launched is the same as the one currently at the top and it Loading Loading @@ -2376,6 +2383,7 @@ class ActivityStarter { mStartActivity = null; mIntent = null; mCallingUid = -1; mRealCallingUid = -1; mOptions = null; mBalCode = BAL_ALLOW_DEFAULT; Loading Loading @@ -2422,13 +2430,14 @@ class ActivityStarter { private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, int startFlags, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, @BalCode int balCode) { IVoiceInteractor voiceInteractor, @BalCode int balCode, int realCallingUid) { reset(false /* clearRequest */); mStartActivity = r; mIntent = r.intent; mOptions = options; mCallingUid = r.launchedFromUid; mRealCallingUid = realCallingUid; mSourceRecord = sourceRecord; mSourceRootTask = mSourceRecord != null ? mSourceRecord.getRootTask() : null; mVoiceSession = voiceSession; Loading services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -1847,6 +1847,7 @@ public class ActivityStarterTests extends WindowTestsBase { starter.startActivityInner(target, source, null /* voiceSession */, null /* voiceInteractor */, 0 /* startFlags */, options, inTask, inTaskFragment, BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */); BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */, -1 /* realCallingUid */); } } services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java +4 −2 Original line number Diff line number Diff line Loading @@ -189,7 +189,8 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* inTask */null, /* inTaskFragment */ null, /* balCode */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, /* intentGrants */null); /* intentGrants */null, /* realCaiingUid */ -1); assertEquals(result, START_ABORTED); } Loading @@ -213,7 +214,8 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* inTask= */null, /* inTaskFragment= */ null, /* balCode= */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, /* intentGrants= */null); /* intentGrants= */null, /* realCaiingUid */ -1); assertEquals(result, START_ABORTED); } Loading Loading
services/core/java/com/android/server/wm/ActivityStarter.java +58 −49 Original line number Diff line number Diff line Loading @@ -80,6 +80,7 @@ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_ import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_DEFAULT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PENDING_INTENT; import static com.android.server.wm.BackgroundActivityStartController.BAL_ALLOW_PERMISSION; 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.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS; Loading Loading @@ -148,6 +149,7 @@ import com.android.server.wm.TaskFragment.EmbeddingCheckResult; import java.io.PrintWriter; import java.text.DateFormat; import java.util.Date; import java.util.function.Predicate; /** * Controller for interpreting how and then launching an activity. Loading Loading @@ -189,6 +191,7 @@ class ActivityStarter { ActivityRecord mStartActivity; private Intent mIntent; private int mCallingUid; private int mRealCallingUid; private ActivityOptions mOptions; // If it is BAL_BLOCK, background activity can only be started in an existing task that contains Loading Loading @@ -611,6 +614,7 @@ class ActivityStarter { mStartActivity = starter.mStartActivity; mIntent = starter.mIntent; mCallingUid = starter.mCallingUid; mRealCallingUid = starter.mRealCallingUid; mOptions = starter.mOptions; mBalCode = starter.mBalCode; Loading Loading @@ -1272,7 +1276,7 @@ class ActivityStarter { mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, checkedOptions, inTask, inTaskFragment, balCode, intentGrants); inTask, inTaskFragment, balCode, intentGrants, realCallingUid); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; Loading Loading @@ -1423,7 +1427,7 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, @BalCode int balCode, NeededUriGrants intentGrants) { NeededUriGrants intentGrants, int realCallingUid) { int result = START_CANCELED; final Task startedActivityRootTask; Loading @@ -1443,7 +1447,7 @@ class ActivityStarter { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, startFlags, options, inTask, inTaskFragment, balCode, intentGrants); intentGrants, realCallingUid); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); startedActivityRootTask = handleStartResult(r, options, result, newTransition, Loading Loading @@ -1590,9 +1594,9 @@ class ActivityStarter { IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, @BalCode int balCode, NeededUriGrants intentGrants) { NeededUriGrants intentGrants, int realCallingUid) { setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord, voiceSession, voiceInteractor, balCode); voiceSession, voiceInteractor, balCode, realCallingUid); computeLaunchingTaskFlags(); mIntent.setFlags(mLaunchFlags); Loading Loading @@ -1938,7 +1942,9 @@ class ActivityStarter { if (taskToFront) { if (mBalCode == BAL_ALLOW_ALLOWLISTED_COMPONENT || mBalCode == BAL_ALLOW_PERMISSION || mBalCode == BAL_ALLOW_PENDING_INTENT) { || mBalCode == BAL_ALLOW_PENDING_INTENT || mBalCode == BAL_ALLOW_SAW_PERMISSION || mBalCode == BAL_ALLOW_VISIBLE_WINDOW) { return true; } } Loading @@ -1948,12 +1954,6 @@ class ActivityStarter { return true; } // TODO(b/230590090): Revisit this - ideally we would not rely on visibility, but rather // have an explicit api for activities to opt-out of ASM protection if they need to. if (mBalCode == BAL_ALLOW_VISIBLE_WINDOW) { return true; } // ASM rules have failed. Log why ActivityRecord targetTopActivity = targetTask == null ? null : targetTask.getActivity(ar -> Loading Loading @@ -1988,7 +1988,7 @@ class ActivityStarter { /* action */ action, /* version */ 3, 4, /* 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(), Loading Loading @@ -2106,7 +2106,8 @@ class ActivityStarter { reusedTask != null ? reusedTask.getTopNonFinishingActivity() : null, intentGrants); if (mAddingToTask) { clearTopIfNeeded(targetTask, mCallingUid, mStartActivity.getUid(), mLaunchFlags); clearTopIfNeeded(targetTask, mCallingUid, mRealCallingUid, mStartActivity.getUid(), mLaunchFlags); return START_SUCCESS; } Loading Loading @@ -2139,38 +2140,45 @@ class ActivityStarter { } /** * If the top activity uid does not match the launched activity, and the launch was not * requested from the top uid, we want to clear out all non matching activities to prevent the * top activity being sandwiched. * If the top activity uid does not match the launching or launched activity, and the launch was * not requested from the top uid, we want to clear out all non matching activities to prevent * the top activity being sandwiched. * * Both creator and sender UID are considered for the launching activity. */ private void clearTopIfNeeded(@NonNull Task targetTask, int callingUid, int startingUid, int launchFlags) { 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 return; } ActivityRecord targetTaskTop = targetTask.getTopNonFinishingActivity(); if (targetTaskTop != null && targetTaskTop.getUid() != startingUid) { 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. ActivityRecord targetTaskTop = targetTask.getTopMostActivity(); if (targetTaskTop == null || isLaunchingOrLaunched.test(targetTaskTop)) { return; } // Find the first activity which matches a safe UID and is not finishing. Clear everything // above it boolean shouldBlockActivityStart = ActivitySecurityModelFeatureFlags .shouldRestrictActivitySwitch(callingUid); int[] finishCount = new int[0]; if (shouldBlockActivityStart) { ActivityRecord activity = targetTask.getActivity( ar -> !ar.finishing && ar.isUid(startingUid)); ActivityRecord activity = targetTask.getActivity(isLaunchingOrLaunched); if (activity == null) { // mStartActivity is not in task, so clear everything activity = mStartActivity; } finishCount = new int[1]; if (activity != null) { targetTask.performClearTop(activity, launchFlags, finishCount); } if (finishCount[0] > 0) { Slog.w(TAG, "Clearing top n: " + finishCount[0] + " activities from task t: " Slog.w(TAG, "Cleared top n: " + finishCount[0] + " activities from task t: " + targetTask + " not matching top uid: " + callingUid); } } Loading @@ -2185,7 +2193,6 @@ class ActivityStarter { Toast.LENGTH_SHORT).show()); } } } /** * Check if the activity being launched is the same as the one currently at the top and it Loading Loading @@ -2376,6 +2383,7 @@ class ActivityStarter { mStartActivity = null; mIntent = null; mCallingUid = -1; mRealCallingUid = -1; mOptions = null; mBalCode = BAL_ALLOW_DEFAULT; Loading Loading @@ -2422,13 +2430,14 @@ class ActivityStarter { private void setInitialState(ActivityRecord r, ActivityOptions options, Task inTask, TaskFragment inTaskFragment, int startFlags, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, @BalCode int balCode) { IVoiceInteractor voiceInteractor, @BalCode int balCode, int realCallingUid) { reset(false /* clearRequest */); mStartActivity = r; mIntent = r.intent; mOptions = options; mCallingUid = r.launchedFromUid; mRealCallingUid = realCallingUid; mSourceRecord = sourceRecord; mSourceRootTask = mSourceRecord != null ? mSourceRecord.getRootTask() : null; mVoiceSession = voiceSession; Loading
services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -1847,6 +1847,7 @@ public class ActivityStarterTests extends WindowTestsBase { starter.startActivityInner(target, source, null /* voiceSession */, null /* voiceInteractor */, 0 /* startFlags */, options, inTask, inTaskFragment, BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */); BackgroundActivityStartController.BAL_ALLOW_DEFAULT, null /* intentGrants */, -1 /* realCallingUid */); } }
services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java +4 −2 Original line number Diff line number Diff line Loading @@ -189,7 +189,8 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* inTask */null, /* inTaskFragment */ null, /* balCode */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, /* intentGrants */null); /* intentGrants */null, /* realCaiingUid */ -1); assertEquals(result, START_ABORTED); } Loading @@ -213,7 +214,8 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* inTask= */null, /* inTaskFragment= */ null, /* balCode= */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, /* intentGrants= */null); /* intentGrants= */null, /* realCaiingUid */ -1); assertEquals(result, START_ABORTED); } Loading