Merge "Add WM shell caption to fullscreen tasks" into tm-qpr-dev

This commit is contained in:
Matt Sziklay
2022-08-24 16:15:14 +00:00
committed by Android (Google) Code Review
6 changed files with 275 additions and 78 deletions

View File

@@ -85,6 +85,7 @@ import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
import com.android.wm.shell.unfold.UnfoldAnimationController; import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldTransitionHandler; import com.android.wm.shell.unfold.UnfoldTransitionHandler;
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
import java.util.Optional; import java.util.Optional;
@@ -294,24 +295,32 @@ 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) {
if (fullscreenTaskListener.isPresent()) { if (fullscreenTaskListener.isPresent()) {
return fullscreenTaskListener.get(); return fullscreenTaskListener.get();
} else { } else {
return new FullscreenTaskListener(shellInit, shellTaskOrganizer, syncQueue, return new FullscreenTaskListener(shellInit, shellTaskOrganizer, syncQueue,
recentTasksOptional); recentTasksOptional, windowDecorViewModelOptional);
} }
} }
//
// Window Decoration
//
@BindsOptionalOf
abstract WindowDecorViewModel<?> optionalWindowDecorViewModel();
// //
// Unfold transition // Unfold transition
// //
@@ -680,7 +689,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,

View File

@@ -55,6 +55,7 @@ import com.android.wm.shell.draganddrop.DragAndDropController;
import com.android.wm.shell.freeform.FreeformComponents; 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.fullscreen.FullscreenTaskListener;
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;
import com.android.wm.shell.pip.PipAnimationController; import com.android.wm.shell.pip.PipAnimationController;
@@ -233,6 +234,7 @@ public abstract class WMShellModule {
ShellInit shellInit, ShellInit shellInit,
Transitions transitions, Transitions transitions,
WindowDecorViewModel<?> windowDecorViewModel, WindowDecorViewModel<?> windowDecorViewModel,
FullscreenTaskListener<?> fullscreenTaskListener,
FreeformTaskListener<?> freeformTaskListener) { FreeformTaskListener<?> freeformTaskListener) {
// 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
@@ -240,7 +242,7 @@ public abstract class WMShellModule {
? shellInit ? shellInit
: null; : null;
return new FreeformTaskTransitionHandler(init, transitions, return new FreeformTaskTransitionHandler(init, transitions,
windowDecorViewModel, freeformTaskListener); windowDecorViewModel, fullscreenTaskListener, freeformTaskListener);
} }
// //

View File

@@ -187,12 +187,14 @@ public class FreeformTaskListener<T extends AutoCloseable>
RunningTaskInfo taskInfo, RunningTaskInfo taskInfo,
SurfaceControl.Transaction startT, SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) { SurfaceControl.Transaction finishT) {
T windowDecor = mWindowDecorOfVanishedTasks.get(taskInfo.taskId); T windowDecor;
mWindowDecorOfVanishedTasks.remove(taskInfo.taskId);
final State<T> state = mTasks.get(taskInfo.taskId); final State<T> state = mTasks.get(taskInfo.taskId);
if (state != null) { if (state != null) {
windowDecor = windowDecor == null ? state.mWindowDecoration : windowDecor; windowDecor = state.mWindowDecoration;
state.mWindowDecoration = null; state.mWindowDecoration = null;
} else {
windowDecor =
mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId);
} }
mWindowDecorationViewModel.setupWindowDecorationForTransition( mWindowDecorationViewModel.setupWindowDecorationForTransition(
taskInfo, startT, finishT, windowDecor); taskInfo, startT, finishT, windowDecor);
@@ -231,7 +233,8 @@ public class FreeformTaskListener<T extends AutoCloseable>
if (mWindowDecorOfVanishedTasks.size() == 0) { if (mWindowDecorOfVanishedTasks.size() == 0) {
return; return;
} }
Log.w(TAG, "Clearing window decors of vanished tasks. There could be visual defects " 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."); + "if any of them is used later in transitions.");
for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) { for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i)); releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));

View File

@@ -32,6 +32,7 @@ import android.window.WindowContainerTransaction;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
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 com.android.wm.shell.windowdecor.WindowDecorViewModel;
@@ -50,6 +51,7 @@ public class FreeformTaskTransitionHandler
private final Transitions mTransitions; private final Transitions mTransitions;
private final FreeformTaskListener<?> mFreeformTaskListener; private final FreeformTaskListener<?> mFreeformTaskListener;
private final FullscreenTaskListener<?> mFullscreenTaskListener;
private final WindowDecorViewModel<?> mWindowDecorViewModel; private final WindowDecorViewModel<?> mWindowDecorViewModel;
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>(); private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
@@ -58,8 +60,10 @@ public class FreeformTaskTransitionHandler
ShellInit shellInit, ShellInit shellInit,
Transitions transitions, Transitions transitions,
WindowDecorViewModel<?> windowDecorViewModel, WindowDecorViewModel<?> windowDecorViewModel,
FullscreenTaskListener<?> fullscreenTaskListener,
FreeformTaskListener<?> freeformTaskListener) { FreeformTaskListener<?> freeformTaskListener) {
mTransitions = transitions; mTransitions = transitions;
mFullscreenTaskListener = fullscreenTaskListener;
mFreeformTaskListener = freeformTaskListener; mFreeformTaskListener = freeformTaskListener;
mWindowDecorViewModel = windowDecorViewModel; mWindowDecorViewModel = windowDecorViewModel;
if (shellInit != null && Transitions.ENABLE_SHELL_TRANSITIONS) { if (shellInit != null && Transitions.ENABLE_SHELL_TRANSITIONS) {
@@ -150,10 +154,16 @@ public class FreeformTaskTransitionHandler
TransitionInfo.Change change, TransitionInfo.Change change,
SurfaceControl.Transaction startT, SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) { SurfaceControl.Transaction finishT) {
if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) { switch (change.getTaskInfo().getWindowingMode()){
return false; case WINDOWING_MODE_FREEFORM:
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
break;
case WINDOWING_MODE_FULLSCREEN:
mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
break;
default:
return false;
} }
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
// Intercepted transition to manage the window decorations. Let other handlers animate. // Intercepted transition to manage the window decorations. Let other handlers animate.
return false; return false;
@@ -164,15 +174,22 @@ public class FreeformTaskTransitionHandler
ArrayList<AutoCloseable> windowDecors, ArrayList<AutoCloseable> windowDecors,
SurfaceControl.Transaction startT, SurfaceControl.Transaction startT,
SurfaceControl.Transaction finishT) { SurfaceControl.Transaction finishT) {
if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) { final AutoCloseable windowDecor;
return false; 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;
} }
final AutoCloseable windowDecor =
mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(), startT, finishT);
if (windowDecor != null) { if (windowDecor != null) {
windowDecors.add(windowDecor); windowDecors.add(windowDecor);
} }
// Intercepted transition to manage the window decorations. Let other handlers animate. // Intercepted transition to manage the window decorations. Let other handlers animate.
return false; return false;
} }
@@ -197,24 +214,29 @@ public class FreeformTaskTransitionHandler
} }
boolean handled = false; boolean handled = false;
boolean adopted = false;
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo(); final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (type == Transitions.TRANSIT_MAXIMIZE if (type == Transitions.TRANSIT_MAXIMIZE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { && taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
handled = true; handled = true;
windowDecor = mFreeformTaskListener.giveWindowDecoration( windowDecor = mFreeformTaskListener.giveWindowDecoration(
change.getTaskInfo(), startT, finishT); change.getTaskInfo(), startT, finishT);
// TODO(b/235638450): Let fullscreen task listener adopt the window decor. adopted = mFullscreenTaskListener.adoptWindowDecoration(change,
startT, finishT, windowDecor);
} }
if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) { && taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
handled = true; handled = true;
// TODO(b/235638450): Let fullscreen task listener transfer the window decor. windowDecor = mFullscreenTaskListener.giveWindowDecoration(
mFreeformTaskListener.adoptWindowDecoration(change, startT, finishT, windowDecor); change.getTaskInfo(), startT, finishT);
adopted = mFreeformTaskListener.adoptWindowDecoration(change,
startT, finishT, windowDecor);
} }
releaseWindowDecor(windowDecor); if (!adopted) {
releaseWindowDecor(windowDecor);
}
return handled; return handled;
} }
@@ -225,7 +247,7 @@ public class FreeformTaskTransitionHandler
releaseWindowDecor(windowDecor); releaseWindowDecor(windowDecor);
} }
mFreeformTaskListener.onTaskTransitionFinished(); mFreeformTaskListener.onTaskTransitionFinished();
// TODO(b/235638450): Dispatch it to fullscreen task listener. mFullscreenTaskListener.onTaskTransitionFinished();
finishCallback.onTransitionFinished(null, null); finishCallback.onTransitionFinished(null, null);
} }

View File

@@ -16,16 +16,21 @@
package com.android.wm.shell.fullscreen; package com.android.wm.shell.fullscreen;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN;
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString; import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
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.Slog; 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;
@@ -34,36 +39,49 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.recents.RecentTasksController;
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.io.PrintWriter; import java.io.PrintWriter;
import java.util.Optional; 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
*/ */
public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener { public class FullscreenTaskListener<T extends AutoCloseable>
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<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
private static class State<T extends AutoCloseable> {
RunningTaskInfo mTaskInfo;
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 SparseArray<TaskData> mDataByTaskId = new SparseArray<>();
/** /**
* This constructor is used by downstream products. * This constructor is used by downstream products.
*/ */
public FullscreenTaskListener(SyncTransactionQueue syncQueue) { public FullscreenTaskListener(SyncTransactionQueue syncQueue) {
this(null /* shellInit */, null /* shellTaskOrganizer */, syncQueue, Optional.empty()); this(null /* shellInit */, null /* shellTaskOrganizer */, syncQueue, Optional.empty(),
Optional.empty());
} }
public FullscreenTaskListener(ShellInit shellInit, public FullscreenTaskListener(ShellInit shellInit,
ShellTaskOrganizer shellTaskOrganizer, ShellTaskOrganizer shellTaskOrganizer,
SyncTransactionQueue syncQueue, SyncTransactionQueue syncQueue,
Optional<RecentTasksController> recentTasksOptional) { Optional<RecentTasksController> recentTasksOptional,
Optional<WindowDecorViewModel<T>> windowDecorViewModelOptional) {
mShellTaskOrganizer = shellTaskOrganizer; mShellTaskOrganizer = shellTaskOrganizer;
mSyncQueue = syncQueue; mSyncQueue = syncQueue;
mRecentTasksOptional = recentTasksOptional; mRecentTasksOptional = recentTasksOptional;
mWindowDecorViewModelOptional = windowDecorViewModelOptional;
// Note: Some derivative FullscreenTaskListener implementations do not use ShellInit // Note: Some derivative FullscreenTaskListener implementations do not use ShellInit
if (shellInit != null) { if (shellInit != null) {
shellInit.addInitCallback(this::onInit, this); shellInit.addInitCallback(this::onInit, this);
@@ -76,55 +94,204 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
@Override @Override
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
if (mDataByTaskId.get(taskInfo.taskId) != null) { if (mTasks.get(taskInfo.taskId) != null) {
throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId); throw new IllegalStateException("Task appeared more than once: #" + taskInfo.taskId);
} }
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;
mDataByTaskId.put(taskInfo.taskId, new TaskData(leash, positionInParent)); final State<T> state = new State();
state.mLeash = leash;
if (Transitions.ENABLE_SHELL_TRANSITIONS) return; state.mTaskInfo = taskInfo;
mSyncQueue.runInSync(t -> { mTasks.put(taskInfo.taskId, state);
// Reset several properties back to fullscreen (PiP, for example, leaves all these
// properties in a bad state).
t.setWindowCrop(leash, null);
t.setPosition(leash, positionInParent.x, positionInParent.y);
t.setAlpha(leash, 1f);
t.setMatrix(leash, 1, 0, 0, 1);
t.show(leash);
});
updateRecentsForVisibleFullscreenTask(taskInfo); updateRecentsForVisibleFullscreenTask(taskInfo);
}
@Override
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
if (Transitions.ENABLE_SHELL_TRANSITIONS) return; if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
if (shouldShowWindowDecor(taskInfo) && mWindowDecorViewModelOptional.isPresent()) {
updateRecentsForVisibleFullscreenTask(taskInfo); SurfaceControl.Transaction t = new SurfaceControl.Transaction();
state.mWindowDecoration =
final TaskData data = mDataByTaskId.get(taskInfo.taskId); mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo,
final Point positionInParent = taskInfo.positionInParent; leash, t, t);
if (!positionInParent.equals(data.positionInParent)) { t.apply();
data.positionInParent.set(positionInParent.x, positionInParent.y); } else {
mSyncQueue.runInSync(t -> { mSyncQueue.runInSync(t -> {
t.setPosition(data.surface, positionInParent.x, positionInParent.y); // Reset several properties back to fullscreen (PiP, for example, leaves all these
// properties in a bad state).
t.setWindowCrop(leash, null);
t.setPosition(leash, positionInParent.x, positionInParent.y);
t.setAlpha(leash, 1f);
t.setMatrix(leash, 1, 0, 0, 1);
t.show(leash);
}); });
} }
} }
@Override @Override
public void onTaskVanished(RunningTaskInfo taskInfo) { public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
if (mDataByTaskId.get(taskInfo.taskId) == null) { final State<T> state = mTasks.get(taskInfo.taskId);
Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId); final Point oldPositionInParent = state.mTaskInfo.positionInParent;
state.mTaskInfo = taskInfo;
if (state.mWindowDecoration != null) {
mWindowDecorViewModelOptional.get().onTaskInfoChanged(
state.mTaskInfo, state.mWindowDecoration);
}
updateRecentsForVisibleFullscreenTask(taskInfo);
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
final Point positionInParent = state.mTaskInfo.positionInParent;
if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
mSyncQueue.runInSync(t -> {
t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
});
}
}
@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
*/
public void createWindowDecoration(TransitionInfo.Change change,
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
if (!mWindowDecorViewModelOptional.isPresent()
|| !shouldShowWindowDecor(state.mTaskInfo)) {
return; return;
} }
mDataByTaskId.remove(taskInfo.taskId); state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration(
state.mTaskInfo, state.mLeash, startT, finishT);
}
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Fullscreen Task Vanished: #%d", /**
taskInfo.taskId); * 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()
|| !shouldShowWindowDecor(change.getTaskInfo())) {
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 {
state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration(
state.mTaskInfo, state.mLeash, startT, finishT);
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()) {
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) {
try {
windowDecor.close();
} catch (Exception e) {
Log.e(TAG, "Failed to release window decoration.", e);
}
} }
private void updateRecentsForVisibleFullscreenTask(RunningTaskInfo taskInfo) { private void updateRecentsForVisibleFullscreenTask(RunningTaskInfo taskInfo) {
@@ -148,17 +315,17 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
} }
private SurfaceControl findTaskSurface(int taskId) { private SurfaceControl findTaskSurface(int taskId) {
if (!mDataByTaskId.contains(taskId)) { if (!mTasks.contains(taskId)) {
throw new IllegalArgumentException("There is no surface for taskId=" + taskId); throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
} }
return mDataByTaskId.get(taskId).surface; return mTasks.get(taskId).mLeash;
} }
@Override @Override
public void dump(@NonNull PrintWriter pw, String prefix) { public void dump(@NonNull PrintWriter pw, String prefix) {
final String innerPrefix = prefix + " "; final String innerPrefix = prefix + " ";
pw.println(prefix + this); pw.println(prefix + this);
pw.println(innerPrefix + mDataByTaskId.size() + " Tasks"); pw.println(innerPrefix + mTasks.size() + " Tasks");
} }
@Override @Override
@@ -166,16 +333,10 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN); return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN);
} }
/** private static boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) {
* Per-task data for each managed task. return taskInfo.getConfiguration().windowConfiguration.getDisplayWindowingMode()
*/ == WINDOWING_MODE_FREEFORM;
private static class TaskData {
public final SurfaceControl surface;
public final Point positionInParent;
public TaskData(SurfaceControl surface, Point positionInParent) {
this.surface = surface;
this.positionInParent = positionInParent;
}
} }
} }

View File

@@ -142,7 +142,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
return; return;
} }
if (oldDecorationSurface != mDecorationContainerSurface) { if (oldDecorationSurface != mDecorationContainerSurface || mDragResizeListener == null) {
closeDragResizeListener(); closeDragResizeListener();
mDragResizeListener = new DragResizeInputListener( mDragResizeListener = new DragResizeInputListener(
mContext, mContext,