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

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

Clean up LetterboxTaskListerner and all related logic.

This is the first step towards moving letterbox gravity logic from WM Shell to WM Core. It's important to do this even before the new implementation in WM Core is ready because surface repositioning in WM Shell causes visible flickering on rotation for all apps on devices with cutout.

Fix: 174632285
Bug: 175212232
Fix: 173440321
Test: atest WMShellUnitTests
Change-Id: I2b3706a1a46bb2c7ee4bb3789fb09b216e32f290
parent f2f545d7
Loading
Loading
Loading
Loading
+0 −45
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ 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.Build;
import android.os.IBinder;
import android.os.Parcel;
@@ -186,22 +185,6 @@ 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;

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

    /**
     * Relative position of the task's top left corner in the parent container.
     * @hide
@@ -222,12 +205,6 @@ public class TaskInfo {
     */
    public int parentTaskId;

    /**
     * Parent bounds.
     * @hide
     */
    public Rect parentBounds;

    /**
     * Whether this task is focused.
     * @hide
@@ -320,7 +297,6 @@ public class TaskInfo {
        return topActivityType == that.topActivityType
                && isResizeable == that.isResizeable
                && Objects.equals(positionInParent, that.positionInParent)
                && equalsLetterboxParams(that)
                && Objects.equals(pictureInPictureParams, that.pictureInPictureParams)
                && getWindowingMode() == that.getWindowingMode()
                && Objects.equals(taskDescription, that.taskDescription)
@@ -328,18 +304,6 @@ public class TaskInfo {
                && isVisible == that.isVisible;
    }

    private boolean equalsLetterboxParams(TaskInfo that) {
        return Objects.equals(letterboxActivityBounds, that.letterboxActivityBounds)
                && Objects.equals(
                        getConfiguration().windowConfiguration.getBounds(),
                        that.getConfiguration().windowConfiguration.getBounds())
                && Objects.equals(
                        getConfiguration().windowConfiguration.getMaxBounds(),
                        that.getConfiguration().windowConfiguration.getMaxBounds())
                && Objects.equals(parentBounds, that.parentBounds)
                && Objects.equals(letterboxActivityInsets, that.letterboxActivityInsets);
    }

    /**
     * Reads the TaskInfo from a parcel.
     */
