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

Commit 2d81132f authored by Mariia Sandrikova's avatar Mariia Sandrikova
Browse files

Move letterbox task positioning to LetterboxTaskListener.

Changes:
- Introduce LetterboxTaskListerner
- Pass activity bounds and task position from WM Core to WM Shell
- Position a task from LetterboxTaskListener.

Fix: 170210431, 170213038, 168706428, 171549361
Test: go/wm-smoke
Test: atest ShellTaskOrganizerTests, LetterboxTaskListenerTest
Change-Id: I9c25b7fe1053900fe3b6eea8e71db302a0c14a5a
parent 813ea77a
Loading
Loading
Loading
Loading
+24 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
@@ -180,6 +182,20 @@ public class TaskInfo {
     */
    public boolean isResizeable;

    /**
     * Activity bounds if this task or its top activity is presented in letterbox mode and
     * {@code null} otherwise.
     * @hide
     */
    @Nullable
    public Rect letterboxActivityBounds;

    /**
     * Relative position of the task's top left corner in the parent container.
     * @hide
     */
    public Point positionInParent;

    /**
     * The launch cookies associated with activities in this task if any.
     * @see ActivityOptions#setLaunchCookie(IBinder)
@@ -256,6 +272,8 @@ public class TaskInfo {
        topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
        isResizeable = source.readBoolean();
        source.readBinderList(launchCookies);
        letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
        positionInParent = source.readTypedObject(Point.CREATOR);
    }

    /**
@@ -287,6 +305,8 @@ public class TaskInfo {
        dest.writeTypedObject(topActivityInfo, flags);
        dest.writeBoolean(isResizeable);
        dest.writeBinderList(launchCookies);
        dest.writeTypedObject(letterboxActivityBounds, flags);
        dest.writeTypedObject(positionInParent, flags);
    }

    @Override
@@ -306,6 +326,9 @@ public class TaskInfo {
                + " topActivityType=" + topActivityType
                + " pictureInPictureParams=" + pictureInPictureParams
                + " topActivityInfo=" + topActivityInfo
                + " launchCookies" + launchCookies;
                + " launchCookies" + launchCookies
                + " letterboxActivityBounds=" + letterboxActivityBounds
                + " positionInParent=" + positionInParent
                + "}";
    }
}
+18 −0
Original line number Diff line number Diff line
@@ -55,6 +55,12 @@
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
    },
    "-848099324": {
      "message": "Letterbox Task Appeared: #%d",
      "level": "VERBOSE",
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/LetterboxTaskListener.java"
    },
    "-712674749": {
      "message": "Clip description: %s",
      "level": "VERBOSE",
@@ -115,12 +121,24 @@
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/ShellTaskOrganizer.java"
    },
    "1104702476": {
      "message": "Letterbox Task Changed: #%d",
      "level": "VERBOSE",
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/LetterboxTaskListener.java"
    },
    "1184615936": {
      "message": "Set drop target window visibility: displayId=%d visibility=%d",
      "level": "VERBOSE",
      "group": "WM_SHELL_DRAG_AND_DROP",
      "at": "com\/android\/wm\/shell\/draganddrop\/DragAndDropController.java"
    },
    "1218010718": {
      "message": "Letterbox Task Vanished: #%d",
      "level": "VERBOSE",
      "group": "WM_SHELL_TASK_ORG",
      "at": "com\/android\/wm\/shell\/LetterboxTaskListener.java"
    },
    "1481772149": {
      "message": "Current target: %s",
      "level": "VERBOSE",
+6 −33
Original line number Diff line number Diff line
@@ -20,9 +20,7 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCR
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;

import android.app.ActivityManager;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.view.SurfaceControl;

@@ -39,7 +37,7 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {

    private final SyncTransactionQueue mSyncQueue;

    private final ArrayMap<Integer, SurfaceControl> mTasks = new ArrayMap<>();
    private final ArraySet<Integer> mTasks = new ArraySet<>();

    FullscreenTaskListener(SyncTransactionQueue syncQueue) {
        mSyncQueue = syncQueue;
@@ -48,17 +46,17 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
    @Override
    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        synchronized (mTasks) {
            if (mTasks.containsKey(taskInfo.taskId)) {
            if (mTasks.contains(taskInfo.taskId)) {
                throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
            }
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
                    taskInfo.taskId);
            mTasks.put(taskInfo.taskId, leash);
            mTasks.add(taskInfo.taskId);
            mSyncQueue.runInSync(t -> {
                // Reset several properties back to fullscreen (PiP, for example, leaves all these
                // properties in a bad state).
                updateSurfacePosition(t, taskInfo, leash);
                t.setWindowCrop(leash, null);
                t.setPosition(leash, 0, 0);
                // TODO(shell-transitions): Eventually set everything in transition so there's no
                //                          SF Transaction here.
                if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -73,7 +71,7 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
    @Override
    public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
        synchronized (mTasks) {
            if (mTasks.remove(taskInfo.taskId) == null) {
            if (!mTasks.remove(taskInfo.taskId)) {
                Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
                return;
            }
@@ -82,23 +80,6 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
        }
    }

    @Override
    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
        synchronized (mTasks) {
            if (!mTasks.containsKey(taskInfo.taskId)) {
                Slog.e(TAG, "Changed Task wasn't appeared or already vanished: #"
                        + taskInfo.taskId);
                return;
            }
            final SurfaceControl leash = mTasks.get(taskInfo.taskId);
            mSyncQueue.runInSync(t -> {
                // Reposition the task in case the bounds has been changed (such as Task level
                // letterboxing).
                updateSurfacePosition(t, taskInfo, leash);
            });
        }
    }

    @Override
    public void dump(@NonNull PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
@@ -112,12 +93,4 @@ class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
        return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
    }

    /** Places the Task surface to the latest position. */
    private static void updateSurfacePosition(SurfaceControl.Transaction t,
            ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        // TODO(170725334) drop this after ag/12876439
        final Configuration config = taskInfo.getConfiguration();
        final Rect bounds = config.windowConfiguration.getBounds();
        t.setPosition(leash, bounds.left, bounds.top);
    }
}
+110 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell;

