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

Commit e6fc6a3c authored by Jerry Chang's avatar Jerry Chang
Browse files

Allow children task of created-by-organizer task to be organized

Allows to organize direct child of root task created by organizer and
extends TaskInfo to reveal the parent task id.

To organize child task properly for each features, passes all child
task organizer events to the listener listening to its parent task if
feasible.

Fix: 169267298
Fix: 169266482
Test: atest WindowOrganizerTests
Test: atest SplitScreenTests
Test: atest PinnedStackTests
Test: atest WindowInsetPolicyTests
Test: atest WMShellUnitTests
Test: split screen works
Change-Id: I8e66f810c86fcdac3287adfa208d8e34786fc9b5
parent ec817350
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -286,6 +286,7 @@ package android.app {
  public class TaskInfo {
    method @NonNull public android.content.res.Configuration getConfiguration();
    method @NonNull public android.window.WindowContainerToken getToken();
    method public boolean hasParentTask();
  }

  public class TimePickerDialog extends android.app.AlertDialog implements android.content.DialogInterface.OnClickListener android.widget.TimePicker.OnTimeChangedListener {
+18 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.app;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
@@ -203,6 +205,13 @@ public class TaskInfo {
     */
    public ArrayList<IBinder> launchCookies = new ArrayList<>();

    /**
     * The identifier of the parent task that is created by organizer, otherwise
     * {@link ActivityTaskManager#INVALID_TASK_ID}.
     * @hide
     */
    public int parentTaskId;

    TaskInfo() {
        // Do nothing
    }
@@ -245,6 +254,12 @@ public class TaskInfo {
        launchCookies.add(cookie);
    }

    /** @hide */
    @TestApi
    public boolean hasParentTask() {
        return parentTaskId != INVALID_TASK_ID;
    }

    /**
     * Reads the TaskInfo from a parcel.
     */
@@ -275,6 +290,7 @@ public class TaskInfo {
        source.readBinderList(launchCookies);
        letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
        positionInParent = source.readTypedObject(Point.CREATOR);
        parentTaskId = source.readInt();
    }

    /**
@@ -308,6 +324,7 @@ public class TaskInfo {
        dest.writeBinderList(launchCookies);
        dest.writeTypedObject(letterboxActivityBounds, flags);
        dest.writeTypedObject(positionInParent, flags);
        dest.writeInt(parentTaskId);
    }

    @Override
@@ -330,6 +347,7 @@ public class TaskInfo {
                + " launchCookies" + launchCookies
                + " letterboxActivityBounds=" + letterboxActivityBounds
                + " positionInParent=" + positionInParent
                + " parentTaskId: " + parentTaskId
                + "}";
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -335,6 +335,12 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        listener = mTaskListeners.get(taskId);
        if (listener != null) return listener;

        // Next priority goes to the listener listening to its parent.
        if (runningTaskInfo.hasParentTask()) {
            listener = mTaskListeners.get(runningTaskInfo.parentTaskId);
            if (listener != null) return listener;
        }

        // Next we try type specific listeners.
        final int taskListenerType = taskInfoToTaskListenerType(runningTaskInfo);
        return mTaskListeners.get(taskListenerType);
+1 −1
Original line number Diff line number Diff line
@@ -117,7 +117,7 @@ public class SplitScreenController implements SplitScreen,
        mTransactionPool = transactionPool;
        mWindowManagerProxy = new WindowManagerProxy(syncQueue, shellTaskOrganizer);
        mTaskOrganizer = shellTaskOrganizer;
        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer);
        mSplits = new SplitScreenTaskListener(this, shellTaskOrganizer, syncQueue);
        mImePositionProcessor = new DividerImeController(mSplits, mTransactionPool, mHandler,
                shellTaskOrganizer);
        mRotationController =
+54 −2
Original line number Diff line number Diff line
@@ -27,8 +27,10 @@ import static com.android.wm.shell.ShellTaskOrganizer.getWindowingMode;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;

import android.app.ActivityManager.RunningTaskInfo;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Log;
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.view.SurfaceSession;

@@ -36,6 +38,8 @@ import androidx.annotation.NonNull;

import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.Transitions;
import com.android.wm.shell.common.SyncTransactionQueue;

import java.io.PrintWriter;

@@ -44,6 +48,8 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
    private static final boolean DEBUG = SplitScreenController.DEBUG;

    private final ShellTaskOrganizer mTaskOrganizer;
    private final SyncTransactionQueue mSyncQueue;
    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();

    RunningTaskInfo mPrimary;
    RunningTaskInfo mSecondary;
@@ -58,9 +64,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
    final SurfaceSession mSurfaceSession = new SurfaceSession();

    SplitScreenTaskListener(SplitScreenController splitScreenController,
                    ShellTaskOrganizer shellTaskOrganizer) {
                    ShellTaskOrganizer shellTaskOrganizer,
                    SyncTransactionQueue syncQueue) {
        mSplitScreenController = splitScreenController;
        mTaskOrganizer = shellTaskOrganizer;
        mSyncQueue = syncQueue;
    }

    void init() {
@@ -93,6 +101,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
    @Override
    public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
        synchronized (this) {
            if (taskInfo.hasParentTask()) {
                handleChildTaskAppeared(taskInfo, leash);
                return;
            }

            final int winMode = getWindowingMode(taskInfo);
            if (winMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
                ProtoLog.v(WM_SHELL_TASK_ORG,
@@ -139,6 +152,11 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
    @Override
    public void onTaskVanished(RunningTaskInfo taskInfo) {
        synchronized (this) {
            if (taskInfo.hasParentTask()) {
                mLeashByTaskId.remove(taskInfo.taskId);
                return;
            }

            final boolean isPrimaryTask = mPrimary != null
                    && taskInfo.token.equals(mPrimary.token);
            final boolean isSecondaryTask = mSecondary != null
@@ -165,8 +183,42 @@ class SplitScreenTaskListener implements ShellTaskOrganizer.TaskListener {
        if (taskInfo.displayId != DEFAULT_DISPLAY) {
            return;
        }
        synchronized (this) {
            if (taskInfo.hasParentTask()) {
                handleChildTaskChanged(taskInfo);
                return;
            }

            mSplitScreenController.post(() -> handleTaskInfoChanged(taskInfo));
        }
    }

    private void handleChildTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
        mLeashByTaskId.put(taskInfo.taskId, leash);
        updateChildTaskSurface(taskInfo, leash, true /* firstAppeared */);
    }

    private void handleChildTaskChanged(RunningTaskInfo taskInfo) {
        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
        updateChildTaskSurface(taskInfo, leash, false /* firstAppeared */);
    }

    private void updateChildTaskSurface(
            RunningTaskInfo taskInfo, SurfaceControl leash, boolean firstAppeared) {
        final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
        final Point taskPositionInParent = taskInfo.positionInParent;
        final Rect corp =  new Rect(taskBounds);
        corp.offset(-taskBounds.left, -taskBounds.top);
        mSyncQueue.runInSync(t -> {
            t.setWindowCrop(leash, corp);
            t.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
            if (firstAppeared && !Transitions.ENABLE_SHELL_TRANSITIONS) {
                t.setAlpha(leash, 1f);
                t.setMatrix(leash, 1, 0, 0, 1);
                t.show(leash);
            }
        });
    }

    /**
     * This is effectively a finite state machine which moves between the various split-screen
Loading