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 com.android.wm.shell.apppairs.AppPairsController;
|
||||
import com.android.wm.shell.common.ShellExecutor;
|
||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||
@@ -42,7 +41,6 @@ public final class ShellCommandHandlerImpl {
|
||||
private final Optional<Pip> mPipOptional;
|
||||
private final Optional<OneHandedController> mOneHandedOptional;
|
||||
private final Optional<HideDisplayCutoutController> mHideDisplayCutout;
|
||||
private final Optional<AppPairsController> mAppPairsOptional;
|
||||
private final Optional<RecentTasksController> mRecentTasks;
|
||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
||||
@@ -56,7 +54,6 @@ public final class ShellCommandHandlerImpl {
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<OneHandedController> oneHandedOptional,
|
||||
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
||||
Optional<AppPairsController> appPairsOptional,
|
||||
Optional<RecentTasksController> recentTasks,
|
||||
ShellExecutor mainExecutor) {
|
||||
mShellTaskOrganizer = shellTaskOrganizer;
|
||||
@@ -66,7 +63,6 @@ public final class ShellCommandHandlerImpl {
|
||||
mPipOptional = pipOptional;
|
||||
mOneHandedOptional = oneHandedOptional;
|
||||
mHideDisplayCutout = hideDisplayCutout;
|
||||
mAppPairsOptional = appPairsOptional;
|
||||
mMainExecutor = mainExecutor;
|
||||
}
|
||||
|
||||
@@ -84,9 +80,6 @@ public final class ShellCommandHandlerImpl {
|
||||
mHideDisplayCutout.ifPresent(hideDisplayCutout -> hideDisplayCutout.dump(pw));
|
||||
pw.println();
|
||||
pw.println();
|
||||
mAppPairsOptional.ifPresent(appPairs -> appPairs.dump(pw, ""));
|
||||
pw.println();
|
||||
pw.println();
|
||||
mSplitScreenOptional.ifPresent(splitScreen -> splitScreen.dump(pw, ""));
|
||||
pw.println();
|
||||
pw.println();
|
||||
@@ -104,10 +97,6 @@ public final class ShellCommandHandlerImpl {
|
||||
return false;
|
||||
}
|
||||
switch (args[1]) {
|
||||
case "pair":
|
||||
return runPair(args, pw);
|
||||
case "unpair":
|
||||
return runUnpair(args, pw);
|
||||
case "moveToSideStage":
|
||||
return runMoveToSideStage(args, pw);
|
||||
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) {
|
||||
if (args.length < 3) {
|
||||
// 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 com.android.wm.shell.apppairs.AppPairsController;
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
@@ -54,7 +53,6 @@ public class ShellInitImpl {
|
||||
private final KidsModeTaskOrganizer mKidsModeTaskOrganizer;
|
||||
private final Optional<BubbleController> mBubblesOptional;
|
||||
private final Optional<SplitScreenController> mSplitScreenOptional;
|
||||
private final Optional<AppPairsController> mAppPairsOptional;
|
||||
private final Optional<PipTouchHandler> mPipTouchHandlerOptional;
|
||||
private final FullscreenTaskListener mFullscreenTaskListener;
|
||||
private final Optional<FullscreenUnfoldController> mFullscreenUnfoldController;
|
||||
@@ -76,7 +74,6 @@ public class ShellInitImpl {
|
||||
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
||||
Optional<BubbleController> bubblesOptional,
|
||||
Optional<SplitScreenController> splitScreenOptional,
|
||||
Optional<AppPairsController> appPairsOptional,
|
||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
|
||||
@@ -94,7 +91,6 @@ public class ShellInitImpl {
|
||||
mKidsModeTaskOrganizer = kidsModeTaskOrganizer;
|
||||
mBubblesOptional = bubblesOptional;
|
||||
mSplitScreenOptional = splitScreenOptional;
|
||||
mAppPairsOptional = appPairsOptional;
|
||||
mFullscreenTaskListener = fullscreenTaskListener;
|
||||
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
||||
mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
|
||||
@@ -122,7 +118,6 @@ public class ShellInitImpl {
|
||||
mShellTaskOrganizer.initStartingWindow(mStartingWindow);
|
||||
mShellTaskOrganizer.registerOrganizer();
|
||||
|
||||
mAppPairsOptional.ifPresent(AppPairsController::onOrganizerRegistered);
|
||||
mSplitScreenOptional.ifPresent(SplitScreenController::onOrganizerRegistered);
|
||||
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.TaskViewTransitions;
|
||||
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.BackAnimationController;
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
@@ -560,17 +558,6 @@ public abstract class WMShellBaseModule {
|
||||
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
|
||||
//
|
||||
@@ -651,7 +638,6 @@ public abstract class WMShellBaseModule {
|
||||
KidsModeTaskOrganizer kidsModeTaskOrganizer,
|
||||
Optional<BubbleController> bubblesOptional,
|
||||
Optional<SplitScreenController> splitScreenOptional,
|
||||
Optional<AppPairsController> appPairsOptional,
|
||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Optional<FullscreenUnfoldController> appUnfoldTransitionController,
|
||||
@@ -669,7 +655,6 @@ public abstract class WMShellBaseModule {
|
||||
kidsModeTaskOrganizer,
|
||||
bubblesOptional,
|
||||
splitScreenOptional,
|
||||
appPairsOptional,
|
||||
pipTouchHandlerOptional,
|
||||
fullscreenTaskListener,
|
||||
appUnfoldTransitionController,
|
||||
@@ -700,12 +685,11 @@ public abstract class WMShellBaseModule {
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<OneHandedController> oneHandedOptional,
|
||||
Optional<HideDisplayCutoutController> hideDisplayCutout,
|
||||
Optional<AppPairsController> appPairsOptional,
|
||||
Optional<RecentTasksController> recentTasksOptional,
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new ShellCommandHandlerImpl(shellTaskOrganizer, kidsModeTaskOrganizer,
|
||||
splitScreenOptional, pipOptional, oneHandedOptional, hideDisplayCutout,
|
||||
appPairsOptional, recentTasksOptional, mainExecutor);
|
||||
recentTasksOptional, mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
@@ -29,7 +29,6 @@ import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
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.common.DisplayController;
|
||||
import com.android.wm.shell.common.DisplayImeController;
|
||||
@@ -176,17 +175,6 @@ public class WMShellModule {
|
||||
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
|
||||
//
|
||||
|
||||
@@ -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())
|
||||
.setHideDisplayCutout(mWMComponent.getHideDisplayCutout())
|
||||
.setShellCommandHandler(mWMComponent.getShellCommandHandler())
|
||||
.setAppPairs(mWMComponent.getAppPairs())
|
||||
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
|
||||
.setTransitions(mWMComponent.getTransitions())
|
||||
.setStartingSurface(mWMComponent.getStartingSurface())
|
||||
@@ -139,7 +138,6 @@ public class SystemUIFactory {
|
||||
.setBubbles(Optional.ofNullable(null))
|
||||
.setHideDisplayCutout(Optional.ofNullable(null))
|
||||
.setShellCommandHandler(Optional.ofNullable(null))
|
||||
.setAppPairs(Optional.ofNullable(null))
|
||||
.setTaskViewFactory(Optional.ofNullable(null))
|
||||
.setTransitions(new ShellTransitions() {})
|
||||
.setDisplayAreaHelper(Optional.ofNullable(null))
|
||||
|
||||
@@ -39,7 +39,6 @@ import com.android.systemui.unfold.UnfoldLatencyTracker;
|
||||
import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
|
||||
import com.android.wm.shell.ShellCommandHandler;
|
||||
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.bubbles.Bubbles;
|
||||
import com.android.wm.shell.compatui.CompatUI;
|
||||
@@ -87,9 +86,6 @@ public interface SysUIComponent {
|
||||
@BindsInstance
|
||||
Builder setSplitScreen(Optional<SplitScreen> s);
|
||||
|
||||
@BindsInstance
|
||||
Builder setAppPairs(Optional<AppPairs> s);
|
||||
|
||||
@BindsInstance
|
||||
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.ShellInit;
|
||||
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.bubbles.Bubbles;
|
||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||
@@ -97,9 +96,6 @@ public interface WMComponent {
|
||||
@WMSingleton
|
||||
Optional<SplitScreen> getSplitScreen();
|
||||
|
||||
@WMSingleton
|
||||
Optional<AppPairs> getAppPairs();
|
||||
|
||||
@WMSingleton
|
||||
Optional<Bubbles> getBubbles();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user