import android.app.ActivityManager;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.Slog;
import android.util.SparseArray;
import android.view.SurfaceControl;

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

/**
  * Organizes a task in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN} when
  * it's presented in the letterbox mode either because orientations of a top activity and a device
  * don't match or because a top activity is in a size compat mode.
  */
final class LetterboxTaskListener implements ShellTaskOrganizer.TaskListener {
    private static final String TAG = "LetterboxTaskListener";

    private final SyncTransactionQueue mSyncQueue;

    private final SparseArray<SurfaceControl> mLeashByTaskId = new SparseArray<>();

    LetterboxTaskListener(SyncTransactionQueue syncQueue) {
        mSyncQueue = syncQueue;
    }

    @Override
    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        synchronized (mLeashByTaskId) {
            if (mLeashByTaskId.get(taskInfo.taskId) != null) {
                throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
            }
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Appeared: #%d",
                    taskInfo.taskId);
            mLeashByTaskId.put(taskInfo.taskId, leash);
            final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
            final Rect activtyBounds = taskInfo.letterboxActivityBounds;
            final Point taskPositionInParent = taskInfo.positionInParent;
            mSyncQueue.runInSync(t -> {
                setPositionAndWindowCrop(
                        t, leash, activtyBounds, taskBounds, taskPositionInParent);
                if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
                    t.setAlpha(leash, 1f);
                    t.setMatrix(leash, 1, 0, 0, 1);
                    t.show(leash);
                }
            });
        }
    }

    @Override
    public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
        synchronized (mLeashByTaskId) {
            if (mLeashByTaskId.get(taskInfo.taskId) == null) {
                Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
                return;
            }
            mLeashByTaskId.remove(taskInfo.taskId);
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Vanished: #%d",
                    taskInfo.taskId);
        }
    }

    @Override
    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
        synchronized (mLeashByTaskId) {
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Letterbox Task Changed: #%d",
                    taskInfo.taskId);
            final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
            final Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
            final Rect activtyBounds = taskInfo.letterboxActivityBounds;
            final Point taskPositionInParent = taskInfo.positionInParent;
            mSyncQueue.runInSync(t -> {
                setPositionAndWindowCrop(
                        t, leash, activtyBounds, taskBounds, taskPositionInParent);
            });
        }
    }

    private static void setPositionAndWindowCrop(
                SurfaceControl.Transaction transaction,
                SurfaceControl leash,
                final Rect activityBounds,
                final Rect taskBounds,
                final Point taskPositionInParent) {
        Rect activtyInTaskCoordinates =  new Rect(activityBounds);
        activtyInTaskCoordinates.offset(-taskBounds.left, -taskBounds.top);
        transaction.setPosition(leash, taskPositionInParent.x, taskPositionInParent.y);
        transaction.setWindowCrop(leash, activtyInTaskCoordinates);
    }
}
+12 −6
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.protolog.ShellProtoLogGroup;

import java.io.PrintWriter;
import java.util.ArrayList;
@@ -65,6 +64,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
    public static final int TASK_LISTENER_TYPE_MULTI_WINDOW = -3;
    public static final int TASK_LISTENER_TYPE_PIP = -4;
    public static final int TASK_LISTENER_TYPE_SPLIT_SCREEN = -5;
    public static final int TASK_LISTENER_TYPE_LETTERBOX = -6;

    @IntDef(prefix = {"TASK_LISTENER_TYPE_"}, value = {
            TASK_LISTENER_TYPE_UNDEFINED,
@@ -72,6 +72,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            TASK_LISTENER_TYPE_MULTI_WINDOW,
            TASK_LISTENER_TYPE_PIP,
            TASK_LISTENER_TYPE_SPLIT_SCREEN,
            TASK_LISTENER_TYPE_LETTERBOX,
    })
    public @interface TaskListenerType {}

@@ -118,6 +119,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
            ShellExecutor mainExecutor, ShellExecutor animExecutor) {
        super(taskOrganizerController, mainExecutor);
        addListenerForType(new FullscreenTaskListener(syncQueue), TASK_LISTENER_TYPE_FULLSCREEN);
        addListenerForType(new LetterboxTaskListener(syncQueue), TASK_LISTENER_TYPE_LETTERBOX);
        mTransitions = new Transitions(this, transactionPool, mainExecutor, animExecutor);
        if (Transitions.ENABLE_SHELL_TRANSITIONS) registerTransitionPlayer(mTransitions);
    }
@@ -329,8 +331,7 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        if (listener != null) return listener;

        // Next we try type specific listeners.
        final int windowingMode = getWindowingMode(runningTaskInfo);
        final int taskListenerType = windowingModeToTaskListenerType(windowingMode);
        final int taskListenerType = taskInfoToTaskListenerType(runningTaskInfo);
        return mTaskListeners.get(taskListenerType);
    }

@@ -339,11 +340,14 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        return taskInfo.configuration.windowConfiguration.getWindowingMode();
    }

    private static @TaskListenerType int windowingModeToTaskListenerType(
            @WindowingMode int windowingMode) {
    @VisibleForTesting
    static @TaskListenerType int taskInfoToTaskListenerType(RunningTaskInfo runningTaskInfo) {
        final int windowingMode = getWindowingMode(runningTaskInfo);
        switch (windowingMode) {
            case WINDOWING_MODE_FULLSCREEN:
                return TASK_LISTENER_TYPE_FULLSCREEN;
                return runningTaskInfo.letterboxActivityBounds != null
                        ? TASK_LISTENER_TYPE_LETTERBOX
                        : TASK_LISTENER_TYPE_FULLSCREEN;
            case WINDOWING_MODE_MULTI_WINDOW:
                return TASK_LISTENER_TYPE_MULTI_WINDOW;
            case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
@@ -362,6 +366,8 @@ public class ShellTaskOrganizer extends TaskOrganizer {
        switch (type) {
            case TASK_LISTENER_TYPE_FULLSCREEN:
                return "TASK_LISTENER_TYPE_FULLSCREEN";
            case TASK_LISTENER_TYPE_LETTERBOX:
                return "TASK_LISTENER_TYPE_LETTERBOX";
            case TASK_LISTENER_TYPE_MULTI_WINDOW:
                return "TASK_LISTENER_TYPE_MULTI_WINDOW";
            case TASK_LISTENER_TYPE_SPLIT_SCREEN:
Loading