Merge "Add WM shell caption to fullscreen tasks" into tm-qpr-dev
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
@@ -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()){
|
||||||
|
case WINDOWING_MODE_FREEFORM:
|
||||||
|
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
|
||||||
|
break;
|
||||||
|
case WINDOWING_MODE_FULLSCREEN:
|
||||||
|
mFullscreenTaskListener.createWindowDecoration(change, startT, finishT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return false;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!adopted) {
|
||||||
releaseWindowDecor(windowDecor);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,15 +94,26 @@ 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;
|
||||||
|
state.mTaskInfo = taskInfo;
|
||||||
|
mTasks.put(taskInfo.taskId, state);
|
||||||
|
|
||||||
|
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||||
|
if (shouldShowWindowDecor(taskInfo) && mWindowDecorViewModelOptional.isPresent()) {
|
||||||
|
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
|
state.mWindowDecoration =
|
||||||
|
mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo,
|
||||||
|
leash, t, t);
|
||||||
|
t.apply();
|
||||||
|
} else {
|
||||||
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).
|
||||||
@@ -94,37 +123,175 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
|
|||||||
t.setMatrix(leash, 1, 0, 0, 1);
|
t.setMatrix(leash, 1, 0, 0, 1);
|
||||||
t.show(leash);
|
t.show(leash);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
|
final State<T> 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);
|
||||||
|
}
|
||||||
|
updateRecentsForVisibleFullscreenTask(taskInfo);
|
||||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) return;
|
||||||
|
|
||||||
updateRecentsForVisibleFullscreenTask(taskInfo);
|
final Point positionInParent = state.mTaskInfo.positionInParent;
|
||||||
|
if (!oldPositionInParent.equals(state.mTaskInfo.positionInParent)) {
|
||||||
final TaskData data = mDataByTaskId.get(taskInfo.taskId);
|
|
||||||
final Point positionInParent = taskInfo.positionInParent;
|
|
||||||
if (!positionInParent.equals(data.positionInParent)) {
|
|
||||||
data.positionInParent.set(positionInParent.x, positionInParent.y);
|
|
||||||
mSyncQueue.runInSync(t -> {
|
mSyncQueue.runInSync(t -> {
|
||||||
t.setPosition(data.surface, positionInParent.x, positionInParent.y);
|
t.setPosition(state.mLeash, positionInParent.x, positionInParent.y);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskVanished(RunningTaskInfo taskInfo) {
|
public void onTaskVanished(ActivityManager.RunningTaskInfo taskInfo) {
|
||||||
if (mDataByTaskId.get(taskInfo.taskId) == null) {
|
final State<T> state = mTasks.get(taskInfo.taskId);
|
||||||
Slog.e(TAG, "Task already vanished: #" + 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user