Merge "Hook-up TaskView/bubbles to shell transition"
This commit is contained in:
@@ -41,6 +41,7 @@ import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -77,6 +78,7 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
private final ShellTaskOrganizer mTaskOrganizer;
|
||||
private final Executor mShellExecutor;
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
private final TaskViewTransitions mTaskViewTransitions;
|
||||
|
||||
private ActivityManager.RunningTaskInfo mTaskInfo;
|
||||
private WindowContainerToken mTaskToken;
|
||||
@@ -92,17 +94,27 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
private final Rect mTmpRootRect = new Rect();
|
||||
private final int[] mTmpLocation = new int[2];
|
||||
|
||||
public TaskView(Context context, ShellTaskOrganizer organizer, SyncTransactionQueue syncQueue) {
|
||||
public TaskView(Context context, ShellTaskOrganizer organizer,
|
||||
TaskViewTransitions taskViewTransitions, SyncTransactionQueue syncQueue) {
|
||||
super(context, null, 0, 0, true /* disableBackgroundLayer */);
|
||||
|
||||
mTaskOrganizer = organizer;
|
||||
mShellExecutor = organizer.getExecutor();
|
||||
mSyncQueue = syncQueue;
|
||||
mTaskViewTransitions = taskViewTransitions;
|
||||
if (mTaskViewTransitions != null) {
|
||||
mTaskViewTransitions.addTaskView(this);
|
||||
}
|
||||
setUseAlpha();
|
||||
getHolder().addCallback(this);
|
||||
mGuard.open("release");
|
||||
}
|
||||
|
||||
/** Until all users are converted, we may have mixed-use (eg. Car). */
|
||||
private boolean isUsingShellTransitions() {
|
||||
return mTaskViewTransitions != null && Transitions.ENABLE_SHELL_TRANSITIONS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only one listener may be set on the view, throws an exception otherwise.
|
||||
*/
|
||||
@@ -129,6 +141,14 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
@NonNull ActivityOptions options, @Nullable Rect launchBounds) {
|
||||
prepareActivityOptions(options, launchBounds);
|
||||
LauncherApps service = mContext.getSystemService(LauncherApps.class);
|
||||
if (isUsingShellTransitions()) {
|
||||
mShellExecutor.execute(() -> {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.startShortcut(mContext.getPackageName(), shortcut, options.toBundle());
|
||||
mTaskViewTransitions.startTaskView(wct, this);
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
service.startShortcut(shortcut, null /* sourceBounds */, options.toBundle());
|
||||
} catch (Exception e) {
|
||||
@@ -148,6 +168,14 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
public void startActivity(@NonNull PendingIntent pendingIntent, @Nullable Intent fillInIntent,
|
||||
@NonNull ActivityOptions options, @Nullable Rect launchBounds) {
|
||||
prepareActivityOptions(options, launchBounds);
|
||||
if (isUsingShellTransitions()) {
|
||||
mShellExecutor.execute(() -> {
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.sendPendingIntent(pendingIntent, fillInIntent, options.toBundle());
|
||||
mTaskViewTransitions.startTaskView(wct, this);
|
||||
});
|
||||
return;
|
||||
}
|
||||
try {
|
||||
pendingIntent.send(mContext, 0 /* code */, fillInIntent,
|
||||
null /* onFinished */, null /* handler */, null /* requiredPermission */,
|
||||
@@ -177,6 +205,16 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
mObscuredTouchRect = obscuredRect;
|
||||
}
|
||||
|
||||
private void onLocationChanged(WindowContainerTransaction wct) {
|
||||
// Update based on the screen bounds
|
||||
getBoundsOnScreen(mTmpRect);
|
||||
getRootView().getBoundsOnScreen(mTmpRootRect);
|
||||
if (!mTmpRootRect.contains(mTmpRect)) {
|
||||
mTmpRect.offsetTo(0, 0);
|
||||
}
|
||||
wct.setBounds(mTaskToken, mTmpRect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call when view position or size has changed. Do not call when animating.
|
||||
*/
|
||||
@@ -184,15 +222,12 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
if (mTaskToken == null) {
|
||||
return;
|
||||
}
|
||||
// Update based on the screen bounds
|
||||
getBoundsOnScreen(mTmpRect);
|
||||
getRootView().getBoundsOnScreen(mTmpRootRect);
|
||||
if (!mTmpRootRect.contains(mTmpRect)) {
|
||||
mTmpRect.offsetTo(0, 0);
|
||||
}
|
||||
// Sync Transactions can't operate simultaneously with shell transition collection.
|
||||
// The transition animation (upon showing) will sync the location itself.
|
||||
if (isUsingShellTransitions() && mTaskViewTransitions.hasPending()) return;
|
||||
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.setBounds(mTaskToken, mTmpRect);
|
||||
onLocationChanged(wct);
|
||||
mSyncQueue.queue(wct);
|
||||
}
|
||||
|
||||
@@ -217,6 +252,9 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
private void performRelease() {
|
||||
getHolder().removeCallback(this);
|
||||
if (mTaskViewTransitions != null) {
|
||||
mTaskViewTransitions.removeTaskView(this);
|
||||
}
|
||||
mShellExecutor.execute(() -> {
|
||||
mTaskOrganizer.removeListener(this);
|
||||
resetTaskInfo();
|
||||
@@ -254,6 +292,10 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
@Override
|
||||
public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl leash) {
|
||||
if (isUsingShellTransitions()) {
|
||||
// Everything else handled by enter transition.
|
||||
return;
|
||||
}
|
||||
mTaskInfo = taskInfo;
|
||||
mTaskToken = taskInfo.token;
|
||||
mTaskLeash = leash;
|
||||
@@ -288,6 +330,8 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
@Override
|
||||
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
// Unlike Appeared, we can't yet guarantee that vanish will happen within a transition that
|
||||
// we know about -- so leave clean-up here even if shell transitions are enabled.
|
||||
if (mTaskToken == null || !mTaskToken.equals(taskInfo.token)) return;
|
||||
|
||||
if (mListener != null) {
|
||||
@@ -355,6 +399,10 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
// Nothing to update, task is not yet available
|
||||
return;
|
||||
}
|
||||
if (isUsingShellTransitions()) {
|
||||
mTaskViewTransitions.setTaskViewVisible(this, true /* visible */);
|
||||
return;
|
||||
}
|
||||
// Reparent the task when this surface is created
|
||||
mTransaction.reparent(mTaskLeash, getSurfaceControl())
|
||||
.show(mTaskLeash)
|
||||
@@ -380,6 +428,11 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
return;
|
||||
}
|
||||
|
||||
if (isUsingShellTransitions()) {
|
||||
mTaskViewTransitions.setTaskViewVisible(this, false /* visible */);
|
||||
return;
|
||||
}
|
||||
|
||||
// Unparent the task when this surface is destroyed
|
||||
mTransaction.reparent(mTaskLeash, null).apply();
|
||||
updateTaskVisibility();
|
||||
@@ -421,4 +474,91 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback,
|
||||
super.onDetachedFromWindow();
|
||||
getViewTreeObserver().removeOnComputeInternalInsetsListener(this);
|
||||
}
|
||||
|
||||
ActivityManager.RunningTaskInfo getTaskInfo() {
|
||||
return mTaskInfo;
|
||||
}
|
||||
|
||||
void prepareHideAnimation(@NonNull SurfaceControl.Transaction finishTransaction) {
|
||||
if (mTaskToken == null) {
|
||||
// Nothing to update, task is not yet available
|
||||
return;
|
||||
}
|
||||
|
||||
finishTransaction.reparent(mTaskLeash, null).apply();
|
||||
|
||||
if (mListener != null) {
|
||||
final int taskId = mTaskInfo.taskId;
|
||||
mListener.onTaskVisibilityChanged(taskId, mSurfaceCreated /* visible */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the associated Task closes. If the TaskView is just being hidden, prepareHide
|
||||
* is used instead.
|
||||
*/
|
||||
void prepareCloseAnimation() {
|
||||
if (mTaskToken != null) {
|
||||
if (mListener != null) {
|
||||
final int taskId = mTaskInfo.taskId;
|
||||
mListenerExecutor.execute(() -> {
|
||||
mListener.onTaskRemovalStarted(taskId);
|
||||
});
|
||||
}
|
||||
mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, false);
|
||||
}
|
||||
resetTaskInfo();
|
||||
}
|
||||
|
||||
void prepareOpenAnimation(final boolean newTask,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash,
|
||||
WindowContainerTransaction wct) {
|
||||
mTaskInfo = taskInfo;
|
||||
mTaskToken = mTaskInfo.token;
|
||||
mTaskLeash = leash;
|
||||
if (mSurfaceCreated) {
|
||||
// Surface is ready, so just reparent the task to this surface control
|
||||
startTransaction.reparent(mTaskLeash, getSurfaceControl())
|
||||
.show(mTaskLeash)
|
||||
.apply();
|
||||
// Also reparent on finishTransaction since the finishTransaction will reparent back
|
||||
// to its "original" parent by default.
|
||||
finishTransaction.reparent(mTaskLeash, getSurfaceControl())
|
||||
.setPosition(mTaskLeash, 0, 0)
|
||||
.apply();
|
||||
|
||||
// TODO: determine if this is really necessary or not
|
||||
onLocationChanged(wct);
|
||||
} else {
|
||||
// The surface has already been destroyed before the task has appeared,
|
||||
// so go ahead and hide the task entirely
|
||||
wct.setHidden(mTaskToken, true /* hidden */);
|
||||
// listener callback is below
|
||||
}
|
||||
if (newTask) {
|
||||
mTaskOrganizer.setInterceptBackPressedOnTaskRoot(mTaskToken, true /* intercept */);
|
||||
}
|
||||
|
||||
if (mTaskInfo.taskDescription != null) {
|
||||
int backgroundColor = mTaskInfo.taskDescription.getBackgroundColor();
|
||||
setResizeBackgroundColor(startTransaction, backgroundColor);
|
||||
}
|
||||
|
||||
if (mListener != null) {
|
||||
final int taskId = mTaskInfo.taskId;
|
||||
final ComponentName baseActivity = mTaskInfo.baseActivity;
|
||||
|
||||
mListenerExecutor.execute(() -> {
|
||||
if (newTask) {
|
||||
mListener.onTaskCreated(taskId, baseActivity);
|
||||
}
|
||||
// Even if newTask, send a visibilityChange if the surface was destroyed.
|
||||
if (!newTask || !mSurfaceCreated) {
|
||||
mListener.onTaskVisibilityChanged(taskId, mSurfaceCreated /* visible */);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,13 +31,24 @@ public class TaskViewFactoryController {
|
||||
private final ShellTaskOrganizer mTaskOrganizer;
|
||||
private final ShellExecutor mShellExecutor;
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
private final TaskViewTransitions mTaskViewTransitions;
|
||||
private final TaskViewFactory mImpl = new TaskViewFactoryImpl();
|
||||
|
||||
public TaskViewFactoryController(ShellTaskOrganizer taskOrganizer,
|
||||
ShellExecutor shellExecutor, SyncTransactionQueue syncQueue,
|
||||
TaskViewTransitions taskViewTransitions) {
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
mShellExecutor = shellExecutor;
|
||||
mSyncQueue = syncQueue;
|
||||
mTaskViewTransitions = taskViewTransitions;
|
||||
}
|
||||
|
||||
public TaskViewFactoryController(ShellTaskOrganizer taskOrganizer,
|
||||
ShellExecutor shellExecutor, SyncTransactionQueue syncQueue) {
|
||||
mTaskOrganizer = taskOrganizer;
|
||||
mShellExecutor = shellExecutor;
|
||||
mSyncQueue = syncQueue;
|
||||
mTaskViewTransitions = null;
|
||||
}
|
||||
|
||||
public TaskViewFactory asTaskViewFactory() {
|
||||
@@ -46,7 +57,7 @@ public class TaskViewFactoryController {
|
||||
|
||||
/** Creates an {@link TaskView} */
|
||||
public void create(@UiContext Context context, Executor executor, Consumer<TaskView> onCreate) {
|
||||
TaskView taskView = new TaskView(context, mTaskOrganizer, mSyncQueue);
|
||||
TaskView taskView = new TaskView(context, mTaskOrganizer, mTaskViewTransitions, mSyncQueue);
|
||||
executor.execute(() -> {
|
||||
onCreate.accept(taskView);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||
import static android.view.WindowManager.TRANSIT_TO_BACK;
|
||||
import static android.view.WindowManager.TRANSIT_TO_FRONT;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ActivityManager;
|
||||
import android.os.IBinder;
|
||||
import android.util.Slog;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.TransitionRequestInfo;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Handles Shell Transitions that involve TaskView tasks.
|
||||
*/
|
||||
public class TaskViewTransitions implements Transitions.TransitionHandler {
|
||||
private static final String TAG = "TaskViewTransitions";
|
||||
|
||||
private final ArrayList<TaskView> mTaskViews = new ArrayList<>();
|
||||
private final ArrayList<PendingTransition> mPending = new ArrayList<>();
|
||||
private final Transitions mTransitions;
|
||||
private final boolean[] mRegistered = new boolean[]{ false };
|
||||
|
||||
/**
|
||||
* TaskView makes heavy use of startTransition. Only one shell-initiated transition can be
|
||||
* in-flight (collecting) at a time (because otherwise, the operations could get merged into
|
||||
* a single transition). So, keep a queue here until we add a queue in server-side.
|
||||
*/
|
||||
private static class PendingTransition {
|
||||
final @WindowManager.TransitionType int mType;
|
||||
final WindowContainerTransaction mWct;
|
||||
final @NonNull TaskView mTaskView;
|
||||
IBinder mClaimed;
|
||||
|
||||
PendingTransition(@WindowManager.TransitionType int type,
|
||||
@Nullable WindowContainerTransaction wct, @NonNull TaskView taskView) {
|
||||
mType = type;
|
||||
mWct = wct;
|
||||
mTaskView = taskView;
|
||||
}
|
||||
}
|
||||
|
||||
public TaskViewTransitions(Transitions transitions) {
|
||||
mTransitions = transitions;
|
||||
// Defer registration until the first TaskView because we want this to be the "first" in
|
||||
// priority when handling requests.
|
||||
// TODO(210041388): register here once we have an explicit ordering mechanism.
|
||||
}
|
||||
|
||||
void addTaskView(TaskView tv) {
|
||||
synchronized (mRegistered) {
|
||||
if (!mRegistered[0]) {
|
||||
mRegistered[0] = true;
|
||||
mTransitions.addHandler(this);
|
||||
}
|
||||
}
|
||||
mTaskViews.add(tv);
|
||||
}
|
||||
|
||||
void removeTaskView(TaskView tv) {
|
||||
mTaskViews.remove(tv);
|
||||
// Note: Don't unregister handler since this is a singleton with lifetime bound to Shell
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks through the pending transitions for one matching `taskView`.
|
||||
* @param taskView the pending transition should be for this.
|
||||
* @param closing When true, this only returns a pending transition of the close/hide type.
|
||||
* Otherwise it selects open/show.
|
||||
* @param latest When true, this will only check the most-recent pending transition for the
|
||||
* specified taskView. If it doesn't match `closing`, this will return null even
|
||||
* if there is a match earlier. The idea behind this is to check the state of
|
||||
* the taskviews "as if all transitions already happened".
|
||||
*/
|
||||
private PendingTransition findPending(TaskView taskView, boolean closing, boolean latest) {
|
||||
for (int i = mPending.size() - 1; i >= 0; --i) {
|
||||
if (mPending.get(i).mTaskView != taskView) continue;
|
||||
if (Transitions.isClosingType(mPending.get(i).mType) == closing) {
|
||||
return mPending.get(i);
|
||||
}
|
||||
if (latest) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private PendingTransition findPending(IBinder claimed) {
|
||||
for (int i = 0; i < mPending.size(); ++i) {
|
||||
if (mPending.get(i).mClaimed != claimed) continue;
|
||||
return mPending.get(i);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @return whether there are pending transitions on TaskViews. */
|
||||
public boolean hasPending() {
|
||||
return !mPending.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@Nullable TransitionRequestInfo request) {
|
||||
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
|
||||
if (triggerTask == null) {
|
||||
return null;
|
||||
}
|
||||
final TaskView taskView = findTaskView(triggerTask);
|
||||
if (taskView == null) return null;
|
||||
// Opening types should all be initiated by shell
|
||||
if (!Transitions.isClosingType(request.getType())) return null;
|
||||
PendingTransition pending = findPending(taskView, true /* closing */, false /* latest */);
|
||||
if (pending == null) {
|
||||
pending = new PendingTransition(request.getType(), null, taskView);
|
||||
}
|
||||
if (pending.mClaimed != null) {
|
||||
throw new IllegalStateException("Task is closing in 2 collecting transitions?"
|
||||
+ " This state doesn't make sense");
|
||||
}
|
||||
pending.mClaimed = transition;
|
||||
return new WindowContainerTransaction();
|
||||
}
|
||||
|
||||
private TaskView findTaskView(ActivityManager.RunningTaskInfo taskInfo) {
|
||||
for (int i = 0; i < mTaskViews.size(); ++i) {
|
||||
if (mTaskViews.get(i).getTaskInfo() == null) continue;
|
||||
if (taskInfo.token.equals(mTaskViews.get(i).getTaskInfo().token)) {
|
||||
return mTaskViews.get(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void startTaskView(WindowContainerTransaction wct, TaskView taskView) {
|
||||
mPending.add(new PendingTransition(TRANSIT_OPEN, wct, taskView));
|
||||
startNextTransition();
|
||||
}
|
||||
|
||||
void setTaskViewVisible(TaskView taskView, boolean visible) {
|
||||
PendingTransition pending = findPending(taskView, !visible, true /* latest */);
|
||||
if (pending != null) {
|
||||
// Already opening or creating a task, so no need to do anything here.
|
||||
return;
|
||||
}
|
||||
if (taskView.getTaskInfo() == null) {
|
||||
// Nothing to update, task is not yet available
|
||||
return;
|
||||
}
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
|
||||
pending = new PendingTransition(
|
||||
visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView);
|
||||
mPending.add(pending);
|
||||
startNextTransition();
|
||||
// visibility is reported in transition.
|
||||
}
|
||||
|
||||
private void startNextTransition() {
|
||||
if (mPending.isEmpty()) return;
|
||||
final PendingTransition pending = mPending.get(0);
|
||||
if (pending.mClaimed != null) {
|
||||
// Wait for this to start animating.
|
||||
return;
|
||||
}
|
||||
pending.mClaimed = mTransitions.startTransition(pending.mType, pending.mWct, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startAnimation(@NonNull IBinder transition,
|
||||
@NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||
PendingTransition pending = findPending(transition);
|
||||
if (pending == null) return false;
|
||||
mPending.remove(pending);
|
||||
TaskView taskView = pending.mTaskView;
|
||||
final ArrayList<TransitionInfo.Change> tasks = new ArrayList<>();
|
||||
for (int i = 0; i < info.getChanges().size(); ++i) {
|
||||
final TransitionInfo.Change chg = info.getChanges().get(i);
|
||||
if (chg.getTaskInfo() == null) continue;
|
||||
tasks.add(chg);
|
||||
}
|
||||
if (tasks.isEmpty()) {
|
||||
Slog.e(TAG, "Got a TaskView transition with no task.");
|
||||
return false;
|
||||
}
|
||||
WindowContainerTransaction wct = null;
|
||||
for (int i = 0; i < tasks.size(); ++i) {
|
||||
TransitionInfo.Change chg = tasks.get(i);
|
||||
if (Transitions.isClosingType(chg.getMode())) {
|
||||
final boolean isHide = chg.getMode() == TRANSIT_TO_BACK;
|
||||
TaskView tv = findTaskView(chg.getTaskInfo());
|
||||
if (tv == null) {
|
||||
throw new IllegalStateException("TaskView transition is closing a "
|
||||
+ "non-taskview task ");
|
||||
}
|
||||
if (isHide) {
|
||||
tv.prepareHideAnimation(finishTransaction);
|
||||
} else {
|
||||
tv.prepareCloseAnimation();
|
||||
}
|
||||
} else if (Transitions.isOpeningType(chg.getMode())) {
|
||||
final boolean taskIsNew = chg.getMode() == TRANSIT_OPEN;
|
||||
if (wct == null) wct = new WindowContainerTransaction();
|
||||
TaskView tv = taskView;
|
||||
if (!taskIsNew) {
|
||||
tv = findTaskView(chg.getTaskInfo());
|
||||
if (tv == null) {
|
||||
throw new IllegalStateException("TaskView transition is showing a "
|
||||
+ "non-taskview task ");
|
||||
}
|
||||
}
|
||||
tv.prepareOpenAnimation(taskIsNew, startTransaction, finishTransaction,
|
||||
chg.getTaskInfo(), chg.getLeash(), wct);
|
||||
} else {
|
||||
throw new IllegalStateException("Claimed transition isn't an opening or closing"
|
||||
+ " type: " + chg.getMode());
|
||||
}
|
||||
}
|
||||
// No animation, just show it immediately.
|
||||
startTransaction.apply();
|
||||
finishTransaction.apply();
|
||||
finishCallback.onTransitionFinished(wct, null /* wctCB */);
|
||||
startNextTransition();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.logging.UiEventLogger;
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.common.DisplayChangeController;
|
||||
import com.android.wm.shell.common.DisplayController;
|
||||
@@ -136,6 +137,7 @@ public class BubbleController {
|
||||
private final TaskStackListenerImpl mTaskStackListener;
|
||||
private final ShellTaskOrganizer mTaskOrganizer;
|
||||
private final DisplayController mDisplayController;
|
||||
private final TaskViewTransitions mTaskViewTransitions;
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
|
||||
// Used to post to main UI thread
|
||||
@@ -212,6 +214,7 @@ public class BubbleController {
|
||||
DisplayController displayController,
|
||||
ShellExecutor mainExecutor,
|
||||
Handler mainHandler,
|
||||
TaskViewTransitions taskViewTransitions,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
BubbleLogger logger = new BubbleLogger(uiEventLogger);
|
||||
BubblePositioner positioner = new BubblePositioner(context, windowManager);
|
||||
@@ -220,7 +223,7 @@ public class BubbleController {
|
||||
new BubbleDataRepository(context, launcherApps, mainExecutor),
|
||||
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
|
||||
logger, taskStackListener, organizer, positioner, displayController, mainExecutor,
|
||||
mainHandler, syncQueue);
|
||||
mainHandler, taskViewTransitions, syncQueue);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -243,6 +246,7 @@ public class BubbleController {
|
||||
DisplayController displayController,
|
||||
ShellExecutor mainExecutor,
|
||||
Handler mainHandler,
|
||||
TaskViewTransitions taskViewTransitions,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
mContext = context;
|
||||
mLauncherApps = launcherApps;
|
||||
@@ -266,6 +270,7 @@ public class BubbleController {
|
||||
mSavedBubbleKeysPerUser = new SparseSetArray<>();
|
||||
mBubbleIconFactory = new BubbleIconFactory(context);
|
||||
mDisplayController = displayController;
|
||||
mTaskViewTransitions = taskViewTransitions;
|
||||
mSyncQueue = syncQueue;
|
||||
}
|
||||
|
||||
@@ -570,6 +575,10 @@ public class BubbleController {
|
||||
return mSyncQueue;
|
||||
}
|
||||
|
||||
TaskViewTransitions getTaskViewTransitions() {
|
||||
return mTaskViewTransitions;
|
||||
}
|
||||
|
||||
/** Contains information to help position things on the screen. */
|
||||
BubblePositioner getPositioner() {
|
||||
return mBubblePositioner;
|
||||
|
||||
@@ -335,7 +335,7 @@ public class BubbleExpandedView extends LinearLayout {
|
||||
mManageButton.setVisibility(GONE);
|
||||
} else {
|
||||
mTaskView = new TaskView(mContext, mController.getTaskOrganizer(),
|
||||
mController.getSyncTransactionQueue());
|
||||
mController.getTaskViewTransitions(), mController.getSyncTransactionQueue());
|
||||
mTaskView.setListener(mController.getMainExecutor(), mTaskViewListener);
|
||||
mExpandedViewContainer.addView(mTaskView);
|
||||
bringChildToFront(mTaskView);
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.wm.shell.ShellInitImpl;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
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;
|
||||
@@ -463,6 +464,12 @@ public abstract class WMShellBaseModule {
|
||||
animExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static TaskViewTransitions provideTaskViewTransitions(Transitions transitions) {
|
||||
return new TaskViewTransitions(transitions);
|
||||
}
|
||||
|
||||
//
|
||||
// Display areas
|
||||
//
|
||||
@@ -594,8 +601,10 @@ public abstract class WMShellBaseModule {
|
||||
static TaskViewFactoryController provideTaskViewFactoryController(
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
@ShellMainThread ShellExecutor mainExecutor,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
return new TaskViewFactoryController(shellTaskOrganizer, mainExecutor, syncQueue);
|
||||
SyncTransactionQueue syncQueue,
|
||||
TaskViewTransitions taskViewTransitions) {
|
||||
return new TaskViewFactoryController(shellTaskOrganizer, mainExecutor, syncQueue,
|
||||
taskViewTransitions);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.launcher3.icons.IconProvider;
|
||||
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;
|
||||
@@ -108,11 +109,13 @@ public class WMShellModule {
|
||||
DisplayController displayController,
|
||||
@ShellMainThread ShellExecutor mainExecutor,
|
||||
@ShellMainThread Handler mainHandler,
|
||||
TaskViewTransitions taskViewTransitions,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
return BubbleController.create(context, null /* synchronizer */,
|
||||
floatingContentCoordinator, statusBarService, windowManager,
|
||||
windowManagerShellWrapper, launcherApps, taskStackListener,
|
||||
uiEventLogger, organizer, displayController, mainExecutor, mainHandler, syncQueue);
|
||||
uiEventLogger, organizer, displayController, mainExecutor, mainHandler,
|
||||
taskViewTransitions, syncQueue);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
@@ -21,6 +21,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -43,12 +45,14 @@ import android.view.SurfaceControl;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceSession;
|
||||
import android.window.WindowContainerToken;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.common.HandlerExecutor;
|
||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||
import com.android.wm.shell.common.SyncTransactionQueue.TransactionRunnable;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -75,6 +79,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
HandlerExecutor mExecutor;
|
||||
@Mock
|
||||
SyncTransactionQueue mSyncQueue;
|
||||
@Mock
|
||||
TaskViewTransitions mTaskViewTransitions;
|
||||
|
||||
SurfaceSession mSession;
|
||||
SurfaceControl mLeash;
|
||||
@@ -110,7 +116,7 @@ public class TaskViewTest extends ShellTestCase {
|
||||
return null;
|
||||
}).when(mSyncQueue).runInSync(any());
|
||||
|
||||
mTaskView = new TaskView(mContext, mOrganizer, mSyncQueue);
|
||||
mTaskView = new TaskView(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue);
|
||||
mTaskView.setListener(mExecutor, mViewListener);
|
||||
}
|
||||
|
||||
@@ -123,7 +129,7 @@ public class TaskViewTest extends ShellTestCase {
|
||||
|
||||
@Test
|
||||
public void testSetPendingListener_throwsException() {
|
||||
TaskView taskView = new TaskView(mContext, mOrganizer, mSyncQueue);
|
||||
TaskView taskView = new TaskView(mContext, mOrganizer, mTaskViewTransitions, mSyncQueue);
|
||||
taskView.setListener(mExecutor, mViewListener);
|
||||
try {
|
||||
taskView.setListener(mExecutor, mViewListener);
|
||||
@@ -144,7 +150,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnTaskAppeared_noSurface() {
|
||||
public void testOnTaskAppeared_noSurface_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
|
||||
verify(mViewListener).onTaskCreated(eq(mTaskInfo.taskId), any());
|
||||
@@ -154,7 +161,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnTaskAppeared_withSurface() {
|
||||
public void testOnTaskAppeared_withSurface_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
|
||||
@@ -163,7 +171,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceCreated_noTask() {
|
||||
public void testSurfaceCreated_noTask_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
|
||||
verify(mViewListener).onInitialized();
|
||||
@@ -172,7 +181,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceCreated_withTask() {
|
||||
public void testSurfaceCreated_withTask_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
|
||||
@@ -181,7 +191,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceDestroyed_noTask() {
|
||||
public void testSurfaceDestroyed_noTask_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
SurfaceHolder sh = mock(SurfaceHolder.class);
|
||||
mTaskView.surfaceCreated(sh);
|
||||
mTaskView.surfaceDestroyed(sh);
|
||||
@@ -190,7 +201,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceDestroyed_withTask() {
|
||||
public void testSurfaceDestroyed_withTask_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
SurfaceHolder sh = mock(SurfaceHolder.class);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
mTaskView.surfaceCreated(sh);
|
||||
@@ -201,7 +213,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnReleased() {
|
||||
public void testOnReleased_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
mTaskView.release();
|
||||
@@ -211,7 +224,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnTaskVanished() {
|
||||
public void testOnTaskVanished_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
mTaskView.onTaskVanished(mTaskInfo);
|
||||
@@ -220,7 +234,8 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBackPressedOnTaskRoot() {
|
||||
public void testOnBackPressedOnTaskRoot_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
mTaskView.onBackPressedOnTaskRoot(mTaskInfo);
|
||||
|
||||
@@ -228,17 +243,158 @@ public class TaskViewTest extends ShellTestCase {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetOnBackPressedOnTaskRoot() {
|
||||
public void testSetOnBackPressedOnTaskRoot_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsetOnBackPressedOnTaskRoot() {
|
||||
public void testUnsetOnBackPressedOnTaskRoot_legacyTransitions() {
|
||||
assumeFalse(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.onTaskAppeared(mTaskInfo, mLeash);
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
|
||||
|
||||
mTaskView.onTaskVanished(mTaskInfo);
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnNewTask_noSurface() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
|
||||
verify(mViewListener).onTaskCreated(eq(mTaskInfo.taskId), any());
|
||||
verify(mViewListener, never()).onInitialized();
|
||||
// If there's no surface the task should be made invisible
|
||||
verify(mViewListener).onTaskVisibilityChanged(eq(mTaskInfo.taskId), eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceCreated_noTask() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
verify(mTaskViewTransitions, never()).setTaskViewVisible(any(), anyBoolean());
|
||||
|
||||
verify(mViewListener).onInitialized();
|
||||
// No task, no visibility change
|
||||
verify(mViewListener, never()).onTaskVisibilityChanged(anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnNewTask_withSurface() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
|
||||
verify(mViewListener).onTaskCreated(eq(mTaskInfo.taskId), any());
|
||||
verify(mViewListener, never()).onTaskVisibilityChanged(anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceCreated_withTask() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
|
||||
verify(mViewListener).onInitialized();
|
||||
verify(mTaskViewTransitions).setTaskViewVisible(eq(mTaskView), eq(true));
|
||||
|
||||
mTaskView.prepareOpenAnimation(false /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
|
||||
verify(mViewListener).onTaskVisibilityChanged(eq(mTaskInfo.taskId), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceDestroyed_noTask() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
SurfaceHolder sh = mock(SurfaceHolder.class);
|
||||
mTaskView.surfaceCreated(sh);
|
||||
mTaskView.surfaceDestroyed(sh);
|
||||
|
||||
verify(mViewListener, never()).onTaskVisibilityChanged(anyInt(), anyBoolean());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSurfaceDestroyed_withTask() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
SurfaceHolder sh = mock(SurfaceHolder.class);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
mTaskView.surfaceCreated(sh);
|
||||
reset(mViewListener);
|
||||
mTaskView.surfaceDestroyed(sh);
|
||||
|
||||
verify(mTaskViewTransitions).setTaskViewVisible(eq(mTaskView), eq(false));
|
||||
|
||||
mTaskView.prepareHideAnimation(new SurfaceControl.Transaction());
|
||||
|
||||
verify(mViewListener).onTaskVisibilityChanged(eq(mTaskInfo.taskId), eq(false));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnReleased() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
mTaskView.release();
|
||||
|
||||
verify(mOrganizer).removeListener(eq(mTaskView));
|
||||
verify(mViewListener).onReleased();
|
||||
verify(mTaskViewTransitions).removeTaskView(eq(mTaskView));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnTaskVanished() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
mTaskView.surfaceCreated(mock(SurfaceHolder.class));
|
||||
mTaskView.prepareCloseAnimation();
|
||||
|
||||
verify(mViewListener).onTaskRemovalStarted(eq(mTaskInfo.taskId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnBackPressedOnTaskRoot() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
mTaskView.onBackPressedOnTaskRoot(mTaskInfo);
|
||||
|
||||
verify(mViewListener).onBackPressedOnTaskRoot(eq(mTaskInfo.taskId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetOnBackPressedOnTaskRoot() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnsetOnBackPressedOnTaskRoot() {
|
||||
assumeTrue(Transitions.ENABLE_SHELL_TRANSITIONS);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mTaskView.prepareOpenAnimation(true /* newTask */, new SurfaceControl.Transaction(),
|
||||
new SurfaceControl.Transaction(), mTaskInfo, mLeash, wct);
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(true));
|
||||
|
||||
mTaskView.prepareCloseAnimation();
|
||||
verify(mOrganizer).setInterceptBackPressedOnTaskRoot(eq(mTaskInfo.token), eq(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.wm.shell.R;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.bubbles.Bubble;
|
||||
import com.android.wm.shell.bubbles.BubbleData;
|
||||
@@ -246,6 +247,8 @@ public class BubblesTest extends SysuiTestCase {
|
||||
private ScreenOffAnimationController mScreenOffAnimationController;
|
||||
@Mock
|
||||
private AuthController mAuthController;
|
||||
@Mock
|
||||
private TaskViewTransitions mTaskViewTransitions;
|
||||
|
||||
private TestableBubblePositioner mPositioner;
|
||||
|
||||
@@ -344,6 +347,7 @@ public class BubblesTest extends SysuiTestCase {
|
||||
mock(DisplayController.class),
|
||||
syncExecutor,
|
||||
mock(Handler.class),
|
||||
mTaskViewTransitions,
|
||||
mock(SyncTransactionQueue.class));
|
||||
mBubbleController.setExpandListener(mBubbleExpandListener);
|
||||
spyOn(mBubbleController);
|
||||
|
||||
@@ -90,6 +90,7 @@ import com.android.systemui.statusbar.policy.HeadsUpManager;
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import com.android.systemui.statusbar.policy.ZenModeController;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.bubbles.Bubble;
|
||||
import com.android.wm.shell.bubbles.BubbleData;
|
||||
@@ -217,6 +218,8 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
|
||||
private KeyguardStateController mKeyguardStateController;
|
||||
@Mock
|
||||
private ScreenOffAnimationController mScreenOffAnimationController;
|
||||
@Mock
|
||||
private TaskViewTransitions mTaskViewTransitions;
|
||||
|
||||
private TestableBubblePositioner mPositioner;
|
||||
|
||||
@@ -306,6 +309,7 @@ public class NewNotifPipelineBubblesTest extends SysuiTestCase {
|
||||
mock(DisplayController.class),
|
||||
syncExecutor,
|
||||
mock(Handler.class),
|
||||
mTaskViewTransitions,
|
||||
mock(SyncTransactionQueue.class));
|
||||
mBubbleController.setExpandListener(mBubbleExpandListener);
|
||||
spyOn(mBubbleController);
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.view.WindowManager;
|
||||
|
||||
import com.android.internal.statusbar.IStatusBarService;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.TaskViewTransitions;
|
||||
import com.android.wm.shell.WindowManagerShellWrapper;
|
||||
import com.android.wm.shell.bubbles.BubbleController;
|
||||
import com.android.wm.shell.bubbles.BubbleData;
|
||||
@@ -56,11 +57,12 @@ public class TestableBubbleController extends BubbleController {
|
||||
DisplayController displayController,
|
||||
ShellExecutor shellMainExecutor,
|
||||
Handler shellMainHandler,
|
||||
TaskViewTransitions taskViewTransitions,
|
||||
SyncTransactionQueue syncQueue) {
|
||||
super(context, data, Runnable::run, floatingContentCoordinator, dataRepository,
|
||||
statusBarService, windowManager, windowManagerShellWrapper, launcherApps,
|
||||
bubbleLogger, taskStackListener, shellTaskOrganizer, positioner, displayController,
|
||||
shellMainExecutor, shellMainHandler, syncQueue);
|
||||
shellMainExecutor, shellMainHandler, taskViewTransitions, syncQueue);
|
||||
setInflateSynchronously(true);
|
||||
initialize();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user