diff options
4 files changed, 69 insertions, 22 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java index 009b8e048840..5e0a449ddd63 100644 --- a/services/core/java/com/android/server/wm/ActivityStarter.java +++ b/services/core/java/com/android/server/wm/ActivityStarter.java @@ -133,6 +133,7 @@ import com.android.server.statusbar.StatusBarManagerInternal; import com.android.server.uri.NeededUriGrants; import com.android.server.wm.ActivityMetricsLogger.LaunchingState; import com.android.server.wm.BackgroundActivityStartController.BalCode; +import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParams; import com.android.server.wm.TaskFragment.EmbeddingCheckResult; @@ -1090,14 +1091,14 @@ class ActivityStarter { ActivityOptions checkedOptions = options != null ? options.getOptions(intent, aInfo, callerApp, mSupervisor) : null; - @BalCode int balCode = BAL_ALLOW_DEFAULT; + final BalVerdict balVerdict; if (!abort) { try { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "shouldAbortBackgroundActivityStart"); BackgroundActivityStartController balController = mSupervisor.getBackgroundActivityLaunchController(); - BackgroundActivityStartController.BalVerdict balVerdict = + balVerdict = balController.checkBackgroundActivityStart( callingUid, callingPid, @@ -1109,13 +1110,13 @@ class ActivityStarter { request.forcedBalByPiSender, intent, checkedOptions); - balCode = balVerdict.getCode(); - request.logMessage.append(" (").append( - BackgroundActivityStartController.balCodeToString(balCode)) - .append(")"); + request.logMessage.append(" (").append(balVerdict).append(")"); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); } + } else { + // Sets ALLOW_BY_DEFAULT as default value as the activity launch will be aborted anyway. + balVerdict = BalVerdict.ALLOW_BY_DEFAULT; } if (request.allowPendingRemoteAnimationRegistryLookup) { @@ -1293,13 +1294,13 @@ class ActivityStarter { WindowProcessController homeProcess = mService.mHomeProcess; boolean isHomeProcess = homeProcess != null && aInfo.applicationInfo.uid == homeProcess.mUid; - if (balCode != BAL_BLOCK && !isHomeProcess) { + if (balVerdict.allows() && !isHomeProcess) { mService.resumeAppSwitches(); } mLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession, request.voiceInteractor, startFlags, checkedOptions, - inTask, inTaskFragment, balCode, intentGrants, realCallingUid); + inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid); if (request.outActivity != null) { request.outActivity[0] = mLastStartActivityRecord; @@ -1449,7 +1450,8 @@ class ActivityStarter { private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, - TaskFragment inTaskFragment, @BalCode int balCode, + TaskFragment inTaskFragment, + BalVerdict balVerdict, NeededUriGrants intentGrants, int realCallingUid) { int result = START_CANCELED; final Task startedActivityRootTask; @@ -1468,7 +1470,7 @@ class ActivityStarter { try { Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner"); result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor, - startFlags, options, inTask, inTaskFragment, balCode, + startFlags, options, inTask, inTaskFragment, balVerdict, intentGrants, realCallingUid); } finally { Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER); @@ -1615,10 +1617,10 @@ class ActivityStarter { int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags, ActivityOptions options, Task inTask, - TaskFragment inTaskFragment, @BalCode int balCode, + TaskFragment inTaskFragment, BalVerdict balVerdict, NeededUriGrants intentGrants, int realCallingUid) { setInitialState(r, options, inTask, inTaskFragment, startFlags, sourceRecord, - voiceSession, voiceInteractor, balCode, realCallingUid); + voiceSession, voiceInteractor, balVerdict.getCode(), realCallingUid); computeLaunchingTaskFlags(); mIntent.setFlags(mLaunchFlags); @@ -1696,7 +1698,8 @@ class ActivityStarter { } recordTransientLaunchIfNeeded(targetTaskTop); // Recycle the target task for this launch. - startResult = recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants); + startResult = + recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants, balVerdict); if (startResult != START_SUCCESS) { return startResult; } @@ -1730,6 +1733,7 @@ class ActivityStarter { recordTransientLaunchIfNeeded(mLastStartActivityRecord); if (!mAvoidMoveToFront && mDoResume) { + logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask); mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask); if (!mTargetRootTask.isTopRootTaskInDisplayArea() && mService.isDreaming() && !dreamStopping) { @@ -1800,6 +1804,7 @@ class ActivityStarter { // now update the focused root-task accordingly. if (!mAvoidMoveToFront && mTargetRootTask.isTopActivityFocusable() && !mRootWindowContainer.isTopDisplayFocusedRootTask(mTargetRootTask)) { + logOnlyCreatorAllowsBAL(balVerdict, realCallingUid, newTask); mTargetRootTask.moveToFront("startActivityInner"); } mRootWindowContainer.resumeFocusedTasksTopActivities( @@ -1817,7 +1822,7 @@ class ActivityStarter { // Note that mStartActivity and source should be in the same Task at this point. if (mOptions != null && mOptions.isLaunchIntoPip() && sourceRecord != null && sourceRecord.getTask() == mStartActivity.getTask() - && balCode != BAL_BLOCK) { + && balVerdict.allows()) { mRootWindowContainer.moveActivityToPinnedRootTask(mStartActivity, sourceRecord, "launch-into-pip"); } @@ -1828,6 +1833,24 @@ class ActivityStarter { return START_SUCCESS; } + private void logOnlyCreatorAllowsBAL(BalVerdict balVerdict, + int realCallingUid, boolean newTask) { + // TODO (b/296478675) eventually, we will prevent such case from happening + // and probably also log that a BAL is prevented by android V. + if (!newTask && balVerdict.onlyCreatorAllows()) { + String realCallingPackage = + mService.mContext.getPackageManager().getNameForUid(realCallingUid); + if (realCallingPackage == null) { + realCallingPackage = "uid=" + realCallingUid; + } + Slog.wtf(TAG, "A background app is brought to the foreground due to a " + + "PendingIntent. However, only the creator of the PendingIntent allows BAL, " + + "while the sender does not allow BAL. realCallingPackage: " + + realCallingPackage + "; callingPackage: " + mRequest.callingPackage + + "; mTargetRootTask:" + mTargetRootTask); + } + } + private void recordTransientLaunchIfNeeded(ActivityRecord r) { if (r == null || !mTransientLaunch) return; final TransitionController controller = r.mTransitionController; @@ -1995,7 +2018,7 @@ class ActivityStarter { */ @VisibleForTesting int recycleTask(Task targetTask, ActivityRecord targetTaskTop, Task reusedTask, - NeededUriGrants intentGrants) { + NeededUriGrants intentGrants, BalVerdict balVerdict) { // Should not recycle task which is from a different user, just adding the starting // activity to the task. if (targetTask.mUserId != mStartActivity.mUserId) { @@ -2024,7 +2047,7 @@ class ActivityStarter { mRootWindowContainer.startPowerModeLaunchIfNeeded(false /* forceSend */, targetTaskTop); - setTargetRootTaskIfNeeded(targetTaskTop); + setTargetRootTaskIfNeeded(targetTaskTop, balVerdict); // When there is a reused activity and the current result is a trampoline activity, // set the reused activity as the result. @@ -2040,6 +2063,7 @@ class ActivityStarter { if (!mMovedToFront && mDoResume) { ProtoLog.d(WM_DEBUG_TASKS, "Bring to front target: %s from %s", mTargetRootTask, targetTaskTop); + logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false); mTargetRootTask.moveToFront("intentActivityFound"); } resumeTargetRootTaskIfNeeded(); @@ -2068,6 +2092,7 @@ class ActivityStarter { targetTaskTop.showStartingWindow(true /* taskSwitch */); } else if (mDoResume) { // Make sure the root task and its belonging display are moved to topmost. + logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false); mTargetRootTask.moveToFront("intentActivityFound"); } // We didn't do anything... but it was needed (a.k.a., client don't use that intent!) @@ -2663,7 +2688,7 @@ class ActivityStarter { * @param intentActivity Existing matching activity. * @return {@link ActivityRecord} brought to front. */ - private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity) { + private void setTargetRootTaskIfNeeded(ActivityRecord intentActivity, BalVerdict balVerdict) { intentActivity.getTaskFragment().clearLastPausedActivity(); Task intentTask = intentActivity.getTask(); // The intent task might be reparented while in getOrCreateRootTask, caches the original @@ -2730,6 +2755,7 @@ class ActivityStarter { // task on top there. // Defer resuming the top activity while moving task to top, since the // current task-top activity may not be the activity that should be resumed. + logOnlyCreatorAllowsBAL(balVerdict, mRealCallingUid, false); mTargetRootTask.moveTaskToFront(intentTask, mNoAnimation, mOptions, mStartActivity.appTimeTracker, DEFER_RESUME, "bringingFoundTaskToFront"); diff --git a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java index b66c4c326a58..287aaf9da42a 100644 --- a/services/core/java/com/android/server/wm/BackgroundActivityStartController.java +++ b/services/core/java/com/android/server/wm/BackgroundActivityStartController.java @@ -433,10 +433,15 @@ public class BackgroundActivityStartController { static class BalVerdict { static final BalVerdict BLOCK = new BalVerdict(BAL_BLOCK, false, "Blocked"); + static final BalVerdict ALLOW_BY_DEFAULT = + new BalVerdict(BAL_ALLOW_DEFAULT, false, "Default"); private final @BalCode int mCode; private final boolean mBackground; private final String mMessage; private String mProcessInfo; + // indicates BAL would be blocked because only creator of the PI has the privilege to allow + // BAL, the sender does not have the privilege to allow BAL. + private boolean mOnlyCreatorAllows; BalVerdict(@BalCode int balCode, boolean background, String message) { this.mBackground = background; @@ -457,6 +462,15 @@ public class BackgroundActivityStartController { return !blocks(); } + BalVerdict setOnlyCreatorAllows(boolean onlyCreatorAllows) { + mOnlyCreatorAllows = onlyCreatorAllows; + return this; + } + + boolean onlyCreatorAllows() { + return mOnlyCreatorAllows; + } + public String toString() { StringBuilder builder = new StringBuilder(); builder.append(balCodeToString(mCode)); @@ -566,6 +580,10 @@ public class BackgroundActivityStartController { BalVerdict resultForRealCaller = state.callerIsRealCaller() && resultForCaller.allows() ? resultForCaller : checkBackgroundActivityStartAllowedBySender(state, checkedOptions); + if (state.isPendingIntent()) { + resultForCaller.setOnlyCreatorAllows( + resultForCaller.allows() && resultForRealCaller.blocks()); + } if (resultForCaller.allows() && checkedOptions.getPendingIntentCreatorBackgroundActivityStartMode() diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java index e2bb115d5fbd..98055fa6f0d5 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java @@ -118,6 +118,7 @@ import com.android.compatibility.common.util.DeviceConfigStateHelper; import com.android.internal.util.FrameworkStatsLog; import com.android.server.am.PendingIntentRecord; import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.wm.BackgroundActivityStartController.BalVerdict; import com.android.server.wm.LaunchParamsController.LaunchParamsModifier; import com.android.server.wm.utils.MockTracker; @@ -1378,7 +1379,8 @@ public class ActivityStarterTests extends WindowTestsBase { .setUserId(10) .build(); - final int result = starter.recycleTask(task, null, null, null); + final int result = starter.recycleTask(task, null, null, null, + BalVerdict.ALLOW_BY_DEFAULT); assertThat(result == START_SUCCESS).isTrue(); assertThat(starter.mAddingToTask).isTrue(); } @@ -1892,7 +1894,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 */, - -1 /* realCallingUid */); + BalVerdict.ALLOW_BY_DEFAULT, + null /* intentGrants */, -1 /* realCallingUid */); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java index cf620fe605c6..c404c77c8550 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowPolicyControllerTests.java @@ -21,6 +21,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.server.wm.BackgroundActivityStartController.BalVerdict; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -186,7 +187,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* options */null, /* inTask */null, /* inTaskFragment */ null, - /* balCode */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, + BalVerdict.ALLOW_BY_DEFAULT, /* intentGrants */null, /* realCaiingUid */ -1); @@ -216,7 +217,7 @@ public class DisplayWindowPolicyControllerTests extends WindowTestsBase { /* options= */null, /* inTask= */null, /* inTaskFragment= */ null, - /* balCode= */ BackgroundActivityStartController.BAL_ALLOW_DEFAULT, + BalVerdict.ALLOW_BY_DEFAULT, /* intentGrants= */null, /* realCaiingUid */ -1); |