Merge "Put window decors at one place" into tm-qpr-dev
This commit is contained in:
@@ -292,17 +292,17 @@ public abstract class WMShellBaseModule {
|
|||||||
// Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
|
// Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
|
||||||
@BindsOptionalOf
|
@BindsOptionalOf
|
||||||
@DynamicOverride
|
@DynamicOverride
|
||||||
abstract FullscreenTaskListener<?> optionalFullscreenTaskListener();
|
abstract FullscreenTaskListener optionalFullscreenTaskListener();
|
||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
static FullscreenTaskListener<?> provideFullscreenTaskListener(
|
static FullscreenTaskListener provideFullscreenTaskListener(
|
||||||
@DynamicOverride Optional<FullscreenTaskListener<?>> fullscreenTaskListener,
|
@DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
ShellTaskOrganizer shellTaskOrganizer,
|
ShellTaskOrganizer shellTaskOrganizer,
|
||||||
SyncTransactionQueue syncQueue,
|
SyncTransactionQueue syncQueue,
|
||||||
Optional<RecentTasksController> recentTasksOptional,
|
Optional<RecentTasksController> recentTasksOptional,
|
||||||
Optional<WindowDecorViewModel<?>> windowDecorViewModelOptional) {
|
Optional<WindowDecorViewModel> windowDecorViewModelOptional) {
|
||||||
if (fullscreenTaskListener.isPresent()) {
|
if (fullscreenTaskListener.isPresent()) {
|
||||||
return fullscreenTaskListener.get();
|
return fullscreenTaskListener.get();
|
||||||
} else {
|
} else {
|
||||||
@@ -316,7 +316,7 @@ public abstract class WMShellBaseModule {
|
|||||||
//
|
//
|
||||||
|
|
||||||
@BindsOptionalOf
|
@BindsOptionalOf
|
||||||
abstract WindowDecorViewModel<?> optionalWindowDecorViewModel();
|
abstract WindowDecorViewModel optionalWindowDecorViewModel();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Unfold transition
|
// Unfold transition
|
||||||
@@ -768,7 +768,7 @@ public abstract class WMShellBaseModule {
|
|||||||
Optional<SplitScreenController> splitScreenOptional,
|
Optional<SplitScreenController> splitScreenOptional,
|
||||||
Optional<Pip> pipOptional,
|
Optional<Pip> pipOptional,
|
||||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<UnfoldAnimationController> unfoldAnimationController,
|
Optional<UnfoldAnimationController> unfoldAnimationController,
|
||||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||||
Optional<FreeformComponents> freeformComponents,
|
Optional<FreeformComponents> freeformComponents,
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ import com.android.wm.shell.freeform.FreeformComponents;
|
|||||||
import com.android.wm.shell.freeform.FreeformTaskListener;
|
import com.android.wm.shell.freeform.FreeformTaskListener;
|
||||||
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
|
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
|
||||||
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
|
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
|
||||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||||
import com.android.wm.shell.onehanded.OneHandedController;
|
import com.android.wm.shell.onehanded.OneHandedController;
|
||||||
import com.android.wm.shell.pip.Pip;
|
import com.android.wm.shell.pip.Pip;
|
||||||
@@ -183,7 +182,7 @@ public abstract class WMShellModule {
|
|||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
static WindowDecorViewModel<?> provideWindowDecorViewModel(
|
static WindowDecorViewModel provideWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
@ShellMainThread Handler mainHandler,
|
@ShellMainThread Handler mainHandler,
|
||||||
@ShellMainThread Choreographer mainChoreographer,
|
@ShellMainThread Choreographer mainChoreographer,
|
||||||
@@ -209,7 +208,7 @@ public abstract class WMShellModule {
|
|||||||
@Provides
|
@Provides
|
||||||
@DynamicOverride
|
@DynamicOverride
|
||||||
static FreeformComponents provideFreeformComponents(
|
static FreeformComponents provideFreeformComponents(
|
||||||
FreeformTaskListener<?> taskListener,
|
FreeformTaskListener taskListener,
|
||||||
FreeformTaskTransitionHandler transitionHandler,
|
FreeformTaskTransitionHandler transitionHandler,
|
||||||
FreeformTaskTransitionObserver transitionObserver) {
|
FreeformTaskTransitionObserver transitionObserver) {
|
||||||
return new FreeformComponents(
|
return new FreeformComponents(
|
||||||
@@ -218,18 +217,18 @@ public abstract class WMShellModule {
|
|||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
static FreeformTaskListener<?> provideFreeformTaskListener(
|
static FreeformTaskListener provideFreeformTaskListener(
|
||||||
Context context,
|
Context context,
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
ShellTaskOrganizer shellTaskOrganizer,
|
ShellTaskOrganizer shellTaskOrganizer,
|
||||||
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
||||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
WindowDecorViewModel windowDecorViewModel) {
|
||||||
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
|
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
|
||||||
// override for this controller from the base module
|
// override for this controller from the base module
|
||||||
ShellInit init = FreeformComponents.isFreeformEnabled(context)
|
ShellInit init = FreeformComponents.isFreeformEnabled(context)
|
||||||
? shellInit
|
? shellInit
|
||||||
: null;
|
: null;
|
||||||
return new FreeformTaskListener<>(init, shellTaskOrganizer, desktopModeTaskRepository,
|
return new FreeformTaskListener(init, shellTaskOrganizer, desktopModeTaskRepository,
|
||||||
windowDecorViewModel);
|
windowDecorViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,7 +237,7 @@ public abstract class WMShellModule {
|
|||||||
static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
|
static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
WindowDecorViewModel windowDecorViewModel) {
|
||||||
return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
|
return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,10 +247,9 @@ public abstract class WMShellModule {
|
|||||||
Context context,
|
Context context,
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
WindowDecorViewModel windowDecorViewModel) {
|
||||||
FreeformTaskListener<?> freeformTaskListener) {
|
|
||||||
return new FreeformTaskTransitionObserver(
|
return new FreeformTaskTransitionObserver(
|
||||||
context, shellInit, transitions, fullscreenTaskListener, freeformTaskListener);
|
context, shellInit, transitions, windowDecorViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -19,12 +19,8 @@ package com.android.wm.shell.freeform;
|
|||||||
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM;
|
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM;
|
||||||
|
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.TransitionInfo;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
@@ -41,31 +37,26 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* {@link ShellTaskOrganizer.TaskListener} for {@link
|
* {@link ShellTaskOrganizer.TaskListener} for {@link
|
||||||
* ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
|
* ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
|
||||||
*
|
|
||||||
* @param <T> the type of window decoration instance
|
|
||||||
*/
|
*/
|
||||||
public class FreeformTaskListener<T extends AutoCloseable>
|
public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||||
implements ShellTaskOrganizer.TaskListener {
|
|
||||||
private static final String TAG = "FreeformTaskListener";
|
private static final String TAG = "FreeformTaskListener";
|
||||||
|
|
||||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||||
private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
|
private final Optional<DesktopModeTaskRepository> mDesktopModeTaskRepository;
|
||||||
private final WindowDecorViewModel<T> mWindowDecorationViewModel;
|
private final WindowDecorViewModel mWindowDecorationViewModel;
|
||||||
|
|
||||||
private final SparseArray<State<T>> mTasks = new SparseArray<>();
|
private final SparseArray<State> mTasks = new SparseArray<>();
|
||||||
private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
|
|
||||||
|
|
||||||
private static class State<T extends AutoCloseable> {
|
private static class State {
|
||||||
RunningTaskInfo mTaskInfo;
|
RunningTaskInfo mTaskInfo;
|
||||||
SurfaceControl mLeash;
|
SurfaceControl mLeash;
|
||||||
T mWindowDecoration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeformTaskListener(
|
public FreeformTaskListener(
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
ShellTaskOrganizer shellTaskOrganizer,
|
ShellTaskOrganizer shellTaskOrganizer,
|
||||||
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
||||||
WindowDecorViewModel<T> windowDecorationViewModel) {
|
WindowDecorViewModel windowDecorationViewModel) {
|
||||||
mShellTaskOrganizer = shellTaskOrganizer;
|
mShellTaskOrganizer = shellTaskOrganizer;
|
||||||
mWindowDecorationViewModel = windowDecorationViewModel;
|
mWindowDecorationViewModel = windowDecorationViewModel;
|
||||||
mDesktopModeTaskRepository = desktopModeTaskRepository;
|
mDesktopModeTaskRepository = desktopModeTaskRepository;
|
||||||
@@ -80,12 +71,17 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
||||||
|
if (mTasks.get(taskInfo.taskId) != null) {
|
||||||
|
throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
|
||||||
|
}
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
final State<T> state = createOrUpdateTaskState(taskInfo, leash);
|
final State state = new State();
|
||||||
|
state.mTaskInfo = taskInfo;
|
||||||
|
state.mLeash = leash;
|
||||||
|
mTasks.put(taskInfo.taskId, state);
|
||||||
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
state.mWindowDecoration =
|
|
||||||
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
|
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
|
||||||
t.apply();
|
t.apply();
|
||||||
}
|
}
|
||||||
@@ -97,28 +93,8 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private State<T> createOrUpdateTaskState(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
|
||||||
State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state != null) {
|
|
||||||
updateTaskInfo(taskInfo);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = new State<>();
|
|
||||||
state.mTaskInfo = taskInfo;
|
|
||||||
state.mLeash = leash;
|
|
||||||
mTasks.put(taskInfo.taskId, state);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskVanished(RunningTaskInfo taskInfo) {
|
public void onTaskVanished(RunningTaskInfo taskInfo) {
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state == null) {
|
|
||||||
// This is possible if the transition happens before this method.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
mTasks.remove(taskInfo.taskId);
|
mTasks.remove(taskInfo.taskId);
|
||||||
@@ -129,26 +105,18 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId));
|
mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
// Save window decorations of closing tasks so that we can hand them over to the
|
mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
|
||||||
// transition system if this method happens before the transition. In case where the
|
|
||||||
// transition didn't happen, it'd be cleared when the next transition finished.
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
releaseWindowDecor(state.mWindowDecoration);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
final State<T> state = updateTaskInfo(taskInfo);
|
final State state = mTasks.get(taskInfo.taskId);
|
||||||
|
state.mTaskInfo = taskInfo;
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
if (state.mWindowDecoration != null) {
|
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo);
|
||||||
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (DesktopModeStatus.IS_SUPPORTED) {
|
if (DesktopModeStatus.IS_SUPPORTED) {
|
||||||
if (taskInfo.isVisible) {
|
if (taskInfo.isVisible) {
|
||||||
@@ -159,15 +127,6 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private State<T> updateTaskInfo(RunningTaskInfo taskInfo) {
|
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state == null) {
|
|
||||||
throw new RuntimeException("Task info changed before appearing: #" + taskInfo.taskId);
|
|
||||||
}
|
|
||||||
state.mTaskInfo = taskInfo;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
||||||
b.setParent(findTaskSurface(taskId));
|
b.setParent(findTaskSurface(taskId));
|
||||||
@@ -186,103 +145,6 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
return mTasks.get(taskId).mLeash;
|
return mTasks.get(taskId).mLeash;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a window decoration for a transition.
|
|
||||||
*
|
|
||||||
* @param change the change of this task transition that needs to have the task layer as the
|
|
||||||
* leash
|
|
||||||
* @return {@code true} if it creates the window decoration; {@code false} otherwise
|
|
||||||
*/
|
|
||||||
boolean createWindowDecoration(
|
|
||||||
TransitionInfo.Change change,
|
|
||||||
SurfaceControl.Transaction startT,
|
|
||||||
SurfaceControl.Transaction finishT) {
|
|
||||||
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
|
|
||||||
state.mTaskInfo, state.mLeash, startT, finishT);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives out the ownership of the task's window decoration. The given task is leaving (of has
|
|
||||||
* left) this task listener. This is the transition system asking for the ownership.
|
|
||||||
*
|
|
||||||
* @param taskInfo the maximizing task
|
|
||||||
* @return the window decor of the maximizing task if any
|
|
||||||
*/
|
|
||||||
T giveWindowDecoration(
|
|
||||||
RunningTaskInfo taskInfo,
|
|
||||||
SurfaceControl.Transaction startT,
|
|
||||||
SurfaceControl.Transaction finishT) {
|
|
||||||
T windowDecor;
|
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state != null) {
|
|
||||||
windowDecor = state.mWindowDecoration;
|
|
||||||
state.mWindowDecoration = null;
|
|
||||||
} else {
|
|
||||||
windowDecor =
|
|
||||||
mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
|
|
||||||
}
|
|
||||||
if (windowDecor == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
mWindowDecorationViewModel.setupWindowDecorationForTransition(
|
|
||||||
taskInfo, startT, finishT, windowDecor);
|
|
||||||
return windowDecor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adopt the incoming window decoration and lets the window decoration prepare for a transition.
|
|
||||||
*
|
|
||||||
* @param change the change of this task transition that needs to have the task layer as the
|
|
||||||
* leash
|
|
||||||
* @param startT the start transaction of this transition
|
|
||||||
* @param finishT the finish transaction of this transition
|
|
||||||
* @param windowDecor the window decoration to adopt
|
|
||||||
* @return {@code true} if it adopts the window decoration; {@code false} otherwise
|
|
||||||
*/
|
|
||||||
boolean adoptWindowDecoration(
|
|
||||||
TransitionInfo.Change change,
|
|
||||||
SurfaceControl.Transaction startT,
|
|
||||||
SurfaceControl.Transaction finishT,
|
|
||||||
@Nullable AutoCloseable windowDecor) {
|
|
||||||
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
|
|
||||||
state.mWindowDecoration = mWindowDecorationViewModel.adoptWindowDecoration(windowDecor);
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
mWindowDecorationViewModel.setupWindowDecorationForTransition(
|
|
||||||
state.mTaskInfo, startT, finishT, state.mWindowDecoration);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
|
|
||||||
state.mTaskInfo, state.mLeash, startT, finishT);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void onTaskTransitionFinished() {
|
|
||||||
if (mWindowDecorOfVanishedTasks.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
|
|
||||||
"Clearing window decors of vanished tasks. There could be visual defects "
|
|
||||||
+ "if any of them is used later in transitions.");
|
|
||||||
for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
|
|
||||||
releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
|
|
||||||
}
|
|
||||||
mWindowDecorOfVanishedTasks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void releaseWindowDecor(T windowDecor) {
|
|
||||||
try {
|
|
||||||
windowDecor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Failed to release window decoration.", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(PrintWriter pw, String prefix) {
|
public void dump(PrintWriter pw, String prefix) {
|
||||||
final String innerPrefix = prefix + " ";
|
final String innerPrefix = prefix + " ";
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ public class FreeformTaskTransitionHandler
|
|||||||
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
|
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
|
||||||
|
|
||||||
private final Transitions mTransitions;
|
private final Transitions mTransitions;
|
||||||
private final WindowDecorViewModel<?> mWindowDecorViewModel;
|
private final WindowDecorViewModel mWindowDecorViewModel;
|
||||||
|
|
||||||
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
|
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
|
||||||
|
|
||||||
public FreeformTaskTransitionHandler(
|
public FreeformTaskTransitionHandler(
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
WindowDecorViewModel windowDecorViewModel) {
|
||||||
mTransitions = transitions;
|
mTransitions = transitions;
|
||||||
mWindowDecorViewModel = windowDecorViewModel;
|
mWindowDecorViewModel = windowDecorViewModel;
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
|
|||||||
@@ -16,13 +16,9 @@
|
|||||||
|
|
||||||
package com.android.wm.shell.freeform;
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
|
||||||
|
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import android.window.TransitionInfo;
|
import android.window.TransitionInfo;
|
||||||
@@ -31,9 +27,9 @@ import android.window.WindowContainerToken;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.VisibleForTesting;
|
import androidx.annotation.VisibleForTesting;
|
||||||
|
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
|
||||||
import com.android.wm.shell.sysui.ShellInit;
|
import com.android.wm.shell.sysui.ShellInit;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -47,23 +43,19 @@ import java.util.Map;
|
|||||||
* be a part of transitions.
|
* be a part of transitions.
|
||||||
*/
|
*/
|
||||||
public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver {
|
public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver {
|
||||||
private static final String TAG = "FreeformTO";
|
|
||||||
|
|
||||||
private final Transitions mTransitions;
|
private final Transitions mTransitions;
|
||||||
private final FreeformTaskListener<?> mFreeformTaskListener;
|
private final WindowDecorViewModel mWindowDecorViewModel;
|
||||||
private final FullscreenTaskListener<?> mFullscreenTaskListener;
|
|
||||||
|
|
||||||
private final Map<IBinder, List<AutoCloseable>> mTransitionToWindowDecors = new HashMap<>();
|
private final Map<IBinder, List<ActivityManager.RunningTaskInfo>> mTransitionToTaskInfo =
|
||||||
|
new HashMap<>();
|
||||||
|
|
||||||
public FreeformTaskTransitionObserver(
|
public FreeformTaskTransitionObserver(
|
||||||
Context context,
|
Context context,
|
||||||
ShellInit shellInit,
|
ShellInit shellInit,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
WindowDecorViewModel windowDecorViewModel) {
|
||||||
FreeformTaskListener<?> freeformTaskListener) {
|
|
||||||
mTransitions = transitions;
|
mTransitions = transitions;
|
||||||
mFreeformTaskListener = freeformTaskListener;
|
mWindowDecorViewModel = windowDecorViewModel;
|
||||||
mFullscreenTaskListener = fullscreenTaskListener;
|
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) {
|
||||||
shellInit.addInitCallback(this::onInit, this);
|
shellInit.addInitCallback(this::onInit, this);
|
||||||
}
|
}
|
||||||
@@ -80,7 +72,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
|||||||
@NonNull TransitionInfo info,
|
@NonNull TransitionInfo info,
|
||||||
@NonNull SurfaceControl.Transaction startT,
|
@NonNull SurfaceControl.Transaction startT,
|
||||||
@NonNull SurfaceControl.Transaction finishT) {
|
@NonNull SurfaceControl.Transaction finishT) {
|
||||||
final ArrayList<AutoCloseable> windowDecors = new ArrayList<>();
|
final ArrayList<ActivityManager.RunningTaskInfo> taskInfoList = new ArrayList<>();
|
||||||
final ArrayList<WindowContainerToken> taskParents = new ArrayList<>();
|
final ArrayList<WindowContainerToken> taskParents = new ArrayList<>();
|
||||||
for (TransitionInfo.Change change : info.getChanges()) {
|
for (TransitionInfo.Change change : info.getChanges()) {
|
||||||
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
|
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
|
||||||
@@ -110,92 +102,40 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
|||||||
onOpenTransitionReady(change, startT, finishT);
|
onOpenTransitionReady(change, startT, finishT);
|
||||||
break;
|
break;
|
||||||
case WindowManager.TRANSIT_CLOSE: {
|
case WindowManager.TRANSIT_CLOSE: {
|
||||||
onCloseTransitionReady(change, windowDecors, startT, finishT);
|
taskInfoList.add(change.getTaskInfo());
|
||||||
|
onCloseTransitionReady(change, startT, finishT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WindowManager.TRANSIT_CHANGE:
|
case WindowManager.TRANSIT_CHANGE:
|
||||||
onChangeTransitionReady(info.getType(), change, startT, finishT);
|
onChangeTransitionReady(change, startT, finishT);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!windowDecors.isEmpty()) {
|
mTransitionToTaskInfo.put(transition, taskInfoList);
|
||||||
mTransitionToWindowDecors.put(transition, windowDecors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onOpenTransitionReady(
|
private void onOpenTransitionReady(
|
||||||
TransitionInfo.Change change,
|
TransitionInfo.Change change,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT) {
|
SurfaceControl.Transaction finishT) {
|
||||||
switch (change.getTaskInfo().getWindowingMode()){
|
mWindowDecorViewModel.createWindowDecoration(
|
||||||
case WINDOWING_MODE_FREEFORM:
|
change.getTaskInfo(), change.getLeash(), startT, finishT);
|
||||||
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
|
|
||||||
break;
|
|
||||||
case WINDOWING_MODE_FULLSCREEN:
|
|
||||||
mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onCloseTransitionReady(
|
private void onCloseTransitionReady(
|
||||||
TransitionInfo.Change change,
|
TransitionInfo.Change change,
|
||||||
ArrayList<AutoCloseable> windowDecors,
|
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT) {
|
SurfaceControl.Transaction finishT) {
|
||||||
final AutoCloseable windowDecor;
|
mWindowDecorViewModel.setupWindowDecorationForTransition(
|
||||||
switch (change.getTaskInfo().getWindowingMode()) {
|
change.getTaskInfo(), startT, finishT);
|
||||||
case WINDOWING_MODE_FREEFORM:
|
|
||||||
windowDecor = mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(),
|
|
||||||
startT, finishT);
|
|
||||||
break;
|
|
||||||
case WINDOWING_MODE_FULLSCREEN:
|
|
||||||
windowDecor = mFullscreenTaskListener.giveWindowDecoration(change.getTaskInfo(),
|
|
||||||
startT, finishT);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
windowDecor = null;
|
|
||||||
}
|
|
||||||
if (windowDecor != null) {
|
|
||||||
windowDecors.add(windowDecor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onChangeTransitionReady(
|
private void onChangeTransitionReady(
|
||||||
int type,
|
|
||||||
TransitionInfo.Change change,
|
TransitionInfo.Change change,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT) {
|
SurfaceControl.Transaction finishT) {
|
||||||
AutoCloseable windowDecor = null;
|
mWindowDecorViewModel.setupWindowDecorationForTransition(
|
||||||
|
|
||||||
boolean adopted = false;
|
|
||||||
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
|
|
||||||
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
|
|
||||||
windowDecor = mFreeformTaskListener.giveWindowDecoration(
|
|
||||||
change.getTaskInfo(), startT, finishT);
|
change.getTaskInfo(), startT, finishT);
|
||||||
if (windowDecor != null) {
|
|
||||||
adopted = mFullscreenTaskListener.adoptWindowDecoration(
|
|
||||||
change, startT, finishT, windowDecor);
|
|
||||||
} else {
|
|
||||||
// will return false if it already has the window decor.
|
|
||||||
adopted = mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
|
|
||||||
windowDecor = mFullscreenTaskListener.giveWindowDecoration(
|
|
||||||
change.getTaskInfo(), startT, finishT);
|
|
||||||
if (windowDecor != null) {
|
|
||||||
adopted = mFreeformTaskListener.adoptWindowDecoration(
|
|
||||||
change, startT, finishT, windowDecor);
|
|
||||||
} else {
|
|
||||||
// will return false if it already has the window decor.
|
|
||||||
adopted = mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!adopted) {
|
|
||||||
releaseWindowDecor(windowDecor);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -203,43 +143,32 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
|
public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
|
||||||
final List<AutoCloseable> windowDecorsOfMerged = mTransitionToWindowDecors.get(merged);
|
final List<ActivityManager.RunningTaskInfo> infoOfMerged =
|
||||||
if (windowDecorsOfMerged == null) {
|
mTransitionToTaskInfo.get(merged);
|
||||||
|
if (infoOfMerged == null) {
|
||||||
// We are adding window decorations of the merged transition to them of the playing
|
// We are adding window decorations of the merged transition to them of the playing
|
||||||
// transition so if there is none of them there is nothing to do.
|
// transition so if there is none of them there is nothing to do.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mTransitionToWindowDecors.remove(merged);
|
mTransitionToTaskInfo.remove(merged);
|
||||||
|
|
||||||
final List<AutoCloseable> windowDecorsOfPlaying = mTransitionToWindowDecors.get(playing);
|
final List<ActivityManager.RunningTaskInfo> infoOfPlaying =
|
||||||
if (windowDecorsOfPlaying != null) {
|
mTransitionToTaskInfo.get(playing);
|
||||||
windowDecorsOfPlaying.addAll(windowDecorsOfMerged);
|
if (infoOfPlaying != null) {
|
||||||
|
infoOfPlaying.addAll(infoOfMerged);
|
||||||
} else {
|
} else {
|
||||||
mTransitionToWindowDecors.put(playing, windowDecorsOfMerged);
|
mTransitionToTaskInfo.put(playing, infoOfMerged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {
|
public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {
|
||||||
final List<AutoCloseable> windowDecors = mTransitionToWindowDecors.getOrDefault(
|
final List<ActivityManager.RunningTaskInfo> taskInfo =
|
||||||
transition, Collections.emptyList());
|
mTransitionToTaskInfo.getOrDefault(transition, Collections.emptyList());
|
||||||
mTransitionToWindowDecors.remove(transition);
|
mTransitionToTaskInfo.remove(transition);
|
||||||
|
|
||||||
for (AutoCloseable windowDecor : windowDecors) {
|
for (int i = 0; i < taskInfo.size(); ++i) {
|
||||||
releaseWindowDecor(windowDecor);
|
mWindowDecorViewModel.destroyWindowDecoration(taskInfo.get(i));
|
||||||
}
|
|
||||||
mFullscreenTaskListener.onTaskTransitionFinished();
|
|
||||||
mFreeformTaskListener.onTaskTransitionFinished();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void releaseWindowDecor(AutoCloseable windowDecor) {
|
|
||||||
if (windowDecor == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
windowDecor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Failed to release window decoration.", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,10 @@ import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.graphics.Point;
|
import android.graphics.Point;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
import android.window.TransitionInfo;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
@@ -46,23 +43,20 @@ import java.util.Optional;
|
|||||||
* Organizes tasks presented in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN}.
|
* Organizes tasks presented in {@link android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN}.
|
||||||
* @param <T> the type of window decoration instance
|
* @param <T> the type of window decoration instance
|
||||||
*/
|
*/
|
||||||
public class FullscreenTaskListener<T extends AutoCloseable>
|
public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||||
implements ShellTaskOrganizer.TaskListener {
|
|
||||||
private static final String TAG = "FullscreenTaskListener";
|
private static final String TAG = "FullscreenTaskListener";
|
||||||
|
|
||||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||||
|
|
||||||
private final SparseArray<State<T>> mTasks = new SparseArray<>();
|
private final SparseArray<State> mTasks = new SparseArray<>();
|
||||||
private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
|
|
||||||
|
|
||||||
private static class State<T extends AutoCloseable> {
|
private static class State {
|
||||||
RunningTaskInfo mTaskInfo;
|
RunningTaskInfo mTaskInfo;
|
||||||
SurfaceControl mLeash;
|
SurfaceControl mLeash;
|
||||||
T mWindowDecoration;
|
|
||||||
}
|
}
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
private final Optional<RecentTasksController> mRecentTasksOptional;
|
private final Optional<RecentTasksController> mRecentTasksOptional;
|
||||||
private final Optional<WindowDecorViewModel<T>> mWindowDecorViewModelOptional;
|
private final Optional<WindowDecorViewModel> mWindowDecorViewModelOptional;
|
||||||
/**
|
/**
|
||||||
* This constructor is used by downstream products.
|
* This constructor is used by downstream products.
|
||||||
*/
|
*/
|
||||||
@@ -75,7 +69,7 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
|||||||
ShellTaskOrganizer shellTaskOrganizer,
|
ShellTaskOrganizer shellTaskOrganizer,
|
||||||
SyncTransactionQueue syncQueue,
|
SyncTransactionQueue syncQueue,
|
||||||
Optional<RecentTasksController> recentTasksOptional,
|
Optional<RecentTasksController> recentTasksOptional,
|
||||||
Optional<WindowDecorViewModel<T>> windowDecorViewModelOptional) {
|
Optional<WindowDecorViewModel> windowDecorViewModelOptional) {
|
||||||
mShellTaskOrganizer = shellTaskOrganizer;
|
mShellTaskOrganizer = shellTaskOrganizer;
|
||||||
mSyncQueue = syncQueue;
|
mSyncQueue = syncQueue;
|
||||||
mRecentTasksOptional = recentTasksOptional;
|
mRecentTasksOptional = recentTasksOptional;
|
||||||
@@ -98,21 +92,21 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
|||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
final Point positionInParent = taskInfo.positionInParent;
|
final Point positionInParent = taskInfo.positionInParent;
|
||||||
final State<T> state = new State();
|
final State state = new State();
|
||||||
state.mLeash = leash;
|
state.mLeash = leash;
|
||||||
state.mTaskInfo = taskInfo;
|
state.mTaskInfo = taskInfo;
|
||||||
mTasks.put(taskInfo.taskId, state);
|
mTasks.put(taskInfo.taskId, state);
|
||||||
|
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||||
|
boolean createdWindowDecor = false;
|
||||||
if (mWindowDecorViewModelOptional.isPresent()) {
|
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
state.mWindowDecoration =
|
createdWindowDecor = mWindowDecorViewModelOptional.get()
|
||||||
mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo,
|
.createWindowDecoration(taskInfo, leash, t, t);
|
||||||
leash, t, t);
|
|
||||||
t.apply();
|
t.apply();
|
||||||
}
|
}
|
||||||
if (state.mWindowDecoration == null) {
|
if (!createdWindowDecor) {
|
||||||
mSyncQueue.runInSync(t -> {
|
mSyncQueue.runInSync(t -> {
|
||||||
// Reset several properties back to fullscreen (PiP, for example, leaves all these
|
// Reset several properties back to fullscreen (PiP, for example, leaves all these
|
||||||
// properties in a bad state).
|
// properties in a bad state).
|
||||||
@@ -127,12 +121,11 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
final State state = mTasks.get(taskInfo.taskId);
|
||||||
final Point oldPositionInParent = state.mTaskInfo.positionInParent;
|
final Point oldPositionInParent = state.mTaskInfo.positionInParent;
|
||||||
state.mTaskInfo = taskInfo;
|
state.mTaskInfo = taskInfo;
|
||||||
if (state.mWindowDecoration != null) {
|
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||||
mWindowDecorViewModelOptional.get().onTaskInfoChanged(
|
mWindowDecorViewModelOptional.get().onTaskInfoChanged(state.mTaskInfo);
|
||||||
state.mTaskInfo, state.mWindowDecoration);
|
|
||||||
}
|
}
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||||
@@ -147,160 +140,13 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state == null) {
|
|
||||||
// This is possible if the transition happens before this method.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
mTasks.remove(taskInfo.taskId);
|
mTasks.remove(taskInfo.taskId);
|
||||||
|
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||||
// Save window decorations of closing tasks so that we can hand them over to the
|
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||||
// transition system if this method happens before the transition. In case where the
|
mWindowDecorViewModelOptional.get().destroyWindowDecoration(taskInfo);
|
||||||
// transition didn't happen, it'd be cleared when the next transition finished.
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
releaseWindowDecor(state.mWindowDecoration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a window decoration for a transition.
|
|
||||||
*
|
|
||||||
* @param change the change of this task transition that needs to have the task layer as the
|
|
||||||
* leash
|
|
||||||
* @return {@code true} if a decoration was actually created.
|
|
||||||
*/
|
|
||||||
public boolean createWindowDecoration(TransitionInfo.Change change,
|
|
||||||
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
|
|
||||||
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
|
|
||||||
if (!mWindowDecorViewModelOptional.isPresent()) return false;
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
// Already has a decoration.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
T newWindowDecor = mWindowDecorViewModelOptional.get().createWindowDecoration(
|
|
||||||
state.mTaskInfo, state.mLeash, startT, finishT);
|
|
||||||
if (newWindowDecor != null) {
|
|
||||||
state.mWindowDecoration = newWindowDecor;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adopt the incoming window decoration and lets the window decoration prepare for a transition.
|
|
||||||
*
|
|
||||||
* @param change the change of this task transition that needs to have the task layer as the
|
|
||||||
* leash
|
|
||||||
* @param startT the start transaction of this transition
|
|
||||||
* @param finishT the finish transaction of this transition
|
|
||||||
* @param windowDecor the window decoration to adopt
|
|
||||||
* @return {@code true} if it adopts the window decoration; {@code false} otherwise
|
|
||||||
*/
|
|
||||||
public boolean adoptWindowDecoration(
|
|
||||||
TransitionInfo.Change change,
|
|
||||||
SurfaceControl.Transaction startT,
|
|
||||||
SurfaceControl.Transaction finishT,
|
|
||||||
@Nullable AutoCloseable windowDecor) {
|
|
||||||
if (!mWindowDecorViewModelOptional.isPresent()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
|
|
||||||
state.mWindowDecoration = mWindowDecorViewModelOptional.get().adoptWindowDecoration(
|
|
||||||
windowDecor);
|
|
||||||
if (state.mWindowDecoration != null) {
|
|
||||||
mWindowDecorViewModelOptional.get().setupWindowDecorationForTransition(
|
|
||||||
state.mTaskInfo, startT, finishT, state.mWindowDecoration);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
T newWindowDecor = mWindowDecorViewModelOptional.get().createWindowDecoration(
|
|
||||||
state.mTaskInfo, state.mLeash, startT, finishT);
|
|
||||||
if (newWindowDecor != null) {
|
|
||||||
state.mWindowDecoration = newWindowDecor;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear window decors of vanished tasks.
|
|
||||||
*/
|
|
||||||
public void onTaskTransitionFinished() {
|
|
||||||
if (mWindowDecorOfVanishedTasks.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS,
|
|
||||||
"Clearing window decors of vanished tasks. There could be visual defects "
|
|
||||||
+ "if any of them is used later in transitions.");
|
|
||||||
for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
|
|
||||||
releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
|
|
||||||
}
|
|
||||||
mWindowDecorOfVanishedTasks.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gives out the ownership of the task's window decoration. The given task is leaving (of has
|
|
||||||
* left) this task listener. This is the transition system asking for the ownership.
|
|
||||||
*
|
|
||||||
* @param taskInfo the maximizing task
|
|
||||||
* @return the window decor of the maximizing task if any
|
|
||||||
*/
|
|
||||||
public T giveWindowDecoration(
|
|
||||||
ActivityManager.RunningTaskInfo taskInfo,
|
|
||||||
SurfaceControl.Transaction startT,
|
|
||||||
SurfaceControl.Transaction finishT) {
|
|
||||||
T windowDecor;
|
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state != null) {
|
|
||||||
windowDecor = state.mWindowDecoration;
|
|
||||||
state.mWindowDecoration = null;
|
|
||||||
} else {
|
|
||||||
windowDecor =
|
|
||||||
mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
|
|
||||||
}
|
|
||||||
if (mWindowDecorViewModelOptional.isPresent() && windowDecor != null) {
|
|
||||||
mWindowDecorViewModelOptional.get().setupWindowDecorationForTransition(
|
|
||||||
taskInfo, startT, finishT, windowDecor);
|
|
||||||
}
|
|
||||||
|
|
||||||
return windowDecor;
|
|
||||||
}
|
|
||||||
|
|
||||||
private State<T> createOrUpdateTaskState(ActivityManager.RunningTaskInfo taskInfo,
|
|
||||||
SurfaceControl leash) {
|
|
||||||
State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
if (state != null) {
|
|
||||||
updateTaskInfo(taskInfo);
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = new State<T>();
|
|
||||||
state.mTaskInfo = taskInfo;
|
|
||||||
state.mLeash = leash;
|
|
||||||
mTasks.put(taskInfo.taskId, state);
|
|
||||||
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private State<T> updateTaskInfo(ActivityManager.RunningTaskInfo taskInfo) {
|
|
||||||
final State<T> state = mTasks.get(taskInfo.taskId);
|
|
||||||
state.mTaskInfo = taskInfo;
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void releaseWindowDecor(T windowDecor) {
|
|
||||||
if (windowDecor == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
windowDecor.close();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Failed to release window decoration.", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -342,6 +188,4 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
|
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import android.app.ActivityManager.RunningTaskInfo;
|
|||||||
import android.app.ActivityTaskManager;
|
import android.app.ActivityTaskManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.util.SparseArray;
|
||||||
import android.view.Choreographer;
|
import android.view.Choreographer;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
@@ -46,7 +47,7 @@ import com.android.wm.shell.transition.Transitions;
|
|||||||
* View model for the window decoration with a caption and shadows. Works with
|
* View model for the window decoration with a caption and shadows. Works with
|
||||||
* {@link CaptionWindowDecoration}.
|
* {@link CaptionWindowDecoration}.
|
||||||
*/
|
*/
|
||||||
public class CaptionWindowDecorViewModel implements WindowDecorViewModel<CaptionWindowDecoration> {
|
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||||
private final ActivityTaskManager mActivityTaskManager;
|
private final ActivityTaskManager mActivityTaskManager;
|
||||||
private final ShellTaskOrganizer mTaskOrganizer;
|
private final ShellTaskOrganizer mTaskOrganizer;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -57,6 +58,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
private FreeformTaskTransitionStarter mTransitionStarter;
|
private FreeformTaskTransitionStarter mTransitionStarter;
|
||||||
private DesktopModeController mDesktopModeController;
|
private DesktopModeController mDesktopModeController;
|
||||||
|
|
||||||
|
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
||||||
|
|
||||||
public CaptionWindowDecorViewModel(
|
public CaptionWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
Handler mainHandler,
|
Handler mainHandler,
|
||||||
@@ -81,12 +84,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CaptionWindowDecoration createWindowDecoration(
|
public boolean createWindowDecoration(
|
||||||
ActivityManager.RunningTaskInfo taskInfo,
|
ActivityManager.RunningTaskInfo taskInfo,
|
||||||
SurfaceControl taskSurface,
|
SurfaceControl taskSurface,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT) {
|
SurfaceControl.Transaction finishT) {
|
||||||
if (!shouldShowWindowDecor(taskInfo)) return null;
|
if (!shouldShowWindowDecor(taskInfo)) return false;
|
||||||
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
|
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
|
||||||
mContext,
|
mContext,
|
||||||
mDisplayController,
|
mDisplayController,
|
||||||
@@ -96,30 +99,24 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
mMainHandler,
|
mMainHandler,
|
||||||
mMainChoreographer,
|
mMainChoreographer,
|
||||||
mSyncQueue);
|
mSyncQueue);
|
||||||
|
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
|
||||||
|
|
||||||
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration);
|
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration);
|
||||||
CaptionTouchEventListener touchEventListener =
|
CaptionTouchEventListener touchEventListener =
|
||||||
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
||||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||||
windowDecoration.setDragResizeCallback(taskPositioner);
|
windowDecoration.setDragResizeCallback(taskPositioner);
|
||||||
setupWindowDecorationForTransition(taskInfo, startT, finishT, windowDecoration);
|
setupWindowDecorationForTransition(taskInfo, startT, finishT);
|
||||||
setupCaptionColor(taskInfo, windowDecoration);
|
setupCaptionColor(taskInfo, windowDecoration);
|
||||||
return windowDecoration;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
if (!(windowDecor instanceof CaptionWindowDecoration)) return null;
|
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||||
final CaptionWindowDecoration captionWindowDecor = (CaptionWindowDecoration) windowDecor;
|
if (decoration == null) return;
|
||||||
if (!shouldShowWindowDecor(captionWindowDecor.mTaskInfo)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return captionWindowDecor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
|
|
||||||
decoration.relayout(taskInfo);
|
decoration.relayout(taskInfo);
|
||||||
|
|
||||||
setupCaptionColor(taskInfo, decoration);
|
setupCaptionColor(taskInfo, decoration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,11 +129,22 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
public void setupWindowDecorationForTransition(
|
public void setupWindowDecorationForTransition(
|
||||||
RunningTaskInfo taskInfo,
|
RunningTaskInfo taskInfo,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT,
|
SurfaceControl.Transaction finishT) {
|
||||||
CaptionWindowDecoration decoration) {
|
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||||
|
if (decoration == null) return;
|
||||||
|
|
||||||
decoration.relayout(taskInfo, startT, finishT);
|
decoration.relayout(taskInfo, startT, finishT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyWindowDecoration(RunningTaskInfo taskInfo) {
|
||||||
|
final CaptionWindowDecoration decoration =
|
||||||
|
mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId);
|
||||||
|
if (decoration == null) return;
|
||||||
|
|
||||||
|
decoration.close();
|
||||||
|
}
|
||||||
|
|
||||||
private class CaptionTouchEventListener implements
|
private class CaptionTouchEventListener implements
|
||||||
View.OnClickListener, View.OnTouchListener {
|
View.OnClickListener, View.OnTouchListener {
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ package com.android.wm.shell.windowdecor;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,10 +26,8 @@ import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
|||||||
* customize {@link WindowDecoration}. Its implementations are responsible to interpret user's
|
* customize {@link WindowDecoration}. Its implementations are responsible to interpret user's
|
||||||
* interactions with UI widgets in window decorations and send corresponding requests to system
|
* interactions with UI widgets in window decorations and send corresponding requests to system
|
||||||
* servers.
|
* servers.
|
||||||
*
|
|
||||||
* @param <T> The actual decoration type
|
|
||||||
*/
|
*/
|
||||||
public interface WindowDecorViewModel<T extends AutoCloseable> {
|
public interface WindowDecorViewModel {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the transition starter that starts freeform task transitions.
|
* Sets the transition starter that starts freeform task transitions.
|
||||||
@@ -50,29 +46,19 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
|
|||||||
* @param finishT the finish transaction to restore states after the transition
|
* @param finishT the finish transaction to restore states after the transition
|
||||||
* @return the window decoration object
|
* @return the window decoration object
|
||||||
*/
|
*/
|
||||||
@Nullable T createWindowDecoration(
|
boolean createWindowDecoration(
|
||||||
ActivityManager.RunningTaskInfo taskInfo,
|
ActivityManager.RunningTaskInfo taskInfo,
|
||||||
SurfaceControl taskSurface,
|
SurfaceControl taskSurface,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT);
|
SurfaceControl.Transaction finishT);
|
||||||
|
|
||||||
/**
|
|
||||||
* Adopts the window decoration if possible.
|
|
||||||
* May be {@code null} if a window decor is not needed or the given one is incompatible.
|
|
||||||
*
|
|
||||||
* @param windowDecor the potential window decoration to adopt
|
|
||||||
* @return the window decoration if it can be adopted, or {@code null} otherwise.
|
|
||||||
*/
|
|
||||||
@Nullable T adoptWindowDecoration(@Nullable AutoCloseable windowDecor);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies a task info update on the given task, with the window decoration created previously
|
* Notifies a task info update on the given task, with the window decoration created previously
|
||||||
* for this task by {@link #createWindowDecoration}.
|
* for this task by {@link #createWindowDecoration}.
|
||||||
*
|
*
|
||||||
* @param taskInfo the new task info of the task
|
* @param taskInfo the new task info of the task
|
||||||
* @param windowDecoration the window decoration created for the task
|
|
||||||
*/
|
*/
|
||||||
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo, T windowDecoration);
|
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies a transition is about to start about the given task to give the window decoration a
|
* Notifies a transition is about to start about the given task to give the window decoration a
|
||||||
@@ -80,11 +66,16 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
|
|||||||
*
|
*
|
||||||
* @param startT the start transaction to be applied before the transition
|
* @param startT the start transaction to be applied before the transition
|
||||||
* @param finishT the finish transaction to restore states after the transition
|
* @param finishT the finish transaction to restore states after the transition
|
||||||
* @param windowDecoration the window decoration created for the task
|
|
||||||
*/
|
*/
|
||||||
void setupWindowDecorationForTransition(
|
void setupWindowDecorationForTransition(
|
||||||
ActivityManager.RunningTaskInfo taskInfo,
|
ActivityManager.RunningTaskInfo taskInfo,
|
||||||
SurfaceControl.Transaction startT,
|
SurfaceControl.Transaction startT,
|
||||||
SurfaceControl.Transaction finishT,
|
SurfaceControl.Transaction finishT);
|
||||||
T windowDecoration);
|
|
||||||
|
/**
|
||||||
|
* Destroys the window decoration of the give task.
|
||||||
|
*
|
||||||
|
* @param taskInfo the info of the task
|
||||||
|
*/
|
||||||
|
void destroyWindowDecoration(ActivityManager.RunningTaskInfo taskInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,17 +17,10 @@
|
|||||||
package com.android.wm.shell.freeform;
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||||
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
|
||||||
import static android.view.WindowManager.TRANSIT_CHANGE;
|
|
||||||
import static android.view.WindowManager.TRANSIT_CLOSE;
|
import static android.view.WindowManager.TRANSIT_CLOSE;
|
||||||
import static android.view.WindowManager.TRANSIT_OPEN;
|
import static android.view.WindowManager.TRANSIT_OPEN;
|
||||||
|
|
||||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_MAXIMIZE;
|
|
||||||
import static com.android.wm.shell.transition.Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE;
|
|
||||||
|
|
||||||
import static org.mockito.Mockito.any;
|
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.eq;
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.same;
|
import static org.mockito.Mockito.same;
|
||||||
@@ -44,9 +37,9 @@ import android.window.WindowContainerToken;
|
|||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
|
||||||
import com.android.wm.shell.sysui.ShellInit;
|
import com.android.wm.shell.sysui.ShellInit;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@@ -65,9 +58,7 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
@Mock
|
@Mock
|
||||||
private Transitions mTransitions;
|
private Transitions mTransitions;
|
||||||
@Mock
|
@Mock
|
||||||
private FullscreenTaskListener<?> mFullscreenTaskListener;
|
private WindowDecorViewModel mWindowDecorViewModel;
|
||||||
@Mock
|
|
||||||
private FreeformTaskListener<?> mFreeformTaskListener;
|
|
||||||
|
|
||||||
private FreeformTaskTransitionObserver mTransitionObserver;
|
private FreeformTaskTransitionObserver mTransitionObserver;
|
||||||
|
|
||||||
@@ -82,7 +73,7 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
doReturn(pm).when(context).getPackageManager();
|
doReturn(pm).when(context).getPackageManager();
|
||||||
|
|
||||||
mTransitionObserver = new FreeformTaskTransitionObserver(
|
mTransitionObserver = new FreeformTaskTransitionObserver(
|
||||||
context, mShellInit, mTransitions, mFullscreenTaskListener, mFreeformTaskListener);
|
context, mShellInit, mTransitions, mWindowDecorViewModel);
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass(
|
final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass(
|
||||||
Runnable.class);
|
Runnable.class);
|
||||||
@@ -112,11 +103,12 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
||||||
mTransitionObserver.onTransitionStarting(transition);
|
mTransitionObserver.onTransitionStarting(transition);
|
||||||
|
|
||||||
verify(mFreeformTaskListener).createWindowDecoration(change, startT, finishT);
|
verify(mWindowDecorViewModel).createWindowDecoration(
|
||||||
|
change.getTaskInfo(), change.getLeash(), startT, finishT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testObtainsWindowDecorOnCloseTransition_freeform() {
|
public void testPreparesWindowDecorOnCloseTransition_freeform() {
|
||||||
final TransitionInfo.Change change =
|
final TransitionInfo.Change change =
|
||||||
createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
|
createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
|
||||||
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
|
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||||
@@ -128,7 +120,8 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
||||||
mTransitionObserver.onTransitionStarting(transition);
|
mTransitionObserver.onTransitionStarting(transition);
|
||||||
|
|
||||||
verify(mFreeformTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
|
verify(mWindowDecorViewModel).setupWindowDecorationForTransition(
|
||||||
|
change.getTaskInfo(), startT, finishT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -138,17 +131,13 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
|
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||||
info.addChange(change);
|
info.addChange(change);
|
||||||
|
|
||||||
final AutoCloseable windowDecor = mock(AutoCloseable.class);
|
|
||||||
doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition = mock(IBinder.class);
|
final IBinder transition = mock(IBinder.class);
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
||||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
||||||
mTransitionObserver.onTransitionStarting(transition);
|
mTransitionObserver.onTransitionStarting(transition);
|
||||||
|
|
||||||
verify(windowDecor, never()).close();
|
verify(mWindowDecorViewModel, never()).destroyWindowDecoration(change.getTaskInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -159,8 +148,6 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
info.addChange(change);
|
info.addChange(change);
|
||||||
|
|
||||||
final AutoCloseable windowDecor = mock(AutoCloseable.class);
|
final AutoCloseable windowDecor = mock(AutoCloseable.class);
|
||||||
doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition = mock(IBinder.class);
|
final IBinder transition = mock(IBinder.class);
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
||||||
@@ -169,7 +156,7 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
mTransitionObserver.onTransitionStarting(transition);
|
mTransitionObserver.onTransitionStarting(transition);
|
||||||
mTransitionObserver.onTransitionFinished(transition, false);
|
mTransitionObserver.onTransitionFinished(transition, false);
|
||||||
|
|
||||||
verify(windowDecor).close();
|
verify(mWindowDecorViewModel).destroyWindowDecoration(change.getTaskInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -192,10 +179,6 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||||
info2.addChange(change2);
|
info2.addChange(change2);
|
||||||
|
|
||||||
final AutoCloseable windowDecor2 = mock(AutoCloseable.class);
|
|
||||||
doReturn(windowDecor2).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change2.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition2 = mock(IBinder.class);
|
final IBinder transition2 = mock(IBinder.class);
|
||||||
final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
||||||
@@ -204,7 +187,7 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
|
|
||||||
mTransitionObserver.onTransitionFinished(transition1, false);
|
mTransitionObserver.onTransitionFinished(transition1, false);
|
||||||
|
|
||||||
verify(windowDecor2).close();
|
verify(mWindowDecorViewModel).destroyWindowDecoration(change2.getTaskInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -215,10 +198,6 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
final TransitionInfo info1 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
final TransitionInfo info1 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||||
info1.addChange(change1);
|
info1.addChange(change1);
|
||||||
|
|
||||||
final AutoCloseable windowDecor1 = mock(AutoCloseable.class);
|
|
||||||
doReturn(windowDecor1).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change1.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition1 = mock(IBinder.class);
|
final IBinder transition1 = mock(IBinder.class);
|
||||||
final SurfaceControl.Transaction startT1 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT1 = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT1 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT1 = mock(SurfaceControl.Transaction.class);
|
||||||
@@ -231,10 +210,6 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||||
info2.addChange(change2);
|
info2.addChange(change2);
|
||||||
|
|
||||||
final AutoCloseable windowDecor2 = mock(AutoCloseable.class);
|
|
||||||
doReturn(windowDecor2).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change2.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition2 = mock(IBinder.class);
|
final IBinder transition2 = mock(IBinder.class);
|
||||||
final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
||||||
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
||||||
@@ -243,48 +218,8 @@ public class FreeformTaskTransitionObserverTest {
|
|||||||
|
|
||||||
mTransitionObserver.onTransitionFinished(transition1, false);
|
mTransitionObserver.onTransitionFinished(transition1, false);
|
||||||
|
|
||||||
verify(windowDecor1).close();
|
verify(mWindowDecorViewModel).destroyWindowDecoration(change1.getTaskInfo());
|
||||||
verify(windowDecor2).close();
|
verify(mWindowDecorViewModel).destroyWindowDecoration(change2.getTaskInfo());
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransfersWindowDecorOnMaximize() {
|
|
||||||
final TransitionInfo.Change change =
|
|
||||||
createChange(TRANSIT_CHANGE, 1, WINDOWING_MODE_FULLSCREEN);
|
|
||||||
final TransitionInfo info = new TransitionInfo(TRANSIT_MAXIMIZE, 0);
|
|
||||||
info.addChange(change);
|
|
||||||
|
|
||||||
final AutoCloseable windowDecor = mock(AutoCloseable.class);
|
|
||||||
doReturn(windowDecor).when(mFreeformTaskListener).giveWindowDecoration(
|
|
||||||
eq(change.getTaskInfo()), any(), any());
|
|
||||||
|
|
||||||
final IBinder transition = mock(IBinder.class);
|
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
|
||||||
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
|
||||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
|
||||||
mTransitionObserver.onTransitionStarting(transition);
|
|
||||||
|
|
||||||
verify(mFreeformTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
|
|
||||||
verify(mFullscreenTaskListener).adoptWindowDecoration(
|
|
||||||
eq(change), same(startT), same(finishT), any());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testTransfersWindowDecorOnRestoreFromMaximize() {
|
|
||||||
final TransitionInfo.Change change =
|
|
||||||
createChange(TRANSIT_CHANGE, 1, WINDOWING_MODE_FREEFORM);
|
|
||||||
final TransitionInfo info = new TransitionInfo(TRANSIT_RESTORE_FROM_MAXIMIZE, 0);
|
|
||||||
info.addChange(change);
|
|
||||||
|
|
||||||
final IBinder transition = mock(IBinder.class);
|
|
||||||
final SurfaceControl.Transaction startT = mock(SurfaceControl.Transaction.class);
|
|
||||||
final SurfaceControl.Transaction finishT = mock(SurfaceControl.Transaction.class);
|
|
||||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
|
||||||
mTransitionObserver.onTransitionStarting(transition);
|
|
||||||
|
|
||||||
verify(mFullscreenTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
|
|
||||||
verify(mFreeformTaskListener).adoptWindowDecoration(
|
|
||||||
eq(change), same(startT), same(finishT), any());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TransitionInfo.Change createChange(int mode, int taskId, int windowingMode) {
|
private static TransitionInfo.Change createChange(int mode, int taskId, int windowingMode) {
|
||||||
|
|||||||
Reference in New Issue
Block a user