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

Commit 98b3b600 authored by Louis Chang's avatar Louis Chang
Browse files

Avoid reparenting the existing task if the launch is blocked

The activity launch was blocked by BAL, however, the existing task
was reparented to the launch-root-task. In the issue case, the task
was reparented from minized-desk to desk root task.

Bug: 434047695
Test: verified via the sample app
Test: ActivityStarterTests
Flag: com.android.window.flags.fix_bal_reparent_existing_task
Change-Id: Ieaa225dc63874c58a5d6bed7b0c6ecad4acdb4ec
parent 96b10744
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -198,3 +198,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    namespace: "windowing_sdk"
    name: "fix_bal_reparent_existing_task"
    description: "Avoid reparent existing task when the background launch is not allowed."
    bug: "434047695"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
 No newline at end of file
+18 −7
Original line number Diff line number Diff line
@@ -151,6 +151,7 @@ import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
import com.android.server.wm.BackgroundActivityStartController.BalVerdict;
import com.android.server.wm.LaunchParamsController.LaunchParams;
import com.android.server.wm.TaskFragment.EmbeddingCheckResult;
import com.android.window.flags.Flags;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -200,7 +201,8 @@ class ActivityStarter {

    // If the code is BAL_BLOCK, background activity can only be started in an existing task that
    // contains an activity with same uid, or if activity starts are enabled in developer options.
    private BalVerdict mBalVerdict;
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    BalVerdict mBalVerdict;

    private int mLaunchMode;
    private boolean mLaunchTaskBehind;
@@ -2020,7 +2022,7 @@ class ActivityStarter {
            recordTransientLaunchIfNeeded(targetTaskTop);
            // Recycle the target task for this launch.
            startResult =
                    recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants, balVerdict);
                    recycleTask(targetTask, targetTaskTop, reusedTask, intentGrants);
            if (startResult != START_SUCCESS) {
                return startResult;
            }
@@ -2383,7 +2385,7 @@ class ActivityStarter {
     */
    @VisibleForTesting
    int recycleTask(Task targetTask, ActivityRecord targetTaskTop, Task reusedTask,
            NeededUriGrants intentGrants, BalVerdict balVerdict) {
            NeededUriGrants intentGrants) {
        // Should not recycle task which is from a different user, just adding the starting
        // activity to the task.
        if (targetTask.mUserId != mStartActivity.mUserId) {
@@ -3078,11 +3080,19 @@ class ActivityStarter {
        Task intentTask = intentActivity.getTask();
        // The intent task might be reparented while in getOrCreateRootTask, caches the original
        // root task to distinguish if it is moving to front or not.
        final Task origRootTask = intentTask != null ? intentTask.getRootTask() : null;
        final Task origRootTask;
        if (Flags.fixBalReparentExistingTask()) {
            origRootTask = intentTask.getRootTask();
        } else {
            origRootTask = intentTask != null ? intentTask.getRootTask() : null;
        }

        if (mTargetRootTask == null) {
        // Update launch target task when it is not indicated.
            if (mSourceRecord != null && mSourceRecord.mLaunchRootTask != null) {
        if (mTargetRootTask == null) {
            if (Flags.fixBalReparentExistingTask() && mBalVerdict.blocks()) {
                // Stays on the same root task if the activity launch is not allowed.
                mTargetRootTask = origRootTask;
            } else if (mSourceRecord != null && mSourceRecord.mLaunchRootTask != null) {
                // Inherit the target-root-task from source to ensure trampoline activities will be
                // launched into the same root task.
                mTargetRootTask = Task.fromWindowContainerToken(mSourceRecord.mLaunchRootTask);
@@ -3388,7 +3398,8 @@ class ActivityStarter {
        return launchFlags;
    }

    private Task getOrCreateRootTask(ActivityRecord r, int launchFlags, Task task,
    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
    Task getOrCreateRootTask(ActivityRecord r, int launchFlags, Task task,
            ActivityOptions aOptions) {
        final boolean onTop =
                (aOptions == null || !aOptions.getAvoidMoveToFront()) && !mLaunchTaskBehind;
+25 −2
Original line number Diff line number Diff line
@@ -97,6 +97,7 @@ import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -1318,12 +1319,34 @@ public class ActivityStarterTests extends WindowTestsBase {
                .setUserId(10)
                .build();

        final int result = starter.recycleTask(task, null, null, null,
                BalVerdict.ALLOW_PRIVILEGED);
        final int result = starter.recycleTask(task, null, null, null);
        assertThat(result == START_SUCCESS).isTrue();
        assertThat(starter.mAddingToTask).isTrue();
    }

    @Test
    @EnableFlags(Flags.FLAG_FIX_BAL_REPARENT_EXISTING_TASK)
    public void testRecycleTaskWhenBalBlocks() {
        final ActivityStarter starter = prepareStarter(0 /* flags */);
        starter.mStartActivity = new ActivityBuilder(mAtm).build();
        starter.mBalVerdict = BalVerdict.BLOCK;
        final Task task = new TaskBuilder(mAtm.mTaskSupervisor)
                .setParentTask(createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
                        ACTIVITY_TYPE_STANDARD))
                .setCreateActivity(true)
                .build();
        final Task rootTask = task.getRootTask();
        final ActivityRecord topActivity = task.getTopMostActivity();

        spyOn(starter);
        final Task launchRootTask = new TaskBuilder(mAtm.mTaskSupervisor).build();
        doReturn(launchRootTask).when(starter).getOrCreateRootTask(eq(starter.mStartActivity),
                anyInt(), eq(task), any());

        starter.recycleTask(task, topActivity, task, null);
        assertThat(rootTask == task.getRootTask()).isTrue();
    }

    @Test
    public void testRecycleTaskWakeUpWhenDreaming() {
        doNothing().when(mWm.mAtmService.mTaskSupervisor).wakeUp(anyInt(), anyString());