@@ -368,13 +332,10 @@ public class TaskInfo {
        topActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
        isResizeable = source.readBoolean();
        source.readBinderList(launchCookies);
        letterboxActivityBounds = source.readTypedObject(Rect.CREATOR);
        positionInParent = source.readTypedObject(Point.CREATOR);
        parentTaskId = source.readInt();
        parentBounds = source.readTypedObject(Rect.CREATOR);
        isFocused = source.readBoolean();
        isVisible = source.readBoolean();
        letterboxActivityInsets = source.readTypedObject(Rect.CREATOR);
    }

    /**
@@ -406,13 +367,10 @@ public class TaskInfo {
        dest.writeTypedObject(topActivityInfo, flags);
        dest.writeBoolean(isResizeable);
        dest.writeBinderList(launchCookies);
        dest.writeTypedObject(letterboxActivityBounds, flags);
        dest.writeTypedObject(positionInParent, flags);
        dest.writeInt(parentTaskId);
        dest.writeTypedObject(parentBounds, flags);
        dest.writeBoolean(isFocused);
        dest.writeBoolean(isVisible);
        dest.writeTypedObject(letterboxActivityInsets, flags);
    }

    @Override
@@ -433,13 +391,10 @@ public class TaskInfo {
                + " pictureInPictureParams=" + pictureInPictureParams
                + " topActivityInfo=" + topActivityInfo
                + " launchCookies=" + launchCookies
                + " letterboxActivityBounds=" + letterboxActivityBounds
                + " positionInParent=" + positionInParent
                + " parentTaskId=" + parentTaskId
                + " parentBounds=" + parentBounds
                + " isFocused=" + isFocused
                + " isVisible=" + isVisible
                + " letterboxActivityInsets=" + letterboxActivityInsets
                + "}";
    }
}
+0 −12
Original line number Diff line number Diff line
@@ -42,16 +42,4 @@
    <!-- Bounds [left top right bottom] on screen for picture-in-picture (PIP) windows,
     when the PIP menu is shown in center. -->
    <string translatable="false" name="pip_menu_bounds">"596 280 1324 690"</string>

    <!-- Gravity of letterboxed apps in portrait screen orientation.
         Can be Gravity.TOP, Gravity.CENTER or Gravity.BOTTOM.
         Any other value will result in runtime exception for a letterboxed activity.
         Default is Gravity.TOP. -->
    <integer name="config_letterboxPortraitGravity">0x00000030</integer>

    <!-- Gravity of letterboxed apps in landscape screen orientation.
         Can be Gravity.LEFT, Gravity.CENTER or Gravity.RIGHT.
         Any other value will result in runtime exception for a letterboxed activity.
         Default is Gravity.CENTER. -->
    <integer name="config_letterboxLandscapeGravity">0x00000011</integer>
</resources>
+36 −30
Original line number Diff line number Diff line
@@ -20,8 +20,9 @@ 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.util.ArraySet;
import android.graphics.Point;
import android.util.Slog;
import android.util.SparseArray;
import android.view.SurfaceControl;

import androidx.annotation.NonNull;
@@ -40,7 +41,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {

    private final SyncTransactionQueue mSyncQueue;

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

    public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
        mSyncQueue = syncQueue;
@@ -48,18 +49,18 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {

    @Override
    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
        synchronized (mTasks) {
            if (mTasks.contains(taskInfo.taskId)) {
                throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
        if (mLeashByTaskId.get(taskInfo.taskId) != null) {
            throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
        }
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
                taskInfo.taskId);
            mTasks.add(taskInfo.taskId);
        mLeashByTaskId.put(taskInfo.taskId, leash);
        final Point positionInParent = taskInfo.positionInParent;
        mSyncQueue.runInSync(t -> {
            // Reset several properties back to fullscreen (PiP, for example, leaves all these
            // properties in a bad state).
            t.setWindowCrop(leash, null);
                t.setPosition(leash, 0, 0);
            t.setPosition(leash, positionInParent.x, positionInParent.y);
            // TODO(shell-transitions): Eventually set everything in transition so there's no
            //                          SF Transaction here.
            if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -69,26 +70,31 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
            }
        });
    }

    @Override
    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
        final SurfaceControl leash = mLeashByTaskId.get(taskInfo.taskId);
        final Point positionInParent = taskInfo.positionInParent;
        mSyncQueue.runInSync(t -> t.setPosition(leash, positionInParent.x, positionInParent.y));
    }

    @Override
    public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
        synchronized (mTasks) {
            if (!mTasks.remove(taskInfo.taskId)) {
        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, "Fullscreen Task Vanished: #%d",
                taskInfo.taskId);
    }
    }

    @Override
    public void dump(@NonNull PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        final String childPrefix = innerPrefix + "  ";
        pw.println(prefix + this);
        pw.println(innerPrefix + mTasks.size() + " Tasks");
        pw.println(innerPrefix + mLeashByTaskId.size() + " Tasks");
    }

    @Override
+1 −107
Original line number Diff line number Diff line
@@ -16,12 +16,9 @@

package com.android.wm.shell;

import android.view.Gravity;

import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
import com.android.wm.shell.letterbox.LetterboxConfigController;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.splitscreen.SplitScreen;
@@ -42,7 +39,6 @@ public final class ShellCommandHandler {
    private final Optional<HideDisplayCutout> mHideDisplayCutout;
    private final ShellTaskOrganizer mShellTaskOrganizer;
    private final Optional<AppPairs> mAppPairsOptional;
    private final LetterboxConfigController mLetterboxConfigController;

    public ShellCommandHandler(
            ShellTaskOrganizer shellTaskOrganizer,
@@ -50,15 +46,13 @@ public final class ShellCommandHandler {
            Optional<Pip> pipOptional,
            Optional<OneHanded> oneHandedOptional,
            Optional<HideDisplayCutout> hideDisplayCutout,
            Optional<AppPairs> appPairsOptional,
            LetterboxConfigController letterboxConfigController) {
            Optional<AppPairs> appPairsOptional) {
        mShellTaskOrganizer = shellTaskOrganizer;
        mSplitScreenOptional = splitScreenOptional;
        mPipOptional = pipOptional;
        mOneHandedOptional = oneHandedOptional;
        mHideDisplayCutout = hideDisplayCutout;
        mAppPairsOptional = appPairsOptional;
        mLetterboxConfigController = letterboxConfigController;
    }

    /** Dumps WM Shell internal state. */
@@ -85,14 +79,6 @@ public final class ShellCommandHandler {
            return false;
        }
        switch (args[1]) {
            case "set-letterbox-portrait-gravity":
                return runSetLetterboxPortraitGravity(args, pw);
            case "get-letterbox-portrait-gravity":
                return runGetLetterboxPortraitGravity(pw);
            case "set-letterbox-landscape-gravity":
                return runSetLetterboxLandscapeGravity(args, pw);
            case "get-letterbox-landscape-gravity":
                return runGetLetterboxLandscapeGravity(pw);
            case "pair":
                return runPair(args, pw);
            case "unpair":
@@ -104,92 +90,6 @@ public final class ShellCommandHandler {
        }
    }

    private boolean runSetLetterboxPortraitGravity(String[] args, PrintWriter pw) {
        if (args.length < 3) {
            // First two arguments are "WMShell" and command name.
            pw.println("Error: reset, TOP, CENTER or BOTTOM should be provided as an argument");
            return true;
        }
        switch (args[2]) {
            case "reset":
                mLetterboxConfigController.resetPortraitGravity();
                break;
            case "TOP":
                mLetterboxConfigController.setPortraitGravity(Gravity.TOP);
                break;
            case "CENTER":
                mLetterboxConfigController.setPortraitGravity(Gravity.CENTER);
                break;
            case "BOTTOM":
                mLetterboxConfigController.setPortraitGravity(Gravity.BOTTOM);
                break;
            default:
                pw.println("Error: expected reset, TOP, CENTER or BOTTOM but got " + args[2]);
        }
        return true;
    }

    private boolean runGetLetterboxPortraitGravity(PrintWriter pw) {
        final int gravity = mLetterboxConfigController.getPortraitGravity();
        switch (gravity) {
            case Gravity.TOP:
                pw.println("TOP");
                break;
            case Gravity.CENTER:
                pw.println("CENTER");
                break;
            case Gravity.BOTTOM:
                pw.println("BOTTOM");
                break;
            default:
                throw new AssertionError("Unexpected gravity: " + gravity);
        }
        return true;
    }

    private boolean runSetLetterboxLandscapeGravity(String[] args, PrintWriter pw) {
        if (args.length < 3) {
            // First two arguments are "WMShell" and command name.
            pw.println("Error: reset, LEFT, CENTER or RIGHT should be provided as an argument");
            return false;
        }
        switch (args[2]) {
            case "reset":
                mLetterboxConfigController.resetLandscapeGravity();
                break;
            case "LEFT":
                mLetterboxConfigController.setLandscapeGravity(Gravity.LEFT);
                break;
            case "CENTER":
                mLetterboxConfigController.setLandscapeGravity(Gravity.CENTER);
                break;
            case "RIGHT":
                mLetterboxConfigController.setLandscapeGravity(Gravity.RIGHT);
                break;
            default:
                pw.println(
                        "Error: expected reset, LEFT, CENTER or RIGHT but got " + args[2]);
        }
        return true;
    }

    private boolean runGetLetterboxLandscapeGravity(PrintWriter pw) {
        final int gravity = mLetterboxConfigController.getLandscapeGravity();
        switch (gravity) {
            case Gravity.LEFT:
                pw.println("LEFT");
                break;
            case Gravity.CENTER:
                pw.println("CENTER");
                break;
            case Gravity.RIGHT:
                pw.println("RIGHT");
                break;
            default:
                throw new AssertionError("Unexpected gravity: " + gravity);
        }
        return true;
    }

    private boolean runPair(String[] args, PrintWriter pw) {
        if (args.length < 4) {
@@ -220,12 +120,6 @@ public final class ShellCommandHandler {
        pw.println("      Print this help text.");
        pw.println("  <no arguments provided>");
        pw.println("    Dump Window Manager Shell internal state");
        pw.println("  set-letterbox-portrait-gravity [reset|TOP|CENTER|BOTTOM]");
        pw.println("  get-letterbox-portrait-gravity");
        pw.println("    Set, reset or print letterbox gravity for portrait screen mode.");
        pw.println("  set-letterbox-landscape-gravity [reset|LEFT|CENTER|RIGHT]");
        pw.println("  get-letterbox-landscape-gravity");
        pw.println("    Set, reset or print letterbox gravity for landscape screen mode.");
        pw.println("  pair <taskId1> <taskId2>");
        pw.println("  unpair <taskId>");
        pw.println("    Pairs/unpairs tasks with given ids.");
+0 −7
Original line number Diff line number Diff line
@@ -17,13 +17,11 @@
package com.android.wm.shell;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_LETTERBOX;

import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.letterbox.LetterboxTaskListener;
import com.android.wm.shell.splitscreen.SplitScreen;

import java.util.Optional;
@@ -38,7 +36,6 @@ public class ShellInit {
    private final ShellTaskOrganizer mShellTaskOrganizer;
    private final Optional<SplitScreen> mSplitScreenOptional;
    private final Optional<AppPairs> mAppPairsOptional;
    private final LetterboxTaskListener mLetterboxTaskListener;
    private final FullscreenTaskListener mFullscreenTaskListener;
    private final Transitions mTransitions;

@@ -47,7 +44,6 @@ public class ShellInit {
            ShellTaskOrganizer shellTaskOrganizer,
            Optional<SplitScreen> splitScreenOptional,
            Optional<AppPairs> appPairsOptional,
            LetterboxTaskListener letterboxTaskListener,
            FullscreenTaskListener fullscreenTaskListener,
            Transitions transitions) {
        mDisplayImeController = displayImeController;
@@ -55,7 +51,6 @@ public class ShellInit {
        mShellTaskOrganizer = shellTaskOrganizer;
        mSplitScreenOptional = splitScreenOptional;
        mAppPairsOptional = appPairsOptional;
        mLetterboxTaskListener = letterboxTaskListener;
        mFullscreenTaskListener = fullscreenTaskListener;
        mTransitions = transitions;
    }
@@ -65,8 +60,6 @@ public class ShellInit {
        // Start listening for display changes
        mDisplayImeController.startMonitorDisplays();

        mShellTaskOrganizer.addListenerForType(
                mLetterboxTaskListener, TASK_LISTENER_TYPE_LETTERBOX);
        mShellTaskOrganizer.addListenerForType(
                mFullscreenTaskListener, TASK_LISTENER_TYPE_FULLSCREEN);
        // Register the shell organizer
Loading