Merge "Remove App pairs related codes and files" into tm-qpr-dev
This commit is contained in:
@@ -18,7 +18,6 @@ package com.android.wm.shell;
|
|||||||
|
|
||||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
||||||
|
|
||||||
import com.android.wm.shell.apppairs.AppPairsController;
|
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
import com.android.wm.shell.common.ShellExecutor;
|
||||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
||||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||||
@@ -42,7 +41,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
private final Optional<Pip> mPipOptional;
|
private final Optional<Pip> mPipOptional;
|
||||||
private final Optional<OneHandedController> mOneHandedOptional;
|
private final Optional<OneHandedController> mOneHandedOptional;
|
||||||
private final Optional<HideDisplayCutoutController> mHideDisplayCutout;
|
private final Optional<HideDisplayCutoutController> mHideDisplayCutout;
|
||||||
private final Optional<AppPairsController> mAppPairsOptional;
|
|
||||||
private final Optional<RecentTasksController> mRecentTasks;
|
private final Optional<RecentTasksController> mRecentTasks;
|
||||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||||
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
||||||
@@ -56,7 +54,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
Optional<Pip> pipOptional,
|
Optional<Pip> pipOptional,
|
||||||
Optional<OneHandedController> oneHandedOptional,
|
Optional<OneHandedController> oneHandedOptional,
|
||||||
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
||||||
Optional<AppPairsController> appPairsOptional,
|
|
||||||
Optional<RecentTasksController> recentTasks,
|
Optional<RecentTasksController> recentTasks,
|
||||||
ShellExecutor mainExecutor) {
|
ShellExecutor mainExecutor) {
|
||||||
mShellTaskOrganizer = shellTaskOrganizer;
|
mShellTaskOrganizer = shellTaskOrganizer;
|
||||||
@@ -66,7 +63,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
mPipOptional = pipOptional;
|
mPipOptional = pipOptional;
|
||||||
mOneHandedOptional = oneHandedOptional;
|
mOneHandedOptional = oneHandedOptional;
|
||||||
mHideDisplayCutout = hideDisplayCutout;
|
mHideDisplayCutout = hideDisplayCutout;
|
||||||
mAppPairsOptional = appPairsOptional;
|
|
||||||
mMainExecutor = mainExecutor;
|
mMainExecutor = mainExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,9 +80,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
|
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.println();
|
pw.println();
|
||||||
mAppPairsOptional.ifPresent(appPairs -> appPairs.dump(pw, ""));
|
|
||||||
pw.println();
|
|
||||||
pw.println();
|
|
||||||
mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw, ""));
|
mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw, ""));
|
||||||
pw.println();
|
pw.println();
|
||||||
pw.println();
|
pw.println();
|
||||||
@@ -104,10 +97,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
switch (args[1]) {
|
switch (args[1]) {
|
||||||
case "pair":
|
|
||||||
return runPair(args, pw);
|
|
||||||
case "unpair":
|
|
||||||
return runUnpair(args, pw);
|
|
||||||
case "moveToSideStage":
|
case "moveToSideStage":
|
||||||
return runMoveToSideStage(args, pw);
|
return runMoveToSideStage(args, pw);
|
||||||
case "removeFromSideStage":
|
case "removeFromSideStage":
|
||||||
@@ -121,29 +110,6 @@ public final class ShellCommandHandlerImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean runPair(String[] args, PrintWriter pw) {
|
|
||||||
if (args.length < 4) {
|
|
||||||
// First two arguments are "WMShell" and command name.
|
|
||||||
pw.println("Error: two task ids should be provided as arguments");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final int taskId1 = new Integer(args[2]);
|
|
||||||
final int taskId2 = new Integer(args[3]);
|
|
||||||
mAppPairsOptional.ifPresent(appPairs -> appPairs.pair(taskId1, taskId2));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean runUnpair(String[] args, PrintWriter pw) {
|
|
||||||
if (args.length < 3) {
|
|
||||||
// First two arguments are "WMShell" and command name.
|
|
||||||
pw.println("Error: task id should be provided as an argument");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final int taskId = new Integer(args[2]);
|
|
||||||
mAppPairsOptional.ifPresent(appPairs -> appPairs.unpair(taskId));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean runMoveToSideStage(String[] args, PrintWriter pw) {
|
private boolean runMoveToSideStage(String[] args, PrintWriter pw) {
|
||||||
if (args.length < 3) {
|
if (args.length < 3) {
|
||||||
// First arguments are "WMShell" and command name.
|
// First arguments are "WMShell" and command name.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ 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_FULLSCREEN;
|
||||||
|
|
||||||
import com.android.wm.shell.apppairs.AppPairsController;
|
|
||||||
import com.android.wm.shell.bubbles.BubbleController;
|
import com.android.wm.shell.bubbles.BubbleController;
|
||||||
import com.android.wm.shell.common.DisplayController;
|
import com.android.wm.shell.common.DisplayController;
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
import com.android.wm.shell.common.DisplayImeController;
|
||||||
@@ -54,7 +53,6 @@ public class ShellInitImpl {
|
|||||||
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
||||||
private final Optional<BubbleController> mBubblesOptional;
|
private final Optional<BubbleController> mBubblesOptional;
|
||||||
private final Optional<SplitScreenController> mSplitScreenOptional;
|
private final Optional<SplitScreenController> mSplitScreenOptional;
|
||||||
private final Optional<AppPairsController> mAppPairsOptional;
|
|
||||||
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
||||||
private final FullscreenTaskListener mFullscreenTaskListener;
|
private final FullscreenTaskListener mFullscreenTaskListener;
|
||||||
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
||||||
@@ -76,7 +74,6 @@ public class ShellInitImpl {
|
|||||||
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
||||||
Optional<BubbleController> bubblesOptional,
|
Optional<BubbleController> bubblesOptional,
|
||||||
Optional<SplitScreenController> splitScreenOptional,
|
Optional<SplitScreenController> splitScreenOptional,
|
||||||
Optional<AppPairsController> appPairsOptional,
|
|
||||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
||||||
@@ -94,7 +91,6 @@ public class ShellInitImpl {
|
|||||||
mKidsModeTaskOrganizer = kidsModeTaskOrganizer;
|
mKidsModeTaskOrganizer = kidsModeTaskOrganizer;
|
||||||
mBubblesOptional = bubblesOptional;
|
mBubblesOptional = bubblesOptional;
|
||||||
mSplitScreenOptional = splitScreenOptional;
|
mSplitScreenOptional = splitScreenOptional;
|
||||||
mAppPairsOptional = appPairsOptional;
|
|
||||||
mFullscreenTaskListener = fullscreenTaskListener;
|
mFullscreenTaskListener = fullscreenTaskListener;
|
||||||
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
||||||
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
||||||
@@ -122,7 +118,6 @@ public class ShellInitImpl {
|
|||||||
mShellTaskOrganizer.initStartingWindow(mStartingWindow);
|
mShellTaskOrganizer.initStartingWindow(mStartingWindow);
|
||||||
mShellTaskOrganizer.registerOrganizer();
|
mShellTaskOrganizer.registerOrganizer();
|
||||||
|
|
||||||
mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
|
|
||||||
mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
|
mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
|
||||||
mBubblesOptional.ifPresent(BubbleController::initialize);
|
mBubblesOptional.ifPresent(BubbleController::initialize);
|
||||||
|
|
||||||
|
|||||||
@@ -1,357 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
|
|
||||||
|
|
||||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
|
||||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
|
|
||||||
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
|
|
||||||
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.view.SurfaceControl;
|
|
||||||
import android.view.SurfaceSession;
|
|
||||||
import android.window.WindowContainerToken;
|
|
||||||
import android.window.WindowContainerTransaction;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
|
||||||
import com.android.wm.shell.common.DisplayInsetsController;
|
|
||||||
import com.android.wm.shell.common.SurfaceUtils;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
import com.android.wm.shell.common.split.SplitLayout;
|
|
||||||
import com.android.wm.shell.common.split.SplitWindowManager;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An app-pairs consisting of {@link #mRootTaskInfo} that acts as the hierarchy parent of
|
|
||||||
* {@link #mTaskInfo1} and {@link #mTaskInfo2} in the pair.
|
|
||||||
* Also includes all UI for managing the pair like the divider.
|
|
||||||
*/
|
|
||||||
class AppPair implements ShellTaskOrganizer.TaskListener, SplitLayout.SplitLayoutHandler {
|
|
||||||
private static final String TAG = AppPair.class.getSimpleName();
|
|
||||||
|
|
||||||
private ActivityManager.RunningTaskInfo mRootTaskInfo;
|
|
||||||
private SurfaceControl mRootTaskLeash;
|
|
||||||
private ActivityManager.RunningTaskInfo mTaskInfo1;
|
|
||||||
private SurfaceControl mTaskLeash1;
|
|
||||||
private ActivityManager.RunningTaskInfo mTaskInfo2;
|
|
||||||
private SurfaceControl mTaskLeash2;
|
|
||||||
private SurfaceControl mDimLayer1;
|
|
||||||
private SurfaceControl mDimLayer2;
|
|
||||||
private final SurfaceSession mSurfaceSession = new SurfaceSession();
|
|
||||||
|
|
||||||
private final AppPairsController mController;
|
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
|
||||||
private final DisplayController mDisplayController;
|
|
||||||
private final DisplayImeController mDisplayImeController;
|
|
||||||
private final DisplayInsetsController mDisplayInsetsController;
|
|
||||||
private SplitLayout mSplitLayout;
|
|
||||||
|
|
||||||
private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
|
|
||||||
new SplitWindowManager.ParentContainerCallbacks() {
|
|
||||||
@Override
|
|
||||||
public void attachToParentSurface(SurfaceControl.Builder b) {
|
|
||||||
b.setParent(mRootTaskLeash);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLeashReady(SurfaceControl leash) {
|
|
||||||
mSyncQueue.runInSync(t -> t
|
|
||||||
.show(leash)
|
|
||||||
.setLayer(leash, Integer.MAX_VALUE)
|
|
||||||
.setPosition(leash,
|
|
||||||
mSplitLayout.getDividerBounds().left,
|
|
||||||
mSplitLayout.getDividerBounds().top));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AppPair(AppPairsController controller) {
|
|
||||||
mController = controller;
|
|
||||||
mSyncQueue = controller.getSyncTransactionQueue();
|
|
||||||
mDisplayController = controller.getDisplayController();
|
|
||||||
mDisplayImeController = controller.getDisplayImeController();
|
|
||||||
mDisplayInsetsController = controller.getDisplayInsetsController();
|
|
||||||
}
|
|
||||||
|
|
||||||
int getRootTaskId() {
|
|
||||||
return mRootTaskInfo != null ? mRootTaskInfo.taskId : INVALID_TASK_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTaskId1() {
|
|
||||||
return mTaskInfo1 != null ? mTaskInfo1.taskId : INVALID_TASK_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTaskId2() {
|
|
||||||
return mTaskInfo2 != null ? mTaskInfo2.taskId : INVALID_TASK_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean contains(int taskId) {
|
|
||||||
return taskId == getRootTaskId() || taskId == getTaskId1() || taskId == getTaskId2();
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean pair(ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2) {
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "pair task1=%d task2=%d in AppPair=%s",
|
|
||||||
task1.taskId, task2.taskId, this);
|
|
||||||
|
|
||||||
if (!task1.supportsMultiWindow || !task2.supportsMultiWindow) {
|
|
||||||
ProtoLog.e(WM_SHELL_TASK_ORG,
|
|
||||||
"Can't pair tasks that doesn't support multi window, "
|
|
||||||
+ "task1.supportsMultiWindow=%b, task2.supportsMultiWindow=%b",
|
|
||||||
task1.supportsMultiWindow, task2.supportsMultiWindow);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
mTaskInfo1 = task1;
|
|
||||||
mTaskInfo2 = task2;
|
|
||||||
mSplitLayout = new SplitLayout(TAG + "SplitDivider",
|
|
||||||
mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
|
|
||||||
mRootTaskInfo.configuration, this /* layoutChangeListener */,
|
|
||||||
mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer(),
|
|
||||||
SplitLayout.PARALLAX_DISMISSING);
|
|
||||||
mDisplayInsetsController.addInsetsChangedListener(mRootTaskInfo.displayId, mSplitLayout);
|
|
||||||
|
|
||||||
final WindowContainerToken token1 = task1.token;
|
|
||||||
final WindowContainerToken token2 = task2.token;
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
|
|
||||||
wct.setHidden(mRootTaskInfo.token, false)
|
|
||||||
.reparent(token1, mRootTaskInfo.token, true /* onTop */)
|
|
||||||
.reparent(token2, mRootTaskInfo.token, true /* onTop */)
|
|
||||||
.setWindowingMode(token1, WINDOWING_MODE_MULTI_WINDOW)
|
|
||||||
.setWindowingMode(token2, WINDOWING_MODE_MULTI_WINDOW)
|
|
||||||
.setBounds(token1, mSplitLayout.getBounds1())
|
|
||||||
.setBounds(token2, mSplitLayout.getBounds2())
|
|
||||||
// Moving the root task to top after the child tasks were repareted , or the root
|
|
||||||
// task cannot be visible and focused.
|
|
||||||
.reorder(mRootTaskInfo.token, true);
|
|
||||||
mController.getTaskOrganizer().applyTransaction(wct);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unpair() {
|
|
||||||
unpair(null /* toTopToken */);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void unpair(@Nullable WindowContainerToken toTopToken) {
|
|
||||||
final WindowContainerToken token1 = mTaskInfo1.token;
|
|
||||||
final WindowContainerToken token2 = mTaskInfo2.token;
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
|
|
||||||
// Reparent out of this container and reset windowing mode.
|
|
||||||
wct.setHidden(mRootTaskInfo.token, true)
|
|
||||||
.reorder(mRootTaskInfo.token, false)
|
|
||||||
.reparent(token1, null, token1 == toTopToken /* onTop */)
|
|
||||||
.reparent(token2, null, token2 == toTopToken /* onTop */)
|
|
||||||
.setWindowingMode(token1, WINDOWING_MODE_UNDEFINED)
|
|
||||||
.setWindowingMode(token2, WINDOWING_MODE_UNDEFINED);
|
|
||||||
mController.getTaskOrganizer().applyTransaction(wct);
|
|
||||||
|
|
||||||
mTaskInfo1 = null;
|
|
||||||
mTaskInfo2 = null;
|
|
||||||
mSplitLayout.release();
|
|
||||||
mSplitLayout = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
|
|
||||||
if (mRootTaskInfo == null || taskInfo.taskId == mRootTaskInfo.taskId) {
|
|
||||||
mRootTaskInfo = taskInfo;
|
|
||||||
mRootTaskLeash = leash;
|
|
||||||
} else if (taskInfo.taskId == getTaskId1()) {
|
|
||||||
mTaskInfo1 = taskInfo;
|
|
||||||
mTaskLeash1 = leash;
|
|
||||||
mSyncQueue.runInSync(t -> mDimLayer1 =
|
|
||||||
SurfaceUtils.makeDimLayer(t, mTaskLeash1, "Dim layer", mSurfaceSession));
|
|
||||||
} else if (taskInfo.taskId == getTaskId2()) {
|
|
||||||
mTaskInfo2 = taskInfo;
|
|
||||||
mTaskLeash2 = leash;
|
|
||||||
mSyncQueue.runInSync(t -> mDimLayer2 =
|
|
||||||
SurfaceUtils.makeDimLayer(t, mTaskLeash2, "Dim layer", mSurfaceSession));
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unknown task=" + taskInfo.taskId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTaskLeash1 == null || mTaskLeash2 == null) return;
|
|
||||||
|
|
||||||
mSplitLayout.init();
|
|
||||||
|
|
||||||
mSyncQueue.runInSync(t -> t
|
|
||||||
.show(mRootTaskLeash)
|
|
||||||
.show(mTaskLeash1)
|
|
||||||
.show(mTaskLeash2)
|
|
||||||
.setPosition(mTaskLeash1,
|
|
||||||
mTaskInfo1.positionInParent.x,
|
|
||||||
mTaskInfo1.positionInParent.y)
|
|
||||||
.setPosition(mTaskLeash2,
|
|
||||||
mTaskInfo2.positionInParent.x,
|
|
||||||
mTaskInfo2.positionInParent.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
|
|
||||||
if (!taskInfo.supportsMultiWindow) {
|
|
||||||
// Dismiss AppPair if the task no longer supports multi window.
|
|
||||||
mController.unpair(mRootTaskInfo.taskId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (taskInfo.taskId == getRootTaskId()) {
|
|
||||||
if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
|
|
||||||
mSyncQueue.runInSync(t -> {
|
|
||||||
if (taskInfo.isVisible) {
|
|
||||||
t.show(mRootTaskLeash);
|
|
||||||
} else {
|
|
||||||
t.hide(mRootTaskLeash);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
mRootTaskInfo = taskInfo;
|
|
||||||
|
|
||||||
if (mSplitLayout != null
|
|
||||||
&& mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)) {
|
|
||||||
onLayoutSizeChanged(mSplitLayout);
|
|
||||||
}
|
|
||||||
} else if (taskInfo.taskId == getTaskId1()) {
|
|
||||||
mTaskInfo1 = taskInfo;
|
|
||||||
} else if (taskInfo.taskId == getTaskId2()) {
|
|
||||||
mTaskInfo2 = taskInfo;
|
|
||||||
} else {
|
|
||||||
throw new IllegalStateException("Unknown task=" + taskInfo.taskId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getSplitItemPosition(WindowContainerToken token) {
|
|
||||||
if (token == null) {
|
|
||||||
return SPLIT_POSITION_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token.equals(mTaskInfo1.getToken())) {
|
|
||||||
return SPLIT_POSITION_TOP_OR_LEFT;
|
|
||||||
} else if (token.equals(mTaskInfo2.getToken())) {
|
|
||||||
return SPLIT_POSITION_BOTTOM_OR_RIGHT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SPLIT_POSITION_UNDEFINED;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
|
||||||
if (taskInfo.taskId == getRootTaskId()) {
|
|
||||||
// We don't want to release this object back to the pool since the root task went away.
|
|
||||||
mController.unpair(mRootTaskInfo.taskId, false /* releaseToPool */);
|
|
||||||
} else if (taskInfo.taskId == getTaskId1()) {
|
|
||||||
mController.unpair(mRootTaskInfo.taskId);
|
|
||||||
mSyncQueue.runInSync(t -> t.remove(mDimLayer1));
|
|
||||||
} else if (taskInfo.taskId == getTaskId2()) {
|
|
||||||
mController.unpair(mRootTaskInfo.taskId);
|
|
||||||
mSyncQueue.runInSync(t -> t.remove(mDimLayer2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
|
||||||
b.setParent(findTaskSurface(taskId));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
|
|
||||||
SurfaceControl.Transaction t) {
|
|
||||||
t.reparent(sc, findTaskSurface(taskId));
|
|
||||||
}
|
|
||||||
|
|
||||||
private SurfaceControl findTaskSurface(int taskId) {
|
|
||||||
if (getRootTaskId() == taskId) {
|
|
||||||
return mRootTaskLeash;
|
|
||||||
} else if (getTaskId1() == taskId) {
|
|
||||||
return mTaskLeash1;
|
|
||||||
} else if (getTaskId2() == taskId) {
|
|
||||||
return mTaskLeash2;
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void dump(@NonNull PrintWriter pw, String prefix) {
|
|
||||||
final String innerPrefix = prefix + " ";
|
|
||||||
final String childPrefix = innerPrefix + " ";
|
|
||||||
pw.println(prefix + this);
|
|
||||||
if (mRootTaskInfo != null) {
|
|
||||||
pw.println(innerPrefix + "Root taskId=" + mRootTaskInfo.taskId
|
|
||||||
+ " winMode=" + mRootTaskInfo.getWindowingMode());
|
|
||||||
}
|
|
||||||
if (mTaskInfo1 != null) {
|
|
||||||
pw.println(innerPrefix + "1 taskId=" + mTaskInfo1.taskId
|
|
||||||
+ " winMode=" + mTaskInfo1.getWindowingMode());
|
|
||||||
}
|
|
||||||
if (mTaskInfo2 != null) {
|
|
||||||
pw.println(innerPrefix + "2 taskId=" + mTaskInfo2.taskId
|
|
||||||
+ " winMode=" + mTaskInfo2.getWindowingMode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return TAG + "#" + getRootTaskId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onSnappedToDismiss(boolean snappedToEnd) {
|
|
||||||
unpair(snappedToEnd ? mTaskInfo1.token : mTaskInfo2.token /* toTopToken */);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLayoutPositionChanging(SplitLayout layout) {
|
|
||||||
mSyncQueue.runInSync(t ->
|
|
||||||
layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
|
|
||||||
true /* applyResizingOffset */));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLayoutSizeChanging(SplitLayout layout) {
|
|
||||||
mSyncQueue.runInSync(t ->
|
|
||||||
layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
|
|
||||||
true /* applyResizingOffset */));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLayoutSizeChanged(SplitLayout layout) {
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
layout.applyTaskChanges(wct, mTaskInfo1, mTaskInfo2);
|
|
||||||
mSyncQueue.queue(wct);
|
|
||||||
mSyncQueue.runInSync(t ->
|
|
||||||
layout.applySurfaceChanges(t, mTaskLeash1, mTaskLeash2, mDimLayer1, mDimLayer2,
|
|
||||||
false /* applyResizingOffset */));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setLayoutOffsetTarget(int offsetX, int offsetY, SplitLayout layout) {
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
|
||||||
layout.applyLayoutOffsetTarget(wct, offsetX, offsetY, mTaskInfo1, mTaskInfo2);
|
|
||||||
mController.getTaskOrganizer().applyTransaction(wct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.android.wm.shell.common.annotations.ExternalThread;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface to engage app pairs feature.
|
|
||||||
*/
|
|
||||||
@ExternalThread
|
|
||||||
public interface AppPairs {
|
|
||||||
/** Pairs indicated tasks. */
|
|
||||||
boolean pair(int task1, int task2);
|
|
||||||
/** Pairs indicated tasks. */
|
|
||||||
boolean pair(ActivityManager.RunningTaskInfo task1, ActivityManager.RunningTaskInfo task2);
|
|
||||||
/** Unpairs any app-pair containing this task id. */
|
|
||||||
void unpair(int taskId);
|
|
||||||
}
|
|
||||||
@@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.util.Slog;
|
|
||||||
import android.util.SparseArray;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
|
||||||
import com.android.wm.shell.common.DisplayInsetsController;
|
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class manages app-pairs multitasking mode and implements the main interface {@link AppPairs}.
|
|
||||||
*/
|
|
||||||
public class AppPairsController {
|
|
||||||
private static final String TAG = AppPairsController.class.getSimpleName();
|
|
||||||
|
|
||||||
private final ShellTaskOrganizer mTaskOrganizer;
|
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
|
||||||
private final ShellExecutor mMainExecutor;
|
|
||||||
private final AppPairsImpl mImpl = new AppPairsImpl();
|
|
||||||
|
|
||||||
private AppPairsPool mPairsPool;
|
|
||||||
// Active app-pairs mapped by root task id key.
|
|
||||||
private final SparseArray<AppPair> mActiveAppPairs = new SparseArray<>();
|
|
||||||
private final DisplayController mDisplayController;
|
|
||||||
private final DisplayImeController mDisplayImeController;
|
|
||||||
private final DisplayInsetsController mDisplayInsetsController;
|
|
||||||
|
|
||||||
public AppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
|
|
||||||
DisplayController displayController, ShellExecutor mainExecutor,
|
|
||||||
DisplayImeController displayImeController,
|
|
||||||
DisplayInsetsController displayInsetsController) {
|
|
||||||
mTaskOrganizer = organizer;
|
|
||||||
mSyncQueue = syncQueue;
|
|
||||||
mDisplayController = displayController;
|
|
||||||
mDisplayImeController = displayImeController;
|
|
||||||
mDisplayInsetsController = displayInsetsController;
|
|
||||||
mMainExecutor = mainExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AppPairs asAppPairs() {
|
|
||||||
return mImpl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onOrganizerRegistered() {
|
|
||||||
if (mPairsPool == null) {
|
|
||||||
setPairsPool(new AppPairsPool(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public void setPairsPool(AppPairsPool pool) {
|
|
||||||
mPairsPool = pool;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean pair(int taskId1, int taskId2) {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = mTaskOrganizer.getRunningTaskInfo(taskId1);
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = mTaskOrganizer.getRunningTaskInfo(taskId2);
|
|
||||||
if (task1 == null || task2 == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return pair(task1, task2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean pair(ActivityManager.RunningTaskInfo task1,
|
|
||||||
ActivityManager.RunningTaskInfo task2) {
|
|
||||||
return pairInner(task1, task2) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
public AppPair pairInner(
|
|
||||||
@NonNull ActivityManager.RunningTaskInfo task1,
|
|
||||||
@NonNull ActivityManager.RunningTaskInfo task2) {
|
|
||||||
final AppPair pair = mPairsPool.acquire();
|
|
||||||
if (!pair.pair(task1, task2)) {
|
|
||||||
mPairsPool.release(pair);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
mActiveAppPairs.put(pair.getRootTaskId(), pair);
|
|
||||||
return pair;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unpair(int taskId) {
|
|
||||||
unpair(taskId, true /* releaseToPool */);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void unpair(int taskId, boolean releaseToPool) {
|
|
||||||
AppPair pair = mActiveAppPairs.get(taskId);
|
|
||||||
if (pair == null) {
|
|
||||||
for (int i = mActiveAppPairs.size() - 1; i >= 0; --i) {
|
|
||||||
final AppPair candidate = mActiveAppPairs.valueAt(i);
|
|
||||||
if (candidate.contains(taskId)) {
|
|
||||||
pair = candidate;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pair == null) {
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "taskId %d isn't isn't in an app-pair.", taskId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "unpair taskId=%d pair=%s", taskId, pair);
|
|
||||||
mActiveAppPairs.remove(pair.getRootTaskId());
|
|
||||||
pair.unpair();
|
|
||||||
if (releaseToPool) {
|
|
||||||
mPairsPool.release(pair);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellTaskOrganizer getTaskOrganizer() {
|
|
||||||
return mTaskOrganizer;
|
|
||||||
}
|
|
||||||
|
|
||||||
SyncTransactionQueue getSyncTransactionQueue() {
|
|
||||||
return mSyncQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayController getDisplayController() {
|
|
||||||
return mDisplayController;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayImeController getDisplayImeController() {
|
|
||||||
return mDisplayImeController;
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayInsetsController getDisplayInsetsController() {
|
|
||||||
return mDisplayInsetsController;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dump(@NonNull PrintWriter pw, String prefix) {
|
|
||||||
final String innerPrefix = prefix + " ";
|
|
||||||
final String childPrefix = innerPrefix + " ";
|
|
||||||
pw.println(prefix + this);
|
|
||||||
|
|
||||||
for (int i = mActiveAppPairs.size() - 1; i >= 0; --i) {
|
|
||||||
mActiveAppPairs.valueAt(i).dump(pw, childPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mPairsPool != null) {
|
|
||||||
mPairsPool.dump(pw, prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return TAG + "#" + mActiveAppPairs.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AppPairsImpl implements AppPairs {
|
|
||||||
@Override
|
|
||||||
public boolean pair(int task1, int task2) {
|
|
||||||
boolean[] result = new boolean[1];
|
|
||||||
try {
|
|
||||||
mMainExecutor.executeBlocking(() -> {
|
|
||||||
result[0] = AppPairsController.this.pair(task1, task2);
|
|
||||||
});
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
|
|
||||||
}
|
|
||||||
return result[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean pair(ActivityManager.RunningTaskInfo task1,
|
|
||||||
ActivityManager.RunningTaskInfo task2) {
|
|
||||||
boolean[] result = new boolean[1];
|
|
||||||
try {
|
|
||||||
mMainExecutor.executeBlocking(() -> {
|
|
||||||
result[0] = AppPairsController.this.pair(task1, task2);
|
|
||||||
});
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Slog.e(TAG, "Failed to pair tasks: " + task1 + ", " + task2);
|
|
||||||
}
|
|
||||||
return result[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void unpair(int taskId) {
|
|
||||||
mMainExecutor.execute(() -> {
|
|
||||||
AppPairsController.this.unpair(taskId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
|
||||||
|
|
||||||
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_TASK_ORG;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that manager pool of {@link AppPair} objects. Helps reduce the need to call system_server
|
|
||||||
* to create a root task for the app-pair when needed since we always have one ready to go.
|
|
||||||
*/
|
|
||||||
class AppPairsPool {
|
|
||||||
private static final String TAG = AppPairsPool.class.getSimpleName();
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
final AppPairsController mController;
|
|
||||||
// The pool
|
|
||||||
private final ArrayList<AppPair> mPool = new ArrayList();
|
|
||||||
|
|
||||||
AppPairsPool(AppPairsController controller) {
|
|
||||||
mController = controller;
|
|
||||||
incrementPool();
|
|
||||||
}
|
|
||||||
|
|
||||||
AppPair acquire() {
|
|
||||||
final AppPair entry = mPool.remove(mPool.size() - 1);
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "acquire entry.taskId=%s listener=%s size=%d",
|
|
||||||
entry.getRootTaskId(), entry, mPool.size());
|
|
||||||
if (mPool.size() == 0) {
|
|
||||||
incrementPool();
|
|
||||||
}
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
void release(AppPair entry) {
|
|
||||||
mPool.add(entry);
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "release entry.taskId=%s listener=%s size=%d",
|
|
||||||
entry.getRootTaskId(), entry, mPool.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
void incrementPool() {
|
|
||||||
ProtoLog.v(WM_SHELL_TASK_ORG, "incrementPool size=%d", mPool.size());
|
|
||||||
final AppPair entry = new AppPair(mController);
|
|
||||||
// TODO: multi-display...
|
|
||||||
mController.getTaskOrganizer().createRootTask(
|
|
||||||
DEFAULT_DISPLAY, WINDOWING_MODE_FULLSCREEN, entry);
|
|
||||||
mPool.add(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
@VisibleForTesting
|
|
||||||
int poolSize() {
|
|
||||||
return mPool.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dump(@NonNull PrintWriter pw, String prefix) {
|
|
||||||
final String innerPrefix = prefix + " ";
|
|
||||||
final String childPrefix = innerPrefix + " ";
|
|
||||||
pw.println(prefix + this);
|
|
||||||
for (int i = mPool.size() - 1; i >= 0; --i) {
|
|
||||||
mPool.get(i).dump(pw, childPrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return TAG + "#" + mPool.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# WM shell sub-modules apppair owner
|
|
||||||
chenghsiuchang@google.com
|
|
||||||
@@ -38,8 +38,6 @@ import com.android.wm.shell.TaskViewFactory;
|
|||||||
import com.android.wm.shell.TaskViewFactoryController;
|
import com.android.wm.shell.TaskViewFactoryController;
|
||||||
import com.android.wm.shell.TaskViewTransitions;
|
import com.android.wm.shell.TaskViewTransitions;
|
||||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||||
import com.android.wm.shell.apppairs.AppPairs;
|
|
||||||
import com.android.wm.shell.apppairs.AppPairsController;
|
|
||||||
import com.android.wm.shell.back.BackAnimation;
|
import com.android.wm.shell.back.BackAnimation;
|
||||||
import com.android.wm.shell.back.BackAnimationController;
|
import com.android.wm.shell.back.BackAnimationController;
|
||||||
import com.android.wm.shell.bubbles.BubbleController;
|
import com.android.wm.shell.bubbles.BubbleController;
|
||||||
@@ -560,17 +558,6 @@ public abstract class WMShellBaseModule {
|
|||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
// App Pairs (optional feature)
|
|
||||||
|
|
||||||
@WMSingleton
|
|
||||||
@Provides
|
|
||||||
static Optional<AppPairs> provideAppPairs(Optional<AppPairsController> appPairsController) {
|
|
||||||
return appPairsController.map((controller) -> controller.asAppPairs());
|
|
||||||
}
|
|
||||||
|
|
||||||
@BindsOptionalOf
|
|
||||||
abstract AppPairsController optionalAppPairs();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Starting window
|
// Starting window
|
||||||
//
|
//
|
||||||
@@ -651,7 +638,6 @@ public abstract class WMShellBaseModule {
|
|||||||
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
||||||
Optional<BubbleController> bubblesOptional,
|
Optional<BubbleController> bubblesOptional,
|
||||||
Optional<SplitScreenController> splitScreenOptional,
|
Optional<SplitScreenController> splitScreenOptional,
|
||||||
Optional<AppPairsController> appPairsOptional,
|
|
||||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
||||||
@@ -669,7 +655,6 @@ public abstract class WMShellBaseModule {
|
|||||||
kidsModeTaskOrganizer,
|
kidsModeTaskOrganizer,
|
||||||
bubblesOptional,
|
bubblesOptional,
|
||||||
splitScreenOptional,
|
splitScreenOptional,
|
||||||
appPairsOptional,
|
|
||||||
pipTouchHandlerOptional,
|
pipTouchHandlerOptional,
|
||||||
fullscreenTaskListener,
|
fullscreenTaskListener,
|
||||||
appUnfoldTransitionController,
|
appUnfoldTransitionController,
|
||||||
@@ -700,12 +685,11 @@ public abstract class WMShellBaseModule {
|
|||||||
Optional<Pip> pipOptional,
|
Optional<Pip> pipOptional,
|
||||||
Optional<OneHandedController> oneHandedOptional,
|
Optional<OneHandedController> oneHandedOptional,
|
||||||
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
||||||
Optional<AppPairsController> appPairsOptional,
|
|
||||||
Optional<RecentTasksController> recentTasksOptional,
|
Optional<RecentTasksController> recentTasksOptional,
|
||||||
@ShellMainThread ShellExecutor mainExecutor) {
|
@ShellMainThread ShellExecutor mainExecutor) {
|
||||||
return new ShellCommandHandlerImpl(shellTaskOrganizer, kidsModeTaskOrganizer,
|
return new ShellCommandHandlerImpl(shellTaskOrganizer, kidsModeTaskOrganizer,
|
||||||
splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
|
splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
|
||||||
appPairsOptional, recentTasksOptional, mainExecutor);
|
recentTasksOptional, mainExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
|||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.TaskViewTransitions;
|
import com.android.wm.shell.TaskViewTransitions;
|
||||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||||
import com.android.wm.shell.apppairs.AppPairsController;
|
|
||||||
import com.android.wm.shell.bubbles.BubbleController;
|
import com.android.wm.shell.bubbles.BubbleController;
|
||||||
import com.android.wm.shell.common.DisplayController;
|
import com.android.wm.shell.common.DisplayController;
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
import com.android.wm.shell.common.DisplayImeController;
|
||||||
@@ -176,17 +175,6 @@ public class WMShellModule {
|
|||||||
recentTasks, stageTaskUnfoldControllerProvider);
|
recentTasks, stageTaskUnfoldControllerProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WMSingleton
|
|
||||||
@Provides
|
|
||||||
static AppPairsController provideAppPairs(ShellTaskOrganizer shellTaskOrganizer,
|
|
||||||
SyncTransactionQueue syncQueue, DisplayController displayController,
|
|
||||||
@ShellMainThread ShellExecutor mainExecutor,
|
|
||||||
DisplayImeController displayImeController,
|
|
||||||
DisplayInsetsController displayInsetsController) {
|
|
||||||
return new AppPairsController(shellTaskOrganizer, syncQueue, displayController,
|
|
||||||
mainExecutor, displayImeController, displayInsetsController);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Pip
|
// Pip
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.flicker.apppairs
|
|
||||||
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test cold launch app from launcher. When the device doesn't support non-resizable in multi window
|
|
||||||
* {@link Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW}, app pairs should not pair
|
|
||||||
* non-resizable apps.
|
|
||||||
*
|
|
||||||
* To run this test: `atest WMShellFlickerTests:AppPairsTestCannotPairNonResizeableApps`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class AppPairsTestCannotPairNonResizeableApps(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : AppPairsTransition(testSpec) {
|
|
||||||
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
transitions {
|
|
||||||
nonResizeableApp?.launchViaIntent(wmHelper)
|
|
||||||
// TODO pair apps through normal UX flow
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, nonResizeableTaskId, pair = true))
|
|
||||||
nonResizeableApp?.run { wmHelper.waitForFullScreenApp(nonResizeableApp.component) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
override fun setup() {
|
|
||||||
super.setup()
|
|
||||||
setSupportsNonResizableMultiWindow(instrumentation, -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
override fun teardown() {
|
|
||||||
super.teardown()
|
|
||||||
resetMultiWindowConfig(instrumentation)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsInvisibleAtEnd() = testSpec.appPairsDividerIsInvisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun onlyResizeableAppWindowVisible() {
|
|
||||||
val nonResizeableApp = nonResizeableApp
|
|
||||||
require(nonResizeableApp != null) {
|
|
||||||
"Non resizeable app not initialized"
|
|
||||||
}
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowVisible(nonResizeableApp.component)
|
|
||||||
isAppWindowInvisible(primaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): List<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = AppPairsHelper.TEST_REPETITIONS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.flicker.apppairs
|
|
||||||
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test cold launch app from launcher.
|
|
||||||
* To run this test: `atest WMShellFlickerTests:AppPairsTestPairPrimaryAndSecondaryApps`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class AppPairsTestPairPrimaryAndSecondaryApps(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : AppPairsTransition(testSpec) {
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
transitions {
|
|
||||||
// TODO pair apps through normal UX flow
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
|
|
||||||
waitAppsShown(primaryApp, secondaryApp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsVisibleAtEnd() = testSpec.appPairsDividerIsVisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun bothAppWindowsVisible() {
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowVisible(primaryApp.component)
|
|
||||||
isAppWindowVisible(secondaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appsEndingBounds() {
|
|
||||||
testSpec.assertLayersEnd {
|
|
||||||
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
|
|
||||||
visibleRegion(primaryApp.component)
|
|
||||||
.coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion))
|
|
||||||
visibleRegion(secondaryApp.component)
|
|
||||||
.coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): List<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = AppPairsHelper.TEST_REPETITIONS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.view.Display
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.server.wm.traces.common.WindowManagerConditionsFactory
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test cold launch app from launcher. When the device supports non-resizable in multi window
|
|
||||||
* {@link Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW}, app pairs can pair
|
|
||||||
* non-resizable apps.
|
|
||||||
*
|
|
||||||
* To run this test: `atest WMShellFlickerTests:AppPairsTestSupportPairNonResizeableApps`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class AppPairsTestSupportPairNonResizeableApps(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : AppPairsTransition(testSpec) {
|
|
||||||
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
transitions {
|
|
||||||
nonResizeableApp?.launchViaIntent(wmHelper)
|
|
||||||
// TODO pair apps through normal UX flow
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, nonResizeableTaskId, pair = true))
|
|
||||||
val waitConditions = mutableListOf(
|
|
||||||
WindowManagerConditionsFactory.isWindowVisible(primaryApp.component),
|
|
||||||
WindowManagerConditionsFactory.isLayerVisible(primaryApp.component),
|
|
||||||
WindowManagerConditionsFactory.isAppTransitionIdle(Display.DEFAULT_DISPLAY))
|
|
||||||
|
|
||||||
nonResizeableApp?.let {
|
|
||||||
waitConditions.add(
|
|
||||||
WindowManagerConditionsFactory.isWindowVisible(nonResizeableApp.component))
|
|
||||||
waitConditions.add(
|
|
||||||
WindowManagerConditionsFactory.isLayerVisible(nonResizeableApp.component))
|
|
||||||
}
|
|
||||||
wmHelper.waitFor(*waitConditions.toTypedArray())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
override fun setup() {
|
|
||||||
super.setup()
|
|
||||||
setSupportsNonResizableMultiWindow(instrumentation, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
override fun teardown() {
|
|
||||||
super.teardown()
|
|
||||||
resetMultiWindowConfig(instrumentation)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsVisibleAtEnd() = testSpec.appPairsDividerIsVisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun bothAppWindowVisible() {
|
|
||||||
val nonResizeableApp = nonResizeableApp
|
|
||||||
require(nonResizeableApp != null) {
|
|
||||||
"Non resizeable app not initialized"
|
|
||||||
}
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowVisible(nonResizeableApp.component)
|
|
||||||
isAppWindowVisible(primaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): List<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = AppPairsHelper.TEST_REPETITIONS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.os.SystemClock
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test cold launch app from launcher.
|
|
||||||
* To run this test: `atest WMShellFlickerTests:AppPairsTestUnpairPrimaryAndSecondaryApps`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class AppPairsTestUnpairPrimaryAndSecondaryApps(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : AppPairsTransition(testSpec) {
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
setup {
|
|
||||||
eachRun {
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
|
|
||||||
waitAppsShown(primaryApp, secondaryApp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
transitions {
|
|
||||||
// TODO pair apps through normal UX flow
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, secondaryTaskId, pair = false))
|
|
||||||
SystemClock.sleep(AppPairsHelper.TIMEOUT_MS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsInvisibleAtEnd() = testSpec.appPairsDividerIsInvisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun bothAppWindowsInvisible() {
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowInvisible(primaryApp.component)
|
|
||||||
isAppWindowInvisible(secondaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appsStartingBounds() {
|
|
||||||
testSpec.assertLayersStart {
|
|
||||||
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
|
|
||||||
visibleRegion(primaryApp.component)
|
|
||||||
.coversExactly(appPairsHelper.getPrimaryBounds(dividerRegion))
|
|
||||||
visibleRegion(secondaryApp.component)
|
|
||||||
.coversExactly(appPairsHelper.getSecondaryBounds(dividerRegion))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appsEndingBounds() {
|
|
||||||
testSpec.assertLayersEnd {
|
|
||||||
notContains(primaryApp.component)
|
|
||||||
notContains(secondaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): List<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = AppPairsHelper.TEST_REPETITIONS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.app.Instrumentation
|
|
||||||
import android.content.Context
|
|
||||||
import android.system.helpers.ActivityHelper
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import com.android.server.wm.flicker.FlickerBuilderProvider
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.server.wm.flicker.helpers.setRotation
|
|
||||||
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
|
|
||||||
import com.android.server.wm.flicker.navBarLayerIsVisible
|
|
||||||
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
|
|
||||||
import com.android.server.wm.flicker.navBarWindowIsVisible
|
|
||||||
import com.android.server.wm.flicker.statusBarLayerIsVisible
|
|
||||||
import com.android.server.wm.flicker.statusBarLayerRotatesScales
|
|
||||||
import com.android.server.wm.flicker.statusBarWindowIsVisible
|
|
||||||
import com.android.server.wm.traces.parser.toFlickerComponent
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.BaseAppHelper
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.getDevEnableNonResizableMultiWindow
|
|
||||||
import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setDevEnableNonResizableMultiWindow
|
|
||||||
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
|
|
||||||
import com.android.wm.shell.flicker.testapp.Components
|
|
||||||
import org.junit.After
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
abstract class AppPairsTransition(protected val testSpec: FlickerTestParameter) {
|
|
||||||
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
|
|
||||||
protected val context: Context = instrumentation.context
|
|
||||||
protected val activityHelper = ActivityHelper.getInstance()
|
|
||||||
protected val appPairsHelper = AppPairsHelper(instrumentation,
|
|
||||||
Components.SplitScreenActivity.LABEL,
|
|
||||||
Components.SplitScreenActivity.COMPONENT.toFlickerComponent())
|
|
||||||
|
|
||||||
protected val primaryApp = SplitScreenHelper.getPrimary(instrumentation)
|
|
||||||
protected val secondaryApp = SplitScreenHelper.getSecondary(instrumentation)
|
|
||||||
protected open val nonResizeableApp: SplitScreenHelper? =
|
|
||||||
SplitScreenHelper.getNonResizeable(instrumentation)
|
|
||||||
protected var primaryTaskId = ""
|
|
||||||
protected var secondaryTaskId = ""
|
|
||||||
protected var nonResizeableTaskId = ""
|
|
||||||
private var prevDevEnableNonResizableMultiWindow = 0
|
|
||||||
|
|
||||||
@Before
|
|
||||||
open fun setup() {
|
|
||||||
prevDevEnableNonResizableMultiWindow = getDevEnableNonResizableMultiWindow(context)
|
|
||||||
if (prevDevEnableNonResizableMultiWindow != 0) {
|
|
||||||
// Turn off the development option
|
|
||||||
setDevEnableNonResizableMultiWindow(context, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
open fun teardown() {
|
|
||||||
setDevEnableNonResizableMultiWindow(context, prevDevEnableNonResizableMultiWindow)
|
|
||||||
}
|
|
||||||
|
|
||||||
@FlickerBuilderProvider
|
|
||||||
fun buildFlicker(): FlickerBuilder {
|
|
||||||
return FlickerBuilder(instrumentation).apply {
|
|
||||||
transition(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal open val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
setup {
|
|
||||||
test {
|
|
||||||
device.wakeUpAndGoToHomeScreen()
|
|
||||||
}
|
|
||||||
eachRun {
|
|
||||||
this.setRotation(testSpec.startRotation)
|
|
||||||
primaryApp.launchViaIntent(wmHelper)
|
|
||||||
secondaryApp.launchViaIntent(wmHelper)
|
|
||||||
nonResizeableApp?.launchViaIntent(wmHelper)
|
|
||||||
updateTasksId()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
teardown {
|
|
||||||
eachRun {
|
|
||||||
executeShellCommand(composePairsCommand(
|
|
||||||
primaryTaskId, secondaryTaskId, pair = false))
|
|
||||||
executeShellCommand(composePairsCommand(
|
|
||||||
primaryTaskId, nonResizeableTaskId, pair = false))
|
|
||||||
primaryApp.exit(wmHelper)
|
|
||||||
secondaryApp.exit(wmHelper)
|
|
||||||
nonResizeableApp?.exit(wmHelper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun updateTasksId() {
|
|
||||||
primaryTaskId = getTaskIdForActivity(
|
|
||||||
primaryApp.component.packageName, primaryApp.component.className).toString()
|
|
||||||
secondaryTaskId = getTaskIdForActivity(
|
|
||||||
secondaryApp.component.packageName, secondaryApp.component.className).toString()
|
|
||||||
val nonResizeableApp = nonResizeableApp
|
|
||||||
if (nonResizeableApp != null) {
|
|
||||||
nonResizeableTaskId = getTaskIdForActivity(
|
|
||||||
nonResizeableApp.component.packageName,
|
|
||||||
nonResizeableApp.component.className).toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getTaskIdForActivity(pkgName: String, activityName: String): Int {
|
|
||||||
return activityHelper.getTaskIdForActivity(pkgName, activityName)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun executeShellCommand(cmd: String) {
|
|
||||||
BaseAppHelper.executeShellCommand(instrumentation, cmd)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun composePairsCommand(
|
|
||||||
primaryApp: String,
|
|
||||||
secondaryApp: String,
|
|
||||||
pair: Boolean
|
|
||||||
): String = buildString {
|
|
||||||
// dumpsys activity service SystemUIService WMShell {pair|unpair} ${TASK_ID_1} ${TASK_ID_2}
|
|
||||||
append("dumpsys activity service SystemUIService WMShell ")
|
|
||||||
if (pair) {
|
|
||||||
append("pair ")
|
|
||||||
} else {
|
|
||||||
append("unpair ")
|
|
||||||
}
|
|
||||||
append("$primaryApp $secondaryApp")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun navBarLayerIsVisible() {
|
|
||||||
testSpec.navBarLayerIsVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun statusBarLayerIsVisible() {
|
|
||||||
testSpec.statusBarLayerIsVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun navBarWindowIsVisible() {
|
|
||||||
testSpec.navBarWindowIsVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun statusBarWindowIsVisible() {
|
|
||||||
testSpec.statusBarWindowIsVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
open fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# window manager > wm shell > Split Screen
|
|
||||||
# Bug component: 928697
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.view.Surface
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.server.wm.flicker.helpers.setRotation
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.appPairsPrimaryBoundsIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.appPairsSecondaryBoundsIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
|
|
||||||
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test open apps to app pairs and rotate.
|
|
||||||
* To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppsInAppPairsMode`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class RotateTwoLaunchedAppsInAppPairsMode(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : RotateTwoLaunchedAppsTransition(testSpec) {
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
transitions {
|
|
||||||
executeShellCommand(composePairsCommand(
|
|
||||||
primaryTaskId, secondaryTaskId, true /* pair */))
|
|
||||||
waitAppsShown(primaryApp, secondaryApp)
|
|
||||||
setRotation(testSpec.endRotation)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerIsVisible() = super.statusBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun bothAppWindowsVisible() {
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowVisible(primaryApp.component)
|
|
||||||
isAppWindowVisible(secondaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsVisibleAtEnd() = testSpec.appPairsDividerIsVisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsPrimaryBoundsIsVisibleAtEnd() =
|
|
||||||
testSpec.appPairsPrimaryBoundsIsVisibleAtEnd(testSpec.endRotation,
|
|
||||||
primaryApp.component)
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsSecondaryBoundsIsVisibleAtEnd() =
|
|
||||||
testSpec.appPairsSecondaryBoundsIsVisibleAtEnd(testSpec.endRotation,
|
|
||||||
secondaryApp.component)
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): Collection<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = SplitScreenHelper.TEST_REPETITIONS,
|
|
||||||
supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.view.Surface
|
|
||||||
import androidx.test.filters.RequiresDevice
|
|
||||||
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameterFactory
|
|
||||||
import com.android.server.wm.flicker.annotation.Group1
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.server.wm.flicker.helpers.setRotation
|
|
||||||
import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.appPairsPrimaryBoundsIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.appPairsSecondaryBoundsIsVisibleAtEnd
|
|
||||||
import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
|
|
||||||
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
|
|
||||||
import org.junit.FixMethodOrder
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.junit.runners.MethodSorters
|
|
||||||
import org.junit.runners.Parameterized
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test open apps to app pairs and rotate.
|
|
||||||
* To run this test: `atest WMShellFlickerTests:RotateTwoLaunchedAppsRotateAndEnterAppPairsMode`
|
|
||||||
*/
|
|
||||||
@RequiresDevice
|
|
||||||
@RunWith(Parameterized::class)
|
|
||||||
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
|
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
|
||||||
@Group1
|
|
||||||
class RotateTwoLaunchedAppsRotateAndEnterAppPairsMode(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : RotateTwoLaunchedAppsTransition(testSpec) {
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
super.transition(this)
|
|
||||||
transitions {
|
|
||||||
this.setRotation(testSpec.endRotation)
|
|
||||||
executeShellCommand(
|
|
||||||
composePairsCommand(primaryTaskId, secondaryTaskId, pair = true))
|
|
||||||
waitAppsShown(primaryApp, secondaryApp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsDividerIsVisibleAtEnd() = testSpec.appPairsDividerIsVisibleAtEnd()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarWindowIsVisible() = super.statusBarWindowIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerIsVisible() = super.statusBarLayerIsVisible()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun bothAppWindowsVisible() {
|
|
||||||
testSpec.assertWmEnd {
|
|
||||||
isAppWindowVisible(primaryApp.component)
|
|
||||||
isAppWindowVisible(secondaryApp.component)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsPrimaryBoundsIsVisibleAtEnd() =
|
|
||||||
testSpec.appPairsPrimaryBoundsIsVisibleAtEnd(testSpec.endRotation,
|
|
||||||
primaryApp.component)
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
fun appPairsSecondaryBoundsIsVisibleAtEnd() =
|
|
||||||
testSpec.appPairsSecondaryBoundsIsVisibleAtEnd(testSpec.endRotation,
|
|
||||||
secondaryApp.component)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
@Parameterized.Parameters(name = "{0}")
|
|
||||||
@JvmStatic
|
|
||||||
fun getParams(): Collection<FlickerTestParameter> {
|
|
||||||
return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
|
|
||||||
repetitions = SplitScreenHelper.TEST_REPETITIONS,
|
|
||||||
supportedRotations = listOf(Surface.ROTATION_90, Surface.ROTATION_270)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2021 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.flicker.apppairs
|
|
||||||
|
|
||||||
import android.view.Surface
|
|
||||||
import com.android.server.wm.flicker.FlickerTestParameter
|
|
||||||
import com.android.server.wm.flicker.dsl.FlickerBuilder
|
|
||||||
import com.android.server.wm.flicker.helpers.setRotation
|
|
||||||
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
|
|
||||||
import com.android.wm.shell.flicker.helpers.BaseAppHelper.Companion.isShellTransitionsEnabled
|
|
||||||
import com.android.wm.shell.flicker.helpers.SplitScreenHelper
|
|
||||||
import org.junit.Assume.assumeFalse
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Ignore
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
abstract class RotateTwoLaunchedAppsTransition(
|
|
||||||
testSpec: FlickerTestParameter
|
|
||||||
) : AppPairsTransition(testSpec) {
|
|
||||||
override val nonResizeableApp: SplitScreenHelper?
|
|
||||||
get() = null
|
|
||||||
|
|
||||||
override val transition: FlickerBuilder.() -> Unit
|
|
||||||
get() = {
|
|
||||||
setup {
|
|
||||||
test {
|
|
||||||
device.wakeUpAndGoToHomeScreen()
|
|
||||||
this.setRotation(Surface.ROTATION_0)
|
|
||||||
primaryApp.launchViaIntent(wmHelper)
|
|
||||||
secondaryApp.launchViaIntent(wmHelper)
|
|
||||||
updateTasksId()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
teardown {
|
|
||||||
eachRun {
|
|
||||||
executeShellCommand(composePairsCommand(
|
|
||||||
primaryTaskId, secondaryTaskId, pair = false))
|
|
||||||
primaryApp.exit(wmHelper)
|
|
||||||
secondaryApp.exit(wmHelper)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
override fun setup() {
|
|
||||||
// AppPairs hasn't been updated to Shell Transition. There will be conflict on rotation.
|
|
||||||
assumeFalse(isShellTransitionsEnabled())
|
|
||||||
super.setup()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerIsVisible() {
|
|
||||||
super.navBarLayerIsVisible()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
@Test
|
|
||||||
override fun navBarLayerRotatesAndScales() {
|
|
||||||
super.navBarLayerRotatesAndScales()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
|
||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.hardware.display.DisplayManager;
|
|
||||||
|
|
||||||
import androidx.test.annotation.UiThreadTest;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
import androidx.test.filters.SmallTest;
|
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.ShellTestCase;
|
|
||||||
import com.android.wm.shell.TestRunningTaskInfoBuilder;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.MockitoAnnotations;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for {@link AppPair}
|
|
||||||
* Build/Install/Run:
|
|
||||||
* atest WMShellUnitTests:AppPairTests
|
|
||||||
*/
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class AppPairTests extends ShellTestCase {
|
|
||||||
|
|
||||||
private AppPairsController mController;
|
|
||||||
@Mock private SyncTransactionQueue mSyncQueue;
|
|
||||||
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
|
||||||
@Mock private DisplayController mDisplayController;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
MockitoAnnotations.initMocks(this);
|
|
||||||
when(mDisplayController.getDisplayContext(anyInt())).thenReturn(mContext);
|
|
||||||
when(mDisplayController.getDisplay(anyInt())).thenReturn(
|
|
||||||
mContext.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY));
|
|
||||||
mController = new TestAppPairsController(
|
|
||||||
mTaskOrganizer,
|
|
||||||
mSyncQueue,
|
|
||||||
mDisplayController);
|
|
||||||
spyOn(mController);
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@UiThreadTest
|
|
||||||
public void testContains() {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
|
|
||||||
final AppPair pair = mController.pairInner(task1, task2);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isTrue();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isTrue();
|
|
||||||
|
|
||||||
pair.unpair();
|
|
||||||
assertThat(pair.contains(task1.taskId)).isFalse();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@UiThreadTest
|
|
||||||
public void testVanishUnpairs() {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
|
|
||||||
final AppPair pair = mController.pairInner(task1, task2);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isTrue();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isTrue();
|
|
||||||
|
|
||||||
pair.onTaskVanished(task1);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isFalse();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@UiThreadTest
|
|
||||||
public void testOnTaskInfoChanged_notSupportsMultiWindow() {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
|
|
||||||
final AppPair pair = mController.pairInner(task1, task2);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isTrue();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isTrue();
|
|
||||||
|
|
||||||
task1.supportsMultiWindow = false;
|
|
||||||
pair.onTaskInfoChanged(task1);
|
|
||||||
verify(mController).unpair(pair.getRootTaskId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
import android.hardware.display.DisplayManager;
|
|
||||||
|
|
||||||
import androidx.test.annotation.UiThreadTest;
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
import androidx.test.filters.SmallTest;
|
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.ShellTestCase;
|
|
||||||
import com.android.wm.shell.TestRunningTaskInfoBuilder;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.MockitoAnnotations;
|
|
||||||
|
|
||||||
/** Tests for {@link AppPairsController} */
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class AppPairsControllerTests extends ShellTestCase {
|
|
||||||
private TestAppPairsController mController;
|
|
||||||
private TestAppPairsPool mPool;
|
|
||||||
@Mock private SyncTransactionQueue mSyncQueue;
|
|
||||||
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
|
||||||
@Mock private DisplayController mDisplayController;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
MockitoAnnotations.initMocks(this);
|
|
||||||
when(mDisplayController.getDisplayContext(anyInt())).thenReturn(mContext);
|
|
||||||
when(mDisplayController.getDisplay(anyInt())).thenReturn(
|
|
||||||
mContext.getSystemService(DisplayManager.class).getDisplay(DEFAULT_DISPLAY));
|
|
||||||
mController = new TestAppPairsController(
|
|
||||||
mTaskOrganizer,
|
|
||||||
mSyncQueue,
|
|
||||||
mDisplayController);
|
|
||||||
mPool = mController.getPool();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@UiThreadTest
|
|
||||||
public void testPairUnpair() {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
|
|
||||||
final AppPair pair = mController.pairInner(task1, task2);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isTrue();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isTrue();
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(0);
|
|
||||||
|
|
||||||
mController.unpair(task2.taskId);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isFalse();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isFalse();
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@UiThreadTest
|
|
||||||
public void testUnpair_DontReleaseToPool() {
|
|
||||||
final ActivityManager.RunningTaskInfo task1 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
final ActivityManager.RunningTaskInfo task2 = new TestRunningTaskInfoBuilder().build();
|
|
||||||
|
|
||||||
final AppPair pair = mController.pairInner(task1, task2);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isTrue();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isTrue();
|
|
||||||
|
|
||||||
mController.unpair(task2.taskId, false /* releaseToPool */);
|
|
||||||
assertThat(pair.contains(task1.taskId)).isFalse();
|
|
||||||
assertThat(pair.contains(task2.taskId)).isFalse();
|
|
||||||
assertThat(mPool.poolSize()).isEqualTo(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
|
||||||
|
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
import androidx.test.filters.SmallTest;
|
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.ShellTestCase;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
import org.mockito.Mock;
|
|
||||||
import org.mockito.MockitoAnnotations;
|
|
||||||
|
|
||||||
/** Tests for {@link AppPairsPool} */
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
public class AppPairsPoolTests extends ShellTestCase {
|
|
||||||
private TestAppPairsController mController;
|
|
||||||
private TestAppPairsPool mPool;
|
|
||||||
@Mock private SyncTransactionQueue mSyncQueue;
|
|
||||||
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
|
||||||
@Mock private DisplayController mDisplayController;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
MockitoAnnotations.initMocks(this);
|
|
||||||
when(mDisplayController.getDisplayContext(anyInt())).thenReturn(mContext);
|
|
||||||
mController = new TestAppPairsController(
|
|
||||||
mTaskOrganizer,
|
|
||||||
mSyncQueue,
|
|
||||||
mDisplayController);
|
|
||||||
mPool = mController.getPool();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public void tearDown() {}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testInitialState() {
|
|
||||||
// Pool should always start off with at least 1 entry.
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testAcquireRelease() {
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(0);
|
|
||||||
final AppPair appPair = mPool.acquire();
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(0);
|
|
||||||
mPool.release(appPair);
|
|
||||||
assertThat(mPool.poolSize()).isGreaterThan(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
|
||||||
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
|
||||||
import com.android.wm.shell.common.DisplayController;
|
|
||||||
import com.android.wm.shell.common.DisplayImeController;
|
|
||||||
import com.android.wm.shell.common.DisplayInsetsController;
|
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
|
|
||||||
public class TestAppPairsController extends AppPairsController {
|
|
||||||
private TestAppPairsPool mPool;
|
|
||||||
|
|
||||||
public TestAppPairsController(ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue,
|
|
||||||
DisplayController displayController) {
|
|
||||||
super(organizer, syncQueue, displayController, mock(ShellExecutor.class),
|
|
||||||
mock(DisplayImeController.class), mock(DisplayInsetsController.class));
|
|
||||||
mPool = new TestAppPairsPool(this);
|
|
||||||
setPairsPool(mPool);
|
|
||||||
}
|
|
||||||
|
|
||||||
TestAppPairsPool getPool() {
|
|
||||||
return mPool;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.apppairs;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
|
||||||
|
|
||||||
import com.android.wm.shell.TestRunningTaskInfoBuilder;
|
|
||||||
|
|
||||||
public class TestAppPairsPool extends AppPairsPool{
|
|
||||||
TestAppPairsPool(AppPairsController controller) {
|
|
||||||
super(controller);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
void incrementPool() {
|
|
||||||
final AppPair entry = new AppPair(mController);
|
|
||||||
final ActivityManager.RunningTaskInfo info =
|
|
||||||
new TestRunningTaskInfoBuilder().build();
|
|
||||||
entry.onTaskAppeared(info, null /* leash */);
|
|
||||||
release(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -119,7 +119,6 @@ public class SystemUIFactory {
|
|||||||
.setBubbles(mWMComponent.getBubbles())
|
.setBubbles(mWMComponent.getBubbles())
|
||||||
.setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
|
.setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
|
||||||
.setShellCommandHandler(mWMComponent.getShellCommandHandler())
|
.setShellCommandHandler(mWMComponent.getShellCommandHandler())
|
||||||
.setAppPairs(mWMComponent.getAppPairs())
|
|
||||||
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
|
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
|
||||||
.setTransitions(mWMComponent.getTransitions())
|
.setTransitions(mWMComponent.getTransitions())
|
||||||
.setStartingSurface(mWMComponent.getStartingSurface())
|
.setStartingSurface(mWMComponent.getStartingSurface())
|
||||||
@@ -139,7 +138,6 @@ public class SystemUIFactory {
|
|||||||
.setBubbles(Optional.ofNullable(null))
|
.setBubbles(Optional.ofNullable(null))
|
||||||
.setHideDisplayCutout(Optional.ofNullable(null))
|
.setHideDisplayCutout(Optional.ofNullable(null))
|
||||||
.setShellCommandHandler(Optional.ofNullable(null))
|
.setShellCommandHandler(Optional.ofNullable(null))
|
||||||
.setAppPairs(Optional.ofNullable(null))
|
|
||||||
.setTaskViewFactory(Optional.ofNullable(null))
|
.setTaskViewFactory(Optional.ofNullable(null))
|
||||||
.setTransitions(new ShellTransitions() {})
|
.setTransitions(new ShellTransitions() {})
|
||||||
.setDisplayAreaHelper(Optional.ofNullable(null))
|
.setDisplayAreaHelper(Optional.ofNullable(null))
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import com.android.systemui.unfold.UnfoldLatencyTracker;
|
|||||||
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
|
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
|
||||||
import com.android.wm.shell.ShellCommandHandler;
|
import com.android.wm.shell.ShellCommandHandler;
|
||||||
import com.android.wm.shell.TaskViewFactory;
|
import com.android.wm.shell.TaskViewFactory;
|
||||||
import com.android.wm.shell.apppairs.AppPairs;
|
|
||||||
import com.android.wm.shell.back.BackAnimation;
|
import com.android.wm.shell.back.BackAnimation;
|
||||||
import com.android.wm.shell.bubbles.Bubbles;
|
import com.android.wm.shell.bubbles.Bubbles;
|
||||||
import com.android.wm.shell.compatui.CompatUI;
|
import com.android.wm.shell.compatui.CompatUI;
|
||||||
@@ -87,9 +86,6 @@ public interface SysUIComponent {
|
|||||||
@BindsInstance
|
@BindsInstance
|
||||||
Builder setSplitScreen(Optional<SplitScreen> s);
|
Builder setSplitScreen(Optional<SplitScreen> s);
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
Builder setAppPairs(Optional<AppPairs> s);
|
|
||||||
|
|
||||||
@BindsInstance
|
@BindsInstance
|
||||||
Builder setOneHanded(Optional<OneHanded> o);
|
Builder setOneHanded(Optional<OneHanded> o);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import com.android.systemui.tv.TvWMComponent;
|
|||||||
import com.android.wm.shell.ShellCommandHandler;
|
import com.android.wm.shell.ShellCommandHandler;
|
||||||
import com.android.wm.shell.ShellInit;
|
import com.android.wm.shell.ShellInit;
|
||||||
import com.android.wm.shell.TaskViewFactory;
|
import com.android.wm.shell.TaskViewFactory;
|
||||||
import com.android.wm.shell.apppairs.AppPairs;
|
|
||||||
import com.android.wm.shell.back.BackAnimation;
|
import com.android.wm.shell.back.BackAnimation;
|
||||||
import com.android.wm.shell.bubbles.Bubbles;
|
import com.android.wm.shell.bubbles.Bubbles;
|
||||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||||
@@ -97,9 +96,6 @@ public interface WMComponent {
|
|||||||
@WMSingleton
|
@WMSingleton
|
||||||
Optional<SplitScreen> getSplitScreen();
|
Optional<SplitScreen> getSplitScreen();
|
||||||
|
|
||||||
@WMSingleton
|
|
||||||
Optional<AppPairs> getAppPairs();
|
|
||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
Optional<Bubbles> getBubbles();
|
Optional<Bubbles> getBubbles();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user