Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +23 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; import android.content.res.Configuration; Loading Loading @@ -61,6 +62,8 @@ import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import java.io.PrintWriter; /** * Records and handles layout of splits. Helps to calculate proper bounds when configuration or * divide position changes. Loading Loading @@ -415,6 +418,19 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange return bounds.width() > bounds.height(); } /** Reverse the split position. */ @SplitPosition public static int reversePosition(@SplitPosition int position) { switch (position) { case SPLIT_POSITION_TOP_OR_LEFT: return SPLIT_POSITION_BOTTOM_OR_RIGHT; case SPLIT_POSITION_BOTTOM_OR_RIGHT: return SPLIT_POSITION_TOP_OR_LEFT; default: return SPLIT_POSITION_UNDEFINED; } } /** * Return if this layout is landscape. */ Loading Loading @@ -502,6 +518,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } } /** Dumps the current split bounds recorded in this layout. */ public void dump(@NonNull PrintWriter pw, String prefix) { pw.println(prefix + "bounds1=" + mBounds1.toShortString()); pw.println(prefix + "dividerBounds=" + mDividerBounds.toShortString()); pw.println(prefix + "bounds2=" + mBounds2.toShortString()); } /** Handles layout change event. */ public interface SplitLayoutHandler { Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +0 −4 Original line number Diff line number Diff line Loading @@ -50,10 +50,6 @@ class SideStage extends StageTaskListener { wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */); } void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); } boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) { // No matter if the root task is empty or not, moving the root to bottom because it no // longer preserves visible child task. Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −22 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.app.ActivityManager; import android.app.ActivityTaskManager; Loading Loading @@ -182,30 +184,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return moveToSideStage(task, sideStagePosition); return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, new WindowContainerTransaction()); } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { private boolean moveToStage(int taskId, @SplitScreen.StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return moveToSideStage(task, sideStagePosition, wct); } public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { return mStageCoordinator.moveToSideStage(task, sideStagePosition); } public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { return mStageCoordinator.moveToSideStage(task, sideStagePosition, wct); return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct); } public boolean removeFromSideStage(int taskId) { Loading @@ -221,13 +210,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void enterSplitScreen(int taskId, boolean leftOrTop) { moveToSideStage(taskId, leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction()); } public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { moveToSideStage(taskId, leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE; final int stagePosition = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; moveToStage(taskId, stageType, stagePosition, wct); } public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) { Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +32 −18 Original line number Diff line number Diff line Loading @@ -273,18 +273,31 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSideStageListener.mVisible && mMainStageListener.mVisible; } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); return moveToSideStage(task, sideStagePosition, wct); boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { StageTaskListener targetStage; int sideStagePosition; if (stageType == STAGE_TYPE_MAIN) { targetStage = mMainStage; sideStagePosition = SplitLayout.reversePosition(stagePosition); } else if (stageType == STAGE_TYPE_SIDE) { targetStage = mSideStage; sideStagePosition = stagePosition; } else { if (mMainStage.isActive()) { // If the split screen is activated, retrieves target stage based on position. targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; sideStagePosition = mSideStagePosition; } else { targetStage = mSideStage; sideStagePosition = stagePosition; } } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); setSideStagePosition(sideStagePosition, wct); mSideStage.evictAllChildren(evictWct); mSideStage.addTask(task, wct); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); targetStage.evictAllChildren(evictWct); targetStage.addTask(task, wct); if (!evictWct.isEmpty()) { wct.merge(evictWct, true /* transfer */); } Loading Loading @@ -463,9 +476,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, case STAGE_TYPE_MAIN: { if (position != SPLIT_POSITION_UNDEFINED) { // Set the side stage opposite of what we want to the main stage. final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; setSideStagePosition(sideStagePosition, wct); setSideStagePosition(SplitLayout.reversePosition(position), wct); } else { position = getMainStagePosition(); } Loading @@ -489,8 +500,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @SplitLayout.SplitPosition int getMainStagePosition() { return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; return SplitLayout.reversePosition(mSideStagePosition); } void setSideStagePosition(@SplitPosition int sideStagePosition, Loading Loading @@ -870,8 +880,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onDoubleTappedDivider() { setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), null /* wct */); mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(), getSideStagePosition(), mSideStage.getTopChildTaskUid(), mSplitLayout.isLandscape()); Loading Loading @@ -1296,11 +1305,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(prefix + TAG + " mDisplayId=" + mDisplayId); pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible); pw.println(innerPrefix + "MainStage"); pw.println(childPrefix + "stagePosition=" + getMainStagePosition()); pw.println(childPrefix + "isActive=" + mMainStage.isActive()); mMainStageListener.dump(pw, childPrefix); pw.println(innerPrefix + "SideStage"); pw.println(childPrefix + "stagePosition=" + getSideStagePosition()); mSideStageListener.dump(pw, childPrefix); pw.println(innerPrefix + "mSplitLayout=" + mSplitLayout); if (mMainStage.isActive()) { pw.println(innerPrefix + "SplitLayout"); mSplitLayout.dump(pw, childPrefix); } } /** Loading libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +4 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,10 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); } void setBounds(Rect bounds, WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, bounds); } Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +23 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.IntDef; import android.annotation.NonNull; import android.app.ActivityManager; import android.content.Context; import android.content.res.Configuration; Loading Loading @@ -61,6 +62,8 @@ import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import java.io.PrintWriter; /** * Records and handles layout of splits. Helps to calculate proper bounds when configuration or * divide position changes. Loading Loading @@ -415,6 +418,19 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange return bounds.width() > bounds.height(); } /** Reverse the split position. */ @SplitPosition public static int reversePosition(@SplitPosition int position) { switch (position) { case SPLIT_POSITION_TOP_OR_LEFT: return SPLIT_POSITION_BOTTOM_OR_RIGHT; case SPLIT_POSITION_BOTTOM_OR_RIGHT: return SPLIT_POSITION_TOP_OR_LEFT; default: return SPLIT_POSITION_UNDEFINED; } } /** * Return if this layout is landscape. */ Loading Loading @@ -502,6 +518,13 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } } /** Dumps the current split bounds recorded in this layout. */ public void dump(@NonNull PrintWriter pw, String prefix) { pw.println(prefix + "bounds1=" + mBounds1.toShortString()); pw.println(prefix + "dividerBounds=" + mDividerBounds.toShortString()); pw.println(prefix + "bounds2=" + mBounds2.toShortString()); } /** Handles layout change event. */ public interface SplitLayoutHandler { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +0 −4 Original line number Diff line number Diff line Loading @@ -50,10 +50,6 @@ class SideStage extends StageTaskListener { wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */); } void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); } boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) { // No matter if the root task is empty or not, moving the root to bottom because it no // longer preserves visible child task. Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +12 −22 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import static android.view.RemoteAnimationTarget.MODE_OPENING; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT; import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE; import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED; import android.app.ActivityManager; import android.app.ActivityTaskManager; Loading Loading @@ -182,30 +184,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return moveToSideStage(task, sideStagePosition); return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition, new WindowContainerTransaction()); } public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { private boolean moveToStage(int taskId, @SplitScreen.StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId); if (task == null) { throw new IllegalArgumentException("Unknown taskId" + taskId); } return moveToSideStage(task, sideStagePosition, wct); } public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { return mStageCoordinator.moveToSideStage(task, sideStagePosition); } public boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { return mStageCoordinator.moveToSideStage(task, sideStagePosition, wct); return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct); } public boolean removeFromSideStage(int taskId) { Loading @@ -221,13 +210,14 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } public void enterSplitScreen(int taskId, boolean leftOrTop) { moveToSideStage(taskId, leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT); enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction()); } public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) { moveToSideStage(taskId, leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct); final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE; final int stagePosition = leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT; moveToStage(taskId, stageType, stagePosition, wct); } public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) { Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +32 −18 Original line number Diff line number Diff line Loading @@ -273,18 +273,31 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mSideStageListener.mVisible && mMainStageListener.mVisible; } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition) { final WindowContainerTransaction wct = new WindowContainerTransaction(); return moveToSideStage(task, sideStagePosition, wct); boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType, @SplitPosition int stagePosition, WindowContainerTransaction wct) { StageTaskListener targetStage; int sideStagePosition; if (stageType == STAGE_TYPE_MAIN) { targetStage = mMainStage; sideStagePosition = SplitLayout.reversePosition(stagePosition); } else if (stageType == STAGE_TYPE_SIDE) { targetStage = mSideStage; sideStagePosition = stagePosition; } else { if (mMainStage.isActive()) { // If the split screen is activated, retrieves target stage based on position. targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage; sideStagePosition = mSideStagePosition; } else { targetStage = mSideStage; sideStagePosition = stagePosition; } } boolean moveToSideStage(ActivityManager.RunningTaskInfo task, @SplitPosition int sideStagePosition, WindowContainerTransaction wct) { final WindowContainerTransaction evictWct = new WindowContainerTransaction(); setSideStagePosition(sideStagePosition, wct); mSideStage.evictAllChildren(evictWct); mSideStage.addTask(task, wct); final WindowContainerTransaction evictWct = new WindowContainerTransaction(); targetStage.evictAllChildren(evictWct); targetStage.addTask(task, wct); if (!evictWct.isEmpty()) { wct.merge(evictWct, true /* transfer */); } Loading Loading @@ -463,9 +476,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, case STAGE_TYPE_MAIN: { if (position != SPLIT_POSITION_UNDEFINED) { // Set the side stage opposite of what we want to the main stage. final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; setSideStagePosition(sideStagePosition, wct); setSideStagePosition(SplitLayout.reversePosition(position), wct); } else { position = getMainStagePosition(); } Loading @@ -489,8 +500,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @SplitLayout.SplitPosition int getMainStagePosition() { return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT; return SplitLayout.reversePosition(mSideStagePosition); } void setSideStagePosition(@SplitPosition int sideStagePosition, Loading Loading @@ -870,8 +880,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Override public void onDoubleTappedDivider() { setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */); setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), null /* wct */); mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(), getSideStagePosition(), mSideStage.getTopChildTaskUid(), mSplitLayout.isLandscape()); Loading Loading @@ -1296,11 +1305,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, pw.println(prefix + TAG + " mDisplayId=" + mDisplayId); pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible); pw.println(innerPrefix + "MainStage"); pw.println(childPrefix + "stagePosition=" + getMainStagePosition()); pw.println(childPrefix + "isActive=" + mMainStage.isActive()); mMainStageListener.dump(pw, childPrefix); pw.println(innerPrefix + "SideStage"); pw.println(childPrefix + "stagePosition=" + getSideStagePosition()); mSideStageListener.dump(pw, childPrefix); pw.println(innerPrefix + "mSplitLayout=" + mSplitLayout); if (mMainStage.isActive()) { pw.println(innerPrefix + "SplitLayout"); mSplitLayout.dump(pw, childPrefix); } } /** Loading
libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +4 −0 Original line number Diff line number Diff line Loading @@ -293,6 +293,10 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { } } void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) { wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/); } void setBounds(Rect bounds, WindowContainerTransaction wct) { wct.setBounds(mRootTaskInfo.token, bounds); } Loading