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}
|
||||
@BindsOptionalOf
|
||||
@DynamicOverride
|
||||
abstract FullscreenTaskListener<?> optionalFullscreenTaskListener();
|
||||
abstract FullscreenTaskListener optionalFullscreenTaskListener();
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static FullscreenTaskListener<?> provideFullscreenTaskListener(
|
||||
@DynamicOverride Optional<FullscreenTaskListener<?>> fullscreenTaskListener,
|
||||
static FullscreenTaskListener provideFullscreenTaskListener(
|
||||
@DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
|
||||
ShellInit shellInit,
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
SyncTransactionQueue syncQueue,
|
||||
Optional<RecentTasksController> recentTasksOptional,
|
||||
Optional<WindowDecorViewModel<?>> windowDecorViewModelOptional) {
|
||||
Optional<WindowDecorViewModel> windowDecorViewModelOptional) {
|
||||
if (fullscreenTaskListener.isPresent()) {
|
||||
return fullscreenTaskListener.get();
|
||||
} else {
|
||||
@@ -316,7 +316,7 @@ public abstract class WMShellBaseModule {
|
||||
//
|
||||
|
||||
@BindsOptionalOf
|
||||
abstract WindowDecorViewModel<?> optionalWindowDecorViewModel();
|
||||
abstract WindowDecorViewModel optionalWindowDecorViewModel();
|
||||
|
||||
//
|
||||
// Unfold transition
|
||||
@@ -768,7 +768,7 @@ public abstract class WMShellBaseModule {
|
||||
Optional<SplitScreenController> splitScreenOptional,
|
||||
Optional<Pip> pipOptional,
|
||||
Optional<PipTouchHandler> pipTouchHandlerOptional,
|
||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
||||
FullscreenTaskListener fullscreenTaskListener,
|
||||
Optional<UnfoldAnimationController> unfoldAnimationController,
|
||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||
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.FreeformTaskTransitionHandler;
|
||||
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.onehanded.OneHandedController;
|
||||
import com.android.wm.shell.pip.Pip;
|
||||
@@ -183,7 +182,7 @@ public abstract class WMShellModule {
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static WindowDecorViewModel<?> provideWindowDecorViewModel(
|
||||
static WindowDecorViewModel provideWindowDecorViewModel(
|
||||
Context context,
|
||||
@ShellMainThread Handler mainHandler,
|
||||
@ShellMainThread Choreographer mainChoreographer,
|
||||
@@ -209,7 +208,7 @@ public abstract class WMShellModule {
|
||||
@Provides
|
||||
@DynamicOverride
|
||||
static FreeformComponents provideFreeformComponents(
|
||||
FreeformTaskListener<?> taskListener,
|
||||
FreeformTaskListener taskListener,
|
||||
FreeformTaskTransitionHandler transitionHandler,
|
||||
FreeformTaskTransitionObserver transitionObserver) {
|
||||
return new FreeformComponents(
|
||||
@@ -218,18 +217,18 @@ public abstract class WMShellModule {
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static FreeformTaskListener<?> provideFreeformTaskListener(
|
||||
static FreeformTaskListener provideFreeformTaskListener(
|
||||
Context context,
|
||||
ShellInit shellInit,
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
||||
WindowDecorViewModel windowDecorViewModel) {
|
||||
// TODO(b/238217847): Temporarily add this check here until we can remove the dynamic
|
||||
// override for this controller from the base module
|
||||
ShellInit init = FreeformComponents.isFreeformEnabled(context)
|
||||
? shellInit
|
||||
: null;
|
||||
return new FreeformTaskListener<>(init, shellTaskOrganizer, desktopModeTaskRepository,
|
||||
return new FreeformTaskListener(init, shellTaskOrganizer, desktopModeTaskRepository,
|
||||
windowDecorViewModel);
|
||||
}
|
||||
|
||||
@@ -238,7 +237,7 @@ public abstract class WMShellModule {
|
||||
static FreeformTaskTransitionHandler provideFreeformTaskTransitionHandler(
|
||||
ShellInit shellInit,
|
||||
Transitions transitions,
|
||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
||||
WindowDecorViewModel windowDecorViewModel) {
|
||||
return new FreeformTaskTransitionHandler(shellInit, transitions, windowDecorViewModel);
|
||||
}
|
||||
|
||||
@@ -248,10 +247,9 @@ public abstract class WMShellModule {
|
||||
Context context,
|
||||
ShellInit shellInit,
|
||||
Transitions transitions,
|
||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
||||
FreeformTaskListener<?> freeformTaskListener) {
|
||||
WindowDecorViewModel windowDecorViewModel) {
|
||||
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 android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
@@ -41,31 +37,26 @@ import java.util.Optional;
|
||||
/**
|
||||
* {@link ShellTaskOrganizer.TaskListener} for {@link
|
||||
* ShellTaskOrganizer#TASK_LISTENER_TYPE_FREEFORM}.
|
||||
*
|
||||
* @param <T> the type of window decoration instance
|
||||
*/
|
||||
public class FreeformTaskListener<T extends AutoCloseable>
|
||||
implements ShellTaskOrganizer.TaskListener {
|
||||
public class FreeformTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
private static final String TAG = "FreeformTaskListener";
|
||||
|
||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||
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<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
|
||||
private final SparseArray<State> mTasks = new SparseArray<>();
|
||||
|
||||
private static class State<T extends AutoCloseable> {
|
||||
private static class State {
|
||||
RunningTaskInfo mTaskInfo;
|
||||
SurfaceControl mLeash;
|
||||
T mWindowDecoration;
|
||||
}
|
||||
|
||||
public FreeformTaskListener(
|
||||
ShellInit shellInit,
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
Optional<DesktopModeTaskRepository> desktopModeTaskRepository,
|
||||
WindowDecorViewModel<T> windowDecorationViewModel) {
|
||||
WindowDecorViewModel windowDecorationViewModel) {
|
||||
mShellTaskOrganizer = shellTaskOrganizer;
|
||||
mWindowDecorationViewModel = windowDecorationViewModel;
|
||||
mDesktopModeTaskRepository = desktopModeTaskRepository;
|
||||
@@ -80,13 +71,18 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
||||
|
||||
@Override
|
||||
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",
|
||||
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) {
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
state.mWindowDecoration =
|
||||
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
|
||||
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
|
||||
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
|
||||
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",
|
||||
taskInfo.taskId);
|
||||
mTasks.remove(taskInfo.taskId);
|
||||
@@ -129,26 +105,18 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
||||
mDesktopModeTaskRepository.ifPresent(it -> it.removeActiveTask(taskInfo.taskId));
|
||||
}
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
// Save window decorations of closing tasks so that we can hand them over to the
|
||||
// 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;
|
||||
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
mWindowDecorationViewModel.destroyWindowDecoration(taskInfo);
|
||||
}
|
||||
releaseWindowDecor(state.mWindowDecoration);
|
||||
}
|
||||
|
||||
@Override
|
||||
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",
|
||||
taskInfo.taskId);
|
||||
if (state.mWindowDecoration != null) {
|
||||
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
|
||||
}
|
||||
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo);
|
||||
|
||||
if (DesktopModeStatus.IS_SUPPORTED) {
|
||||
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
|
||||
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
||||
b.setParent(findTaskSurface(taskId));
|
||||
@@ -186,103 +145,6 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
||||
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
|
||||
public void dump(PrintWriter pw, String prefix) {
|
||||
final String innerPrefix = prefix + " ";
|
||||
|
||||
@@ -46,14 +46,14 @@ public class FreeformTaskTransitionHandler
|
||||
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
|
||||
|
||||
private final Transitions mTransitions;
|
||||
private final WindowDecorViewModel<?> mWindowDecorViewModel;
|
||||
private final WindowDecorViewModel mWindowDecorViewModel;
|
||||
|
||||
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
|
||||
|
||||
public FreeformTaskTransitionHandler(
|
||||
ShellInit shellInit,
|
||||
Transitions transitions,
|
||||
WindowDecorViewModel<?> windowDecorViewModel) {
|
||||
WindowDecorViewModel windowDecorViewModel) {
|
||||
mTransitions = transitions;
|
||||
mWindowDecorViewModel = windowDecorViewModel;
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
|
||||
@@ -16,13 +16,9 @@
|
||||
|
||||
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.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.window.TransitionInfo;
|
||||
@@ -31,9 +27,9 @@ import android.window.WindowContainerToken;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
||||
import com.android.wm.shell.sysui.ShellInit;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -47,23 +43,19 @@ import java.util.Map;
|
||||
* be a part of transitions.
|
||||
*/
|
||||
public class FreeformTaskTransitionObserver implements Transitions.TransitionObserver {
|
||||
private static final String TAG = "FreeformTO";
|
||||
|
||||
private final Transitions mTransitions;
|
||||
private final FreeformTaskListener<?> mFreeformTaskListener;
|
||||
private final FullscreenTaskListener<?> mFullscreenTaskListener;
|
||||
private final WindowDecorViewModel mWindowDecorViewModel;
|
||||
|
||||
private final Map<IBinder, List<AutoCloseable>> mTransitionToWindowDecors = new HashMap<>();
|
||||
private final Map<IBinder, List<ActivityManager.RunningTaskInfo>> mTransitionToTaskInfo =
|
||||
new HashMap<>();
|
||||
|
||||
public FreeformTaskTransitionObserver(
|
||||
Context context,
|
||||
ShellInit shellInit,
|
||||
Transitions transitions,
|
||||
FullscreenTaskListener<?> fullscreenTaskListener,
|
||||
FreeformTaskListener<?> freeformTaskListener) {
|
||||
WindowDecorViewModel windowDecorViewModel) {
|
||||
mTransitions = transitions;
|
||||
mFreeformTaskListener = freeformTaskListener;
|
||||
mFullscreenTaskListener = fullscreenTaskListener;
|
||||
mWindowDecorViewModel = windowDecorViewModel;
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS && FreeformComponents.isFreeformEnabled(context)) {
|
||||
shellInit.addInitCallback(this::onInit, this);
|
||||
}
|
||||
@@ -80,7 +72,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
||||
@NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startT,
|
||||
@NonNull SurfaceControl.Transaction finishT) {
|
||||
final ArrayList<AutoCloseable> windowDecors = new ArrayList<>();
|
||||
final ArrayList<ActivityManager.RunningTaskInfo> taskInfoList = new ArrayList<>();
|
||||
final ArrayList<WindowContainerToken> taskParents = new ArrayList<>();
|
||||
for (TransitionInfo.Change change : info.getChanges()) {
|
||||
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
|
||||
@@ -110,92 +102,40 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
||||
onOpenTransitionReady(change, startT, finishT);
|
||||
break;
|
||||
case WindowManager.TRANSIT_CLOSE: {
|
||||
onCloseTransitionReady(change, windowDecors, startT, finishT);
|
||||
taskInfoList.add(change.getTaskInfo());
|
||||
onCloseTransitionReady(change, startT, finishT);
|
||||
break;
|
||||
}
|
||||
case WindowManager.TRANSIT_CHANGE:
|
||||
onChangeTransitionReady(info.getType(), change, startT, finishT);
|
||||
onChangeTransitionReady(change, startT, finishT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!windowDecors.isEmpty()) {
|
||||
mTransitionToWindowDecors.put(transition, windowDecors);
|
||||
}
|
||||
mTransitionToTaskInfo.put(transition, taskInfoList);
|
||||
}
|
||||
|
||||
private void onOpenTransitionReady(
|
||||
TransitionInfo.Change change,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT) {
|
||||
switch (change.getTaskInfo().getWindowingMode()){
|
||||
case WINDOWING_MODE_FREEFORM:
|
||||
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
|
||||
break;
|
||||
case WINDOWING_MODE_FULLSCREEN:
|
||||
mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
|
||||
break;
|
||||
}
|
||||
mWindowDecorViewModel.createWindowDecoration(
|
||||
change.getTaskInfo(), change.getLeash(), startT, finishT);
|
||||
}
|
||||
|
||||
private void onCloseTransitionReady(
|
||||
TransitionInfo.Change change,
|
||||
ArrayList<AutoCloseable> windowDecors,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT) {
|
||||
final AutoCloseable windowDecor;
|
||||
switch (change.getTaskInfo().getWindowingMode()) {
|
||||
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);
|
||||
}
|
||||
mWindowDecorViewModel.setupWindowDecorationForTransition(
|
||||
change.getTaskInfo(), startT, finishT);
|
||||
}
|
||||
|
||||
private void onChangeTransitionReady(
|
||||
int type,
|
||||
TransitionInfo.Change change,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT) {
|
||||
AutoCloseable windowDecor = null;
|
||||
|
||||
boolean adopted = false;
|
||||
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
|
||||
if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
|
||||
windowDecor = mFreeformTaskListener.giveWindowDecoration(
|
||||
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);
|
||||
}
|
||||
mWindowDecorViewModel.setupWindowDecorationForTransition(
|
||||
change.getTaskInfo(), startT, finishT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -203,43 +143,32 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs
|
||||
|
||||
@Override
|
||||
public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
|
||||
final List<AutoCloseable> windowDecorsOfMerged = mTransitionToWindowDecors.get(merged);
|
||||
if (windowDecorsOfMerged == null) {
|
||||
final List<ActivityManager.RunningTaskInfo> infoOfMerged =
|
||||
mTransitionToTaskInfo.get(merged);
|
||||
if (infoOfMerged == null) {
|
||||
// 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.
|
||||
return;
|
||||
}
|
||||
mTransitionToWindowDecors.remove(merged);
|
||||
mTransitionToTaskInfo.remove(merged);
|
||||
|
||||
final List<AutoCloseable> windowDecorsOfPlaying = mTransitionToWindowDecors.get(playing);
|
||||
if (windowDecorsOfPlaying != null) {
|
||||
windowDecorsOfPlaying.addAll(windowDecorsOfMerged);
|
||||
final List<ActivityManager.RunningTaskInfo> infoOfPlaying =
|
||||
mTransitionToTaskInfo.get(playing);
|
||||
if (infoOfPlaying != null) {
|
||||
infoOfPlaying.addAll(infoOfMerged);
|
||||
} else {
|
||||
mTransitionToWindowDecors.put(playing, windowDecorsOfMerged);
|
||||
mTransitionToTaskInfo.put(playing, infoOfMerged);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionFinished(@NonNull IBinder transition, boolean aborted) {
|
||||
final List<AutoCloseable> windowDecors = mTransitionToWindowDecors.getOrDefault(
|
||||
transition, Collections.emptyList());
|
||||
mTransitionToWindowDecors.remove(transition);
|
||||
final List<ActivityManager.RunningTaskInfo> taskInfo =
|
||||
mTransitionToTaskInfo.getOrDefault(transition, Collections.emptyList());
|
||||
mTransitionToTaskInfo.remove(transition);
|
||||
|
||||
for (AutoCloseable windowDecor : windowDecors) {
|
||||
releaseWindowDecor(windowDecor);
|
||||
}
|
||||
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);
|
||||
for (int i = 0; i < taskInfo.size(); ++i) {
|
||||
mWindowDecorViewModel.destroyWindowDecoration(taskInfo.get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,10 @@ import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.internal.protolog.common.ProtoLog;
|
||||
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}.
|
||||
* @param <T> the type of window decoration instance
|
||||
*/
|
||||
public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
implements ShellTaskOrganizer.TaskListener {
|
||||
public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
private static final String TAG = "FullscreenTaskListener";
|
||||
|
||||
private final ShellTaskOrganizer mShellTaskOrganizer;
|
||||
|
||||
private final SparseArray<State<T>> mTasks = new SparseArray<>();
|
||||
private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
|
||||
private final SparseArray<State> mTasks = new SparseArray<>();
|
||||
|
||||
private static class State<T extends AutoCloseable> {
|
||||
private static class State {
|
||||
RunningTaskInfo mTaskInfo;
|
||||
SurfaceControl mLeash;
|
||||
T mWindowDecoration;
|
||||
}
|
||||
private final SyncTransactionQueue mSyncQueue;
|
||||
private final Optional<RecentTasksController> mRecentTasksOptional;
|
||||
private final Optional<WindowDecorViewModel<T>> mWindowDecorViewModelOptional;
|
||||
private final Optional<WindowDecorViewModel> mWindowDecorViewModelOptional;
|
||||
/**
|
||||
* This constructor is used by downstream products.
|
||||
*/
|
||||
@@ -75,7 +69,7 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
SyncTransactionQueue syncQueue,
|
||||
Optional<RecentTasksController> recentTasksOptional,
|
||||
Optional<WindowDecorViewModel<T>> windowDecorViewModelOptional) {
|
||||
Optional<WindowDecorViewModel> windowDecorViewModelOptional) {
|
||||
mShellTaskOrganizer = shellTaskOrganizer;
|
||||
mSyncQueue = syncQueue;
|
||||
mRecentTasksOptional = recentTasksOptional;
|
||||
@@ -98,21 +92,21 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Appeared: #%d",
|
||||
taskInfo.taskId);
|
||||
final Point positionInParent = taskInfo.positionInParent;
|
||||
final State<T> state = new State();
|
||||
final State state = new State();
|
||||
state.mLeash = leash;
|
||||
state.mTaskInfo = taskInfo;
|
||||
mTasks.put(taskInfo.taskId, state);
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||
boolean createdWindowDecor = false;
|
||||
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||
state.mWindowDecoration =
|
||||
mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo,
|
||||
leash, t, t);
|
||||
createdWindowDecor = mWindowDecorViewModelOptional.get()
|
||||
.createWindowDecoration(taskInfo, leash, t, t);
|
||||
t.apply();
|
||||
}
|
||||
if (state.mWindowDecoration == null) {
|
||||
if (!createdWindowDecor) {
|
||||
mSyncQueue.runInSync(t -> {
|
||||
// Reset several properties back to fullscreen (PiP, for example, leaves all these
|
||||
// properties in a bad state).
|
||||
@@ -127,12 +121,11 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
|
||||
@Override
|
||||
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;
|
||||
state.mTaskInfo = taskInfo;
|
||||
if (state.mWindowDecoration != null) {
|
||||
mWindowDecorViewModelOptional.get().onTaskInfoChanged(
|
||||
state.mTaskInfo, state.mWindowDecoration);
|
||||
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||
mWindowDecorViewModelOptional.get().onTaskInfoChanged(state.mTaskInfo);
|
||||
}
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||
@@ -147,160 +140,13 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
|
||||
@Override
|
||||
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",
|
||||
taskInfo.taskId);
|
||||
mTasks.remove(taskInfo.taskId);
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
// Save window decorations of closing tasks so that we can hand them over to the
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||
if (mWindowDecorViewModelOptional.isPresent()) {
|
||||
mWindowDecorViewModelOptional.get().destroyWindowDecoration(taskInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,6 +188,4 @@ public class FullscreenTaskListener<T extends AutoCloseable>
|
||||
public String toString() {
|
||||
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.content.Context;
|
||||
import android.os.Handler;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Choreographer;
|
||||
import android.view.MotionEvent;
|
||||
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
|
||||
* {@link CaptionWindowDecoration}.
|
||||
*/
|
||||
public class CaptionWindowDecorViewModel implements WindowDecorViewModel<CaptionWindowDecoration> {
|
||||
public class CaptionWindowDecorViewModel implements WindowDecorViewModel {
|
||||
private final ActivityTaskManager mActivityTaskManager;
|
||||
private final ShellTaskOrganizer mTaskOrganizer;
|
||||
private final Context mContext;
|
||||
@@ -57,6 +58,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
||||
private FreeformTaskTransitionStarter mTransitionStarter;
|
||||
private DesktopModeController mDesktopModeController;
|
||||
|
||||
private final SparseArray<CaptionWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
|
||||
|
||||
public CaptionWindowDecorViewModel(
|
||||
Context context,
|
||||
Handler mainHandler,
|
||||
@@ -81,12 +84,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
||||
}
|
||||
|
||||
@Override
|
||||
public CaptionWindowDecoration createWindowDecoration(
|
||||
public boolean createWindowDecoration(
|
||||
ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl taskSurface,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT) {
|
||||
if (!shouldShowWindowDecor(taskInfo)) return null;
|
||||
if (!shouldShowWindowDecor(taskInfo)) return false;
|
||||
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
|
||||
mContext,
|
||||
mDisplayController,
|
||||
@@ -96,30 +99,24 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
||||
mMainHandler,
|
||||
mMainChoreographer,
|
||||
mSyncQueue);
|
||||
mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
|
||||
|
||||
TaskPositioner taskPositioner = new TaskPositioner(mTaskOrganizer, windowDecoration);
|
||||
CaptionTouchEventListener touchEventListener =
|
||||
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||
windowDecoration.setDragResizeCallback(taskPositioner);
|
||||
setupWindowDecorationForTransition(taskInfo, startT, finishT, windowDecoration);
|
||||
setupWindowDecorationForTransition(taskInfo, startT, finishT);
|
||||
setupCaptionColor(taskInfo, windowDecoration);
|
||||
return windowDecoration;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) {
|
||||
if (!(windowDecor instanceof CaptionWindowDecoration)) return null;
|
||||
final CaptionWindowDecoration captionWindowDecor = (CaptionWindowDecoration) windowDecor;
|
||||
if (!shouldShowWindowDecor(captionWindowDecor.mTaskInfo)) {
|
||||
return null;
|
||||
}
|
||||
return captionWindowDecor;
|
||||
}
|
||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||
if (decoration == null) return;
|
||||
|
||||
@Override
|
||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
|
||||
decoration.relayout(taskInfo);
|
||||
|
||||
setupCaptionColor(taskInfo, decoration);
|
||||
}
|
||||
|
||||
@@ -132,11 +129,22 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
||||
public void setupWindowDecorationForTransition(
|
||||
RunningTaskInfo taskInfo,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT,
|
||||
CaptionWindowDecoration decoration) {
|
||||
SurfaceControl.Transaction finishT) {
|
||||
final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
|
||||
if (decoration == null) return;
|
||||
|
||||
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
|
||||
View.OnClickListener, View.OnTouchListener {
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ package com.android.wm.shell.windowdecor;
|
||||
import android.app.ActivityManager;
|
||||
import android.view.SurfaceControl;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
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
|
||||
* interactions with UI widgets in window decorations and send corresponding requests to system
|
||||
* 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.
|
||||
@@ -50,29 +46,19 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
|
||||
* @param finishT the finish transaction to restore states after the transition
|
||||
* @return the window decoration object
|
||||
*/
|
||||
@Nullable T createWindowDecoration(
|
||||
boolean createWindowDecoration(
|
||||
ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl taskSurface,
|
||||
SurfaceControl.Transaction startT,
|
||||
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
|
||||
* for this task by {@link #createWindowDecoration}.
|
||||
*
|
||||
* @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
|
||||
@@ -80,11 +66,16 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
|
||||
*
|
||||
* @param startT the start transaction to be applied before the transition
|
||||
* @param finishT the finish transaction to restore states after the transition
|
||||
* @param windowDecoration the window decoration created for the task
|
||||
*/
|
||||
void setupWindowDecorationForTransition(
|
||||
ActivityManager.RunningTaskInfo taskInfo,
|
||||
SurfaceControl.Transaction startT,
|
||||
SurfaceControl.Transaction finishT,
|
||||
T windowDecoration);
|
||||
SurfaceControl.Transaction finishT);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
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_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.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.same;
|
||||
@@ -44,9 +37,9 @@ import android.window.WindowContainerToken;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
||||
import com.android.wm.shell.sysui.ShellInit;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -65,9 +58,7 @@ public class FreeformTaskTransitionObserverTest {
|
||||
@Mock
|
||||
private Transitions mTransitions;
|
||||
@Mock
|
||||
private FullscreenTaskListener<?> mFullscreenTaskListener;
|
||||
@Mock
|
||||
private FreeformTaskListener<?> mFreeformTaskListener;
|
||||
private WindowDecorViewModel mWindowDecorViewModel;
|
||||
|
||||
private FreeformTaskTransitionObserver mTransitionObserver;
|
||||
|
||||
@@ -82,7 +73,7 @@ public class FreeformTaskTransitionObserverTest {
|
||||
doReturn(pm).when(context).getPackageManager();
|
||||
|
||||
mTransitionObserver = new FreeformTaskTransitionObserver(
|
||||
context, mShellInit, mTransitions, mFullscreenTaskListener, mFreeformTaskListener);
|
||||
context, mShellInit, mTransitions, mWindowDecorViewModel);
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
final ArgumentCaptor<Runnable> initRunnableCaptor = ArgumentCaptor.forClass(
|
||||
Runnable.class);
|
||||
@@ -112,11 +103,12 @@ public class FreeformTaskTransitionObserverTest {
|
||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
||||
mTransitionObserver.onTransitionStarting(transition);
|
||||
|
||||
verify(mFreeformTaskListener).createWindowDecoration(change, startT, finishT);
|
||||
verify(mWindowDecorViewModel).createWindowDecoration(
|
||||
change.getTaskInfo(), change.getLeash(), startT, finishT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testObtainsWindowDecorOnCloseTransition_freeform() {
|
||||
public void testPreparesWindowDecorOnCloseTransition_freeform() {
|
||||
final TransitionInfo.Change change =
|
||||
createChange(TRANSIT_CLOSE, 1, WINDOWING_MODE_FREEFORM);
|
||||
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||
@@ -128,7 +120,8 @@ public class FreeformTaskTransitionObserverTest {
|
||||
mTransitionObserver.onTransitionReady(transition, info, startT, finishT);
|
||||
mTransitionObserver.onTransitionStarting(transition);
|
||||
|
||||
verify(mFreeformTaskListener).giveWindowDecoration(change.getTaskInfo(), startT, finishT);
|
||||
verify(mWindowDecorViewModel).setupWindowDecorationForTransition(
|
||||
change.getTaskInfo(), startT, finishT);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,17 +131,13 @@ public class FreeformTaskTransitionObserverTest {
|
||||
final TransitionInfo info = new TransitionInfo(TRANSIT_CLOSE, 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(windowDecor, never()).close();
|
||||
verify(mWindowDecorViewModel, never()).destroyWindowDecoration(change.getTaskInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,8 +148,6 @@ public class FreeformTaskTransitionObserverTest {
|
||||
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);
|
||||
@@ -169,7 +156,7 @@ public class FreeformTaskTransitionObserverTest {
|
||||
mTransitionObserver.onTransitionStarting(transition);
|
||||
mTransitionObserver.onTransitionFinished(transition, false);
|
||||
|
||||
verify(windowDecor).close();
|
||||
verify(mWindowDecorViewModel).destroyWindowDecoration(change.getTaskInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -192,10 +179,6 @@ public class FreeformTaskTransitionObserverTest {
|
||||
final TransitionInfo info2 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||
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 SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
||||
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
||||
@@ -204,7 +187,7 @@ public class FreeformTaskTransitionObserverTest {
|
||||
|
||||
mTransitionObserver.onTransitionFinished(transition1, false);
|
||||
|
||||
verify(windowDecor2).close();
|
||||
verify(mWindowDecorViewModel).destroyWindowDecoration(change2.getTaskInfo());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -215,10 +198,6 @@ public class FreeformTaskTransitionObserverTest {
|
||||
final TransitionInfo info1 = new TransitionInfo(TRANSIT_CLOSE, 0);
|
||||
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 SurfaceControl.Transaction startT1 = 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);
|
||||
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 SurfaceControl.Transaction startT2 = mock(SurfaceControl.Transaction.class);
|
||||
final SurfaceControl.Transaction finishT2 = mock(SurfaceControl.Transaction.class);
|
||||
@@ -243,48 +218,8 @@ public class FreeformTaskTransitionObserverTest {
|
||||
|
||||
mTransitionObserver.onTransitionFinished(transition1, false);
|
||||
|
||||
verify(windowDecor1).close();
|
||||
verify(windowDecor2).close();
|
||||
}
|
||||
|
||||
@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());
|
||||
verify(mWindowDecorViewModel).destroyWindowDecoration(change1.getTaskInfo());
|
||||
verify(mWindowDecorViewModel).destroyWindowDecoration(change2.getTaskInfo());
|
||||
}
|
||||
|
||||
private static TransitionInfo.Change createChange(int mode, int taskId, int windowingMode) {
|
||||
|
||||
Reference in New Issue
Block a user