Merge "Add FreeformTaskTransitionHandler" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
3f2c081a30
@@ -29,8 +29,6 @@ import com.android.internal.logging.UiEventLogger;
|
|||||||
import com.android.launcher3.icons.IconProvider;
|
import com.android.launcher3.icons.IconProvider;
|
||||||
import com.android.wm.shell.RootDisplayAreaOrganizer;
|
import com.android.wm.shell.RootDisplayAreaOrganizer;
|
||||||
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
|
||||||
import com.android.wm.shell.sysui.ShellCommandHandler;
|
|
||||||
import com.android.wm.shell.sysui.ShellInit;
|
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.TaskViewFactory;
|
import com.android.wm.shell.TaskViewFactory;
|
||||||
import com.android.wm.shell.TaskViewFactoryController;
|
import com.android.wm.shell.TaskViewFactoryController;
|
||||||
@@ -59,7 +57,7 @@ import com.android.wm.shell.compatui.CompatUIController;
|
|||||||
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
|
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
|
||||||
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
|
import com.android.wm.shell.displayareahelper.DisplayAreaHelperController;
|
||||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||||
import com.android.wm.shell.freeform.FreeformTaskListener;
|
import com.android.wm.shell.freeform.FreeformComponents;
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
||||||
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
|
||||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||||
@@ -78,7 +76,9 @@ import com.android.wm.shell.startingsurface.StartingSurface;
|
|||||||
import com.android.wm.shell.startingsurface.StartingWindowController;
|
import com.android.wm.shell.startingsurface.StartingWindowController;
|
||||||
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
|
import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
|
||||||
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
|
import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
|
||||||
|
import com.android.wm.shell.sysui.ShellCommandHandler;
|
||||||
import com.android.wm.shell.sysui.ShellController;
|
import com.android.wm.shell.sysui.ShellController;
|
||||||
|
import com.android.wm.shell.sysui.ShellInit;
|
||||||
import com.android.wm.shell.sysui.ShellInterface;
|
import com.android.wm.shell.sysui.ShellInterface;
|
||||||
import com.android.wm.shell.transition.ShellTransitions;
|
import com.android.wm.shell.transition.ShellTransitions;
|
||||||
import com.android.wm.shell.transition.Transitions;
|
import com.android.wm.shell.transition.Transitions;
|
||||||
@@ -339,15 +339,15 @@ 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 FreeformTaskListener<?> optionalFreeformTaskListener();
|
abstract FreeformComponents optionalFreeformComponents();
|
||||||
|
|
||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
static Optional<FreeformTaskListener<?>> provideFreeformTaskListener(
|
static Optional<FreeformComponents> provideFreeformTaskListener(
|
||||||
@DynamicOverride Optional<FreeformTaskListener<?>> freeformTaskListener,
|
@DynamicOverride Optional<FreeformComponents> freeformComponents,
|
||||||
Context context) {
|
Context context) {
|
||||||
if (FreeformTaskListener.isFreeformEnabled(context)) {
|
if (FreeformComponents.isFreeformEnabled(context)) {
|
||||||
return freeformTaskListener;
|
return freeformComponents;
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
@@ -636,7 +636,7 @@ public abstract class WMShellBaseModule {
|
|||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<UnfoldAnimationController> unfoldAnimationController,
|
Optional<UnfoldAnimationController> unfoldAnimationController,
|
||||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||||
Optional<FreeformTaskListener<?>> freeformTaskListener,
|
Optional<FreeformComponents> freeformComponents,
|
||||||
Optional<RecentTasksController> recentTasksOptional,
|
Optional<RecentTasksController> recentTasksOptional,
|
||||||
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
|
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
@@ -655,7 +655,7 @@ public abstract class WMShellBaseModule {
|
|||||||
fullscreenTaskListener,
|
fullscreenTaskListener,
|
||||||
unfoldAnimationController,
|
unfoldAnimationController,
|
||||||
unfoldTransitionHandler,
|
unfoldTransitionHandler,
|
||||||
freeformTaskListener,
|
freeformComponents,
|
||||||
recentTasksOptional,
|
recentTasksOptional,
|
||||||
activityEmbeddingOptional,
|
activityEmbeddingOptional,
|
||||||
transitions,
|
transitions,
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ import com.android.wm.shell.common.TransactionPool;
|
|||||||
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
|
import com.android.wm.shell.common.annotations.ShellBackgroundThread;
|
||||||
import com.android.wm.shell.common.annotations.ShellMainThread;
|
import com.android.wm.shell.common.annotations.ShellMainThread;
|
||||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||||
|
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.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;
|
||||||
@@ -194,10 +196,27 @@ public abstract class WMShellModule {
|
|||||||
@WMSingleton
|
@WMSingleton
|
||||||
@Provides
|
@Provides
|
||||||
@DynamicOverride
|
@DynamicOverride
|
||||||
|
static FreeformComponents provideFreeformComponents(
|
||||||
|
FreeformTaskListener<?> taskListener,
|
||||||
|
FreeformTaskTransitionHandler transitionHandler) {
|
||||||
|
return new FreeformComponents(taskListener, Optional.of(transitionHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
@WMSingleton
|
||||||
|
@Provides
|
||||||
static FreeformTaskListener<?> provideFreeformTaskListener(
|
static FreeformTaskListener<?> provideFreeformTaskListener(
|
||||||
|
WindowDecorViewModel<?> windowDecorViewModel) {
|
||||||
|
return new FreeformTaskListener<>(windowDecorViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@WMSingleton
|
||||||
|
@Provides
|
||||||
|
static FreeformTaskTransitionHandler provideTaskTransitionHandler(
|
||||||
|
Transitions transitions,
|
||||||
WindowDecorViewModel<?> windowDecorViewModel,
|
WindowDecorViewModel<?> windowDecorViewModel,
|
||||||
SyncTransactionQueue syncQueue) {
|
FreeformTaskListener<?> freeformTaskListener) {
|
||||||
return new FreeformTaskListener<>(windowDecorViewModel, syncQueue);
|
return new FreeformTaskTransitionHandler(transitions, windowDecorViewModel,
|
||||||
|
freeformTaskListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
|
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
|
||||||
|
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.provider.Settings;
|
||||||
|
|
||||||
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that holds freeform related classes. It serves as the single injection point of
|
||||||
|
* all freeform classes to avoid leaking implementation details to the base Dagger module.
|
||||||
|
*/
|
||||||
|
public class FreeformComponents {
|
||||||
|
public final ShellTaskOrganizer.TaskListener mTaskListener;
|
||||||
|
public final Optional<Transitions.TransitionHandler> mTaskTransitionHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an instance with the given components.
|
||||||
|
*/
|
||||||
|
public FreeformComponents(
|
||||||
|
ShellTaskOrganizer.TaskListener taskListener,
|
||||||
|
Optional<Transitions.TransitionHandler> taskTransitionHandler) {
|
||||||
|
mTaskListener = taskListener;
|
||||||
|
mTaskTransitionHandler = taskTransitionHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if this device supports freeform.
|
||||||
|
*/
|
||||||
|
public static boolean isFreeformEnabled(Context context) {
|
||||||
|
return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
|
||||||
|
|| Settings.Global.getInt(context.getContentResolver(),
|
||||||
|
DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,20 +16,18 @@
|
|||||||
|
|
||||||
package com.android.wm.shell.freeform;
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
|
|
||||||
import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
|
|
||||||
|
|
||||||
import android.app.ActivityManager.RunningTaskInfo;
|
import android.app.ActivityManager.RunningTaskInfo;
|
||||||
import android.content.Context;
|
import android.util.Log;
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.Slog;
|
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
|
import android.window.TransitionInfo;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.android.internal.protolog.common.ProtoLog;
|
import com.android.internal.protolog.common.ProtoLog;
|
||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
|
||||||
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
import com.android.wm.shell.protolog.ShellProtoLogGroup;
|
||||||
|
import com.android.wm.shell.transition.Transitions;
|
||||||
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -45,9 +43,9 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
private static final String TAG = "FreeformTaskListener";
|
private static final String TAG = "FreeformTaskListener";
|
||||||
|
|
||||||
private final WindowDecorViewModel<T> mWindowDecorationViewModel;
|
private final WindowDecorViewModel<T> mWindowDecorationViewModel;
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
|
||||||
|
|
||||||
private final SparseArray<State<T>> mTasks = new SparseArray<>();
|
private final SparseArray<State<T>> mTasks = new SparseArray<>();
|
||||||
|
private final SparseArray<T> mWindowDecorOfVanishedTasks = new SparseArray<>();
|
||||||
|
|
||||||
private static class State<T extends AutoCloseable> {
|
private static class State<T extends AutoCloseable> {
|
||||||
RunningTaskInfo mTaskInfo;
|
RunningTaskInfo mTaskInfo;
|
||||||
@@ -55,58 +53,79 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
T mWindowDecoration;
|
T mWindowDecoration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FreeformTaskListener(
|
public FreeformTaskListener(WindowDecorViewModel<T> windowDecorationViewModel) {
|
||||||
WindowDecorViewModel<T> windowDecorationViewModel,
|
|
||||||
SyncTransactionQueue syncQueue) {
|
|
||||||
mWindowDecorationViewModel = windowDecorationViewModel;
|
mWindowDecorationViewModel = windowDecorationViewModel;
|
||||||
mSyncQueue = syncQueue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) {
|
||||||
if (mTasks.get(taskInfo.taskId) != null) {
|
|
||||||
throw new RuntimeException("Task appeared more than once: #" + taskInfo.taskId);
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Appeared: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
final State<T> state = new State<>();
|
final State<T> state = createOrUpdateTaskState(taskInfo, leash);
|
||||||
|
if (!Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
|
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
|
state.mWindowDecoration =
|
||||||
|
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t);
|
||||||
|
t.apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.mTaskInfo = taskInfo;
|
||||||
state.mLeash = leash;
|
state.mLeash = leash;
|
||||||
state.mWindowDecoration =
|
|
||||||
mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash);
|
|
||||||
mTasks.put(taskInfo.taskId, state);
|
mTasks.put(taskInfo.taskId, state);
|
||||||
|
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskVanished(RunningTaskInfo taskInfo) {
|
public void onTaskVanished(RunningTaskInfo taskInfo) {
|
||||||
State<T> state = mTasks.get(taskInfo.taskId);
|
final State<T> state = mTasks.get(taskInfo.taskId);
|
||||||
if (state == null) {
|
if (state == null) {
|
||||||
Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
|
// This is possible if the transition happens before this method.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
mTasks.remove(taskInfo.taskId);
|
mTasks.remove(taskInfo.taskId);
|
||||||
|
|
||||||
try {
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
state.mWindowDecoration.close();
|
// Save window decorations of closing tasks so that we can hand them over to the
|
||||||
} catch (Exception e) {
|
// transition system if this method happens before the transition. In case where the
|
||||||
Slog.e(TAG, "Failed to release window decoration.", e);
|
// transition didn't happen, it'd be cleared when the next transition finished.
|
||||||
|
if (state.mWindowDecoration != null) {
|
||||||
|
mWindowDecorOfVanishedTasks.put(taskInfo.taskId, state.mWindowDecoration);
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
releaseWindowDecor(state.mWindowDecoration);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
|
||||||
State<T> state = mTasks.get(taskInfo.taskId);
|
final State<T> state = updateTaskInfo(taskInfo);
|
||||||
if (state == null) {
|
|
||||||
throw new RuntimeException(
|
|
||||||
"Task info changed before appearing: #" + taskInfo.taskId);
|
|
||||||
}
|
|
||||||
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
|
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Info Changed: #%d",
|
||||||
taskInfo.taskId);
|
taskInfo.taskId);
|
||||||
state.mTaskInfo = taskInfo;
|
if (state.mWindowDecoration != null) {
|
||||||
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
|
mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private State<T> updateTaskInfo(RunningTaskInfo taskInfo) {
|
||||||
|
final State<T> state = mTasks.get(taskInfo.taskId);
|
||||||
|
if (state == null) {
|
||||||
|
throw new RuntimeException("Task info changed before appearing: #" + taskInfo.taskId);
|
||||||
|
}
|
||||||
|
state.mTaskInfo = taskInfo;
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
|
||||||
@@ -126,6 +145,93 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
return mTasks.get(taskId).mLeash;
|
return mTasks.get(taskId).mLeash;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a window decoration for a transition.
|
||||||
|
*
|
||||||
|
* @param change the change of this task transition that needs to have the task layer as the
|
||||||
|
* leash
|
||||||
|
* @return {@code true} if it adopts the window decoration; {@code false} otherwise
|
||||||
|
*/
|
||||||
|
void createWindowDecoration(
|
||||||
|
TransitionInfo.Change change,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT) {
|
||||||
|
final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash());
|
||||||
|
state.mWindowDecoration = mWindowDecorationViewModel.createWindowDecoration(
|
||||||
|
state.mTaskInfo, state.mLeash, startT, finishT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = mWindowDecorOfVanishedTasks.get(taskInfo.taskId);
|
||||||
|
mWindowDecorOfVanishedTasks.remove(taskInfo.taskId);
|
||||||
|
final State<T> state = mTasks.get(taskInfo.taskId);
|
||||||
|
if (state != null) {
|
||||||
|
windowDecor = windowDecor == null ? state.mWindowDecoration : windowDecor;
|
||||||
|
state.mWindowDecoration = 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;
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Clearing window decors of vanished tasks. There could be visual defects "
|
||||||
|
+ "if any of them is used later in transitions.");
|
||||||
|
for (int i = 0; i < mWindowDecorOfVanishedTasks.size(); ++i) {
|
||||||
|
releaseWindowDecor(mWindowDecorOfVanishedTasks.valueAt(i));
|
||||||
|
}
|
||||||
|
mWindowDecorOfVanishedTasks.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseWindowDecor(T windowDecor) {
|
||||||
|
try {
|
||||||
|
windowDecor.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to release window decoration.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dump(PrintWriter pw, String prefix) {
|
public void dump(PrintWriter pw, String prefix) {
|
||||||
final String innerPrefix = prefix + " ";
|
final String innerPrefix = prefix + " ";
|
||||||
@@ -137,16 +243,4 @@ public class FreeformTaskListener<T extends AutoCloseable>
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return TAG;
|
return TAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if freeform support is enabled in system.
|
|
||||||
*
|
|
||||||
* @param context context used to check settings and package manager.
|
|
||||||
* @return {@code true} if freeform is enabled, {@code false} if not.
|
|
||||||
*/
|
|
||||||
public static boolean isFreeformEnabled(Context context) {
|
|
||||||
return context.getPackageManager().hasSystemFeature(FEATURE_FREEFORM_WINDOW_MANAGEMENT)
|
|
||||||
|| Settings.Global.getInt(context.getContentResolver(),
|
|
||||||
DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,234 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
|
||||||
|
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
|
||||||
|
|
||||||
|
import android.app.ActivityManager;
|
||||||
|
import android.app.WindowConfiguration;
|
||||||
|
import android.os.IBinder;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.SurfaceControl;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.window.TransitionInfo;
|
||||||
|
import android.window.TransitionRequestInfo;
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
import com.android.wm.shell.windowdecor.WindowDecorViewModel;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Transitions.TransitionHandler} that handles freeform task launches, closes,
|
||||||
|
* maximizing and restoring transitions. It also reports transitions so that window decorations can
|
||||||
|
* be a part of transitions.
|
||||||
|
*/
|
||||||
|
public class FreeformTaskTransitionHandler
|
||||||
|
implements Transitions.TransitionHandler, FreeformTaskTransitionStarter {
|
||||||
|
private static final String TAG = "FreeformTH";
|
||||||
|
|
||||||
|
private final Transitions mTransitions;
|
||||||
|
private final FreeformTaskListener<?> mFreeformTaskListener;
|
||||||
|
|
||||||
|
private final List<IBinder> mPendingTransitionTokens = new ArrayList<>();
|
||||||
|
|
||||||
|
public FreeformTaskTransitionHandler(
|
||||||
|
Transitions transitions,
|
||||||
|
WindowDecorViewModel<?> windowDecorViewModel,
|
||||||
|
FreeformTaskListener<?> freeformTaskListener) {
|
||||||
|
mTransitions = transitions;
|
||||||
|
mFreeformTaskListener = freeformTaskListener;
|
||||||
|
|
||||||
|
windowDecorViewModel.setFreeformTaskTransitionStarter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startWindowingModeTransition(
|
||||||
|
int targetWindowingMode, WindowContainerTransaction wct) {
|
||||||
|
final int type;
|
||||||
|
switch (targetWindowingMode) {
|
||||||
|
case WINDOWING_MODE_FULLSCREEN:
|
||||||
|
type = Transitions.TRANSIT_MAXIMIZE;
|
||||||
|
break;
|
||||||
|
case WINDOWING_MODE_FREEFORM:
|
||||||
|
type = Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unexpected target windowing mode "
|
||||||
|
+ WindowConfiguration.windowingModeToString(targetWindowingMode));
|
||||||
|
}
|
||||||
|
final IBinder token = mTransitions.startTransition(type, wct, this);
|
||||||
|
mPendingTransitionTokens.add(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||||
|
@NonNull SurfaceControl.Transaction startT,
|
||||||
|
@NonNull SurfaceControl.Transaction finishT,
|
||||||
|
@NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||||
|
boolean transitionHandled = false;
|
||||||
|
final ArrayList<AutoCloseable> windowDecorsInCloseTransitions = new ArrayList<>();
|
||||||
|
for (TransitionInfo.Change change : info.getChanges()) {
|
||||||
|
if ((change.getFlags() & TransitionInfo.FLAG_IS_WALLPAPER) != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
|
||||||
|
if (taskInfo == null || taskInfo.taskId == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (change.getMode()) {
|
||||||
|
case WindowManager.TRANSIT_OPEN:
|
||||||
|
transitionHandled |= startOpenTransition(change, startT, finishT);
|
||||||
|
break;
|
||||||
|
case WindowManager.TRANSIT_CLOSE:
|
||||||
|
transitionHandled |= startCloseTransition(
|
||||||
|
change, windowDecorsInCloseTransitions, startT, finishT);
|
||||||
|
break;
|
||||||
|
case WindowManager.TRANSIT_CHANGE:
|
||||||
|
transitionHandled |= startChangeTransition(
|
||||||
|
transition, info.getType(), change, startT, finishT);
|
||||||
|
break;
|
||||||
|
case WindowManager.TRANSIT_TO_BACK:
|
||||||
|
case WindowManager.TRANSIT_TO_FRONT:
|
||||||
|
transitionHandled = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mPendingTransitionTokens.remove(transition);
|
||||||
|
|
||||||
|
if (!transitionHandled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
startT.apply();
|
||||||
|
mTransitions.getMainExecutor().execute(
|
||||||
|
() -> finishTransition(windowDecorsInCloseTransitions, finishCallback));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean startOpenTransition(
|
||||||
|
TransitionInfo.Change change,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT) {
|
||||||
|
if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mFreeformTaskListener.createWindowDecoration(change, startT, finishT);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean startCloseTransition(
|
||||||
|
TransitionInfo.Change change,
|
||||||
|
ArrayList<AutoCloseable> windowDecors,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT) {
|
||||||
|
if (change.getTaskInfo().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final AutoCloseable windowDecor =
|
||||||
|
mFreeformTaskListener.giveWindowDecoration(change.getTaskInfo(), startT, finishT);
|
||||||
|
if (windowDecor != null) {
|
||||||
|
windowDecors.add(windowDecor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean startChangeTransition(
|
||||||
|
IBinder transition,
|
||||||
|
int type,
|
||||||
|
TransitionInfo.Change change,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT) {
|
||||||
|
AutoCloseable windowDecor = null;
|
||||||
|
|
||||||
|
if (!mPendingTransitionTokens.contains(transition)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean handled = false;
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
|
||||||
|
if (type == Transitions.TRANSIT_MAXIMIZE
|
||||||
|
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
|
||||||
|
handled = true;
|
||||||
|
windowDecor = mFreeformTaskListener.giveWindowDecoration(
|
||||||
|
change.getTaskInfo(), startT, finishT);
|
||||||
|
// TODO(b/235638450): Let fullscreen task listener adopt the window decor.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Transitions.TRANSIT_RESTORE_FROM_MAXIMIZE
|
||||||
|
&& taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
|
||||||
|
handled = true;
|
||||||
|
// TODO(b/235638450): Let fullscreen task listener transfer the window decor.
|
||||||
|
mFreeformTaskListener.adoptWindowDecoration(change, startT, finishT, windowDecor);
|
||||||
|
}
|
||||||
|
|
||||||
|
releaseWindowDecor(windowDecor);
|
||||||
|
|
||||||
|
return handled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishTransition(
|
||||||
|
ArrayList<AutoCloseable> windowDecorsInCloseTransitions,
|
||||||
|
Transitions.TransitionFinishCallback finishCallback) {
|
||||||
|
for (AutoCloseable windowDecor : windowDecorsInCloseTransitions) {
|
||||||
|
releaseWindowDecor(windowDecor);
|
||||||
|
}
|
||||||
|
mFreeformTaskListener.onTaskTransitionFinished();
|
||||||
|
// TODO(b/235638450): Dispatch it to fullscreen task listener.
|
||||||
|
finishCallback.onTransitionFinished(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void releaseWindowDecor(AutoCloseable windowDecor) {
|
||||||
|
if (windowDecor == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
windowDecor.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to release window decoration.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||||
|
@NonNull TransitionRequestInfo request) {
|
||||||
|
final ActivityManager.RunningTaskInfo taskInfo = request.getTriggerTask();
|
||||||
|
if (taskInfo == null || taskInfo.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
switch (request.getType()) {
|
||||||
|
case WindowManager.TRANSIT_OPEN:
|
||||||
|
case WindowManager.TRANSIT_CLOSE:
|
||||||
|
case WindowManager.TRANSIT_TO_FRONT:
|
||||||
|
case WindowManager.TRANSIT_TO_BACK:
|
||||||
|
return new WindowContainerTransaction();
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.wm.shell.freeform;
|
||||||
|
|
||||||
|
import android.window.WindowContainerTransaction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface around {@link FreeformTaskTransitionHandler} for task listeners to start freeform
|
||||||
|
* task transitions.
|
||||||
|
*/
|
||||||
|
public interface FreeformTaskTransitionStarter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts a windowing mode transition.
|
||||||
|
*
|
||||||
|
* @param targetWindowingMode the target windowing mode
|
||||||
|
* @param wct the {@link WindowContainerTransaction} that changes the windowing mode
|
||||||
|
*/
|
||||||
|
void startWindowingModeTransition(int targetWindowingMode, WindowContainerTransaction wct);
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ import com.android.wm.shell.common.DisplayImeController;
|
|||||||
import com.android.wm.shell.common.DisplayInsetsController;
|
import com.android.wm.shell.common.DisplayInsetsController;
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
import com.android.wm.shell.common.ShellExecutor;
|
||||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||||
import com.android.wm.shell.freeform.FreeformTaskListener;
|
import com.android.wm.shell.freeform.FreeformComponents;
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
||||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||||
import com.android.wm.shell.pip.phone.PipTouchHandler;
|
import com.android.wm.shell.pip.phone.PipTouchHandler;
|
||||||
@@ -68,7 +68,7 @@ public class ShellInit {
|
|||||||
private final FullscreenTaskListener mFullscreenTaskListener;
|
private final FullscreenTaskListener mFullscreenTaskListener;
|
||||||
private final Optional<UnfoldAnimationController> mUnfoldController;
|
private final Optional<UnfoldAnimationController> mUnfoldController;
|
||||||
private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
private final Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
||||||
private final Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional;
|
private final Optional<FreeformComponents> mFreeformComponentsOptional;
|
||||||
private final ShellExecutor mMainExecutor;
|
private final ShellExecutor mMainExecutor;
|
||||||
private final Transitions mTransitions;
|
private final Transitions mTransitions;
|
||||||
private final StartingWindowController mStartingWindow;
|
private final StartingWindowController mStartingWindow;
|
||||||
@@ -93,7 +93,7 @@ public class ShellInit {
|
|||||||
FullscreenTaskListener fullscreenTaskListener,
|
FullscreenTaskListener fullscreenTaskListener,
|
||||||
Optional<UnfoldAnimationController> unfoldAnimationController,
|
Optional<UnfoldAnimationController> unfoldAnimationController,
|
||||||
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
Optional<UnfoldTransitionHandler> unfoldTransitionHandler,
|
||||||
Optional<FreeformTaskListener<?>> freeformTaskListenerOptional,
|
Optional<FreeformComponents> freeformComponentsOptional,
|
||||||
Optional<RecentTasksController> recentTasks,
|
Optional<RecentTasksController> recentTasks,
|
||||||
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
|
Optional<ActivityEmbeddingController> activityEmbeddingOptional,
|
||||||
Transitions transitions,
|
Transitions transitions,
|
||||||
@@ -111,7 +111,7 @@ public class ShellInit {
|
|||||||
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
mPipTouchHandlerOptional = pipTouchHandlerOptional;
|
||||||
mUnfoldController = unfoldAnimationController;
|
mUnfoldController = unfoldAnimationController;
|
||||||
mUnfoldTransitionHandler = unfoldTransitionHandler;
|
mUnfoldTransitionHandler = unfoldTransitionHandler;
|
||||||
mFreeformTaskListenerOptional = freeformTaskListenerOptional;
|
mFreeformComponentsOptional = freeformComponentsOptional;
|
||||||
mRecentTasks = recentTasks;
|
mRecentTasks = recentTasks;
|
||||||
mActivityEmbeddingOptional = activityEmbeddingOptional;
|
mActivityEmbeddingOptional = activityEmbeddingOptional;
|
||||||
mTransitions = transitions;
|
mTransitions = transitions;
|
||||||
@@ -143,6 +143,8 @@ public class ShellInit {
|
|||||||
mTransitions.register(mShellTaskOrganizer);
|
mTransitions.register(mShellTaskOrganizer);
|
||||||
mActivityEmbeddingOptional.ifPresent(ActivityEmbeddingController::init);
|
mActivityEmbeddingOptional.ifPresent(ActivityEmbeddingController::init);
|
||||||
mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init);
|
mUnfoldTransitionHandler.ifPresent(UnfoldTransitionHandler::init);
|
||||||
|
mFreeformComponentsOptional.flatMap(f -> f.mTaskTransitionHandler)
|
||||||
|
.ifPresent(mTransitions::addHandler);
|
||||||
if (mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) {
|
if (mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) {
|
||||||
final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions,
|
final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions,
|
||||||
mPipTouchHandlerOptional.get().getTransitionHandler(),
|
mPipTouchHandlerOptional.get().getTransitionHandler(),
|
||||||
@@ -158,9 +160,9 @@ public class ShellInit {
|
|||||||
mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
|
mPipTouchHandlerOptional.ifPresent((handler) -> handler.init());
|
||||||
|
|
||||||
// Initialize optional freeform
|
// Initialize optional freeform
|
||||||
mFreeformTaskListenerOptional.ifPresent(f ->
|
mFreeformComponentsOptional.ifPresent(f ->
|
||||||
mShellTaskOrganizer.addListenerForType(
|
mShellTaskOrganizer.addListenerForType(
|
||||||
f, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
|
f.mTaskListener, ShellTaskOrganizer.TASK_LISTENER_TYPE_FREEFORM));
|
||||||
|
|
||||||
mUnfoldController.ifPresent(UnfoldAnimationController::init);
|
mUnfoldController.ifPresent(UnfoldAnimationController::init);
|
||||||
mRecentTasks.ifPresent(RecentTasksController::init);
|
mRecentTasks.ifPresent(RecentTasksController::init);
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ public class Transitions implements RemoteCallable<Transitions> {
|
|||||||
/** Transition type for dismissing split-screen. */
|
/** Transition type for dismissing split-screen. */
|
||||||
public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 7;
|
public static final int TRANSIT_SPLIT_DISMISS = TRANSIT_FIRST_CUSTOM + 7;
|
||||||
|
|
||||||
|
/** Transition type for freeform to maximize transition. */
|
||||||
|
public static final int TRANSIT_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 8;
|
||||||
|
|
||||||
|
/** Transition type for maximize to freeform transition. */
|
||||||
|
public static final int TRANSIT_RESTORE_FROM_MAXIMIZE = WindowManager.TRANSIT_FIRST_CUSTOM + 9;
|
||||||
|
|
||||||
private final WindowOrganizer mOrganizer;
|
private final WindowOrganizer mOrganizer;
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final ShellExecutor mMainExecutor;
|
private final ShellExecutor mMainExecutor;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import com.android.wm.shell.R;
|
|||||||
import com.android.wm.shell.ShellTaskOrganizer;
|
import com.android.wm.shell.ShellTaskOrganizer;
|
||||||
import com.android.wm.shell.common.DisplayController;
|
import com.android.wm.shell.common.DisplayController;
|
||||||
import com.android.wm.shell.common.SyncTransactionQueue;
|
import com.android.wm.shell.common.SyncTransactionQueue;
|
||||||
|
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
||||||
|
import com.android.wm.shell.transition.Transitions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View model for the window decoration with a caption and shadows. Works with
|
* View model for the window decoration with a caption and shadows. Works with
|
||||||
@@ -50,6 +52,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
private final DisplayController mDisplayController;
|
private final DisplayController mDisplayController;
|
||||||
private final SyncTransactionQueue mSyncQueue;
|
private final SyncTransactionQueue mSyncQueue;
|
||||||
|
|
||||||
|
private FreeformTaskTransitionStarter mTransitionStarter;
|
||||||
|
|
||||||
public CaptionWindowDecorViewModel(
|
public CaptionWindowDecorViewModel(
|
||||||
Context context,
|
Context context,
|
||||||
Handler mainHandler,
|
Handler mainHandler,
|
||||||
@@ -66,9 +70,17 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
mSyncQueue = syncQueue;
|
mSyncQueue = syncQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
|
||||||
|
mTransitionStarter = transitionStarter;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CaptionWindowDecoration createWindowDecoration(
|
public CaptionWindowDecoration createWindowDecoration(
|
||||||
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface) {
|
ActivityManager.RunningTaskInfo taskInfo,
|
||||||
|
SurfaceControl taskSurface,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT) {
|
||||||
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
|
final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration(
|
||||||
mContext,
|
mContext,
|
||||||
mDisplayController,
|
mDisplayController,
|
||||||
@@ -83,18 +95,39 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
new CaptionTouchEventListener(taskInfo, taskPositioner);
|
||||||
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
windowDecoration.setCaptionListeners(touchEventListener, touchEventListener);
|
||||||
windowDecoration.setDragResizeCallback(taskPositioner);
|
windowDecoration.setDragResizeCallback(taskPositioner);
|
||||||
onTaskInfoChanged(taskInfo, windowDecoration);
|
setupWindowDecorationForTransition(taskInfo, startT, finishT, windowDecoration);
|
||||||
|
setupCaptionColor(taskInfo, windowDecoration);
|
||||||
return windowDecoration;
|
return windowDecoration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) {
|
||||||
|
return (windowDecor instanceof CaptionWindowDecoration)
|
||||||
|
? (CaptionWindowDecoration) windowDecor
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
|
public void onTaskInfoChanged(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
|
||||||
decoration.relayout(taskInfo);
|
decoration.relayout(taskInfo);
|
||||||
|
|
||||||
|
setupCaptionColor(taskInfo, decoration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupCaptionColor(RunningTaskInfo taskInfo, CaptionWindowDecoration decoration) {
|
||||||
int statusBarColor = taskInfo.taskDescription.getStatusBarColor();
|
int statusBarColor = taskInfo.taskDescription.getStatusBarColor();
|
||||||
decoration.setCaptionColor(statusBarColor);
|
decoration.setCaptionColor(statusBarColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setupWindowDecorationForTransition(
|
||||||
|
RunningTaskInfo taskInfo,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT,
|
||||||
|
CaptionWindowDecoration decoration) {
|
||||||
|
decoration.relayout(taskInfo, startT, finishT);
|
||||||
|
}
|
||||||
|
|
||||||
private class CaptionTouchEventListener implements
|
private class CaptionTouchEventListener implements
|
||||||
View.OnClickListener, View.OnTouchListener {
|
View.OnClickListener, View.OnTouchListener {
|
||||||
|
|
||||||
@@ -105,7 +138,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
private int mDragPointerId = -1;
|
private int mDragPointerId = -1;
|
||||||
|
|
||||||
private CaptionTouchEventListener(
|
private CaptionTouchEventListener(
|
||||||
RunningTaskInfo taskInfo, DragResizeCallback dragResizeCallback) {
|
RunningTaskInfo taskInfo,
|
||||||
|
DragResizeCallback dragResizeCallback) {
|
||||||
mTaskId = taskInfo.taskId;
|
mTaskId = taskInfo.taskId;
|
||||||
mTaskToken = taskInfo.token;
|
mTaskToken = taskInfo.token;
|
||||||
mDragResizeCallback = dragResizeCallback;
|
mDragResizeCallback = dragResizeCallback;
|
||||||
@@ -113,7 +147,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
int id = v.getId();
|
final int id = v.getId();
|
||||||
if (id == R.id.close_window) {
|
if (id == R.id.close_window) {
|
||||||
mActivityTaskManager.removeTask(mTaskId);
|
mActivityTaskManager.removeTask(mTaskId);
|
||||||
} else if (id == R.id.maximize_window) {
|
} else if (id == R.id.maximize_window) {
|
||||||
@@ -129,9 +163,13 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption
|
|||||||
if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
|
if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) {
|
||||||
wct.setBounds(mTaskToken, null);
|
wct.setBounds(mTaskToken, null);
|
||||||
}
|
}
|
||||||
|
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||||
|
mTransitionStarter.startWindowingModeTransition(targetWindowingMode, wct);
|
||||||
|
} else {
|
||||||
mSyncQueue.queue(wct);
|
mSyncQueue.queue(wct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouch(View v, MotionEvent e) {
|
public boolean onTouch(View v, MotionEvent e) {
|
||||||
|
|||||||
@@ -101,6 +101,16 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
||||||
|
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
||||||
|
relayout(taskInfo, t, t);
|
||||||
|
mSyncQueue.runInSync(transaction -> {
|
||||||
|
transaction.merge(t);
|
||||||
|
t.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void relayout(ActivityManager.RunningTaskInfo taskInfo,
|
||||||
|
SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
|
||||||
final int shadowRadiusDp = taskInfo.isFocused
|
final int shadowRadiusDp = taskInfo.isFocused
|
||||||
? DECOR_SHADOW_FOCUSED_THICKNESS_IN_DIP : DECOR_SHADOW_UNFOCUSED_THICKNESS_IN_DIP;
|
? DECOR_SHADOW_FOCUSED_THICKNESS_IN_DIP : DECOR_SHADOW_UNFOCUSED_THICKNESS_IN_DIP;
|
||||||
final boolean isFreeform = mTaskInfo.configuration.windowConfiguration.getWindowingMode()
|
final boolean isFreeform = mTaskInfo.configuration.windowConfiguration.getWindowingMode()
|
||||||
@@ -110,18 +120,12 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL
|
|||||||
|
|
||||||
WindowDecorLinearLayout oldRootView = mResult.mRootView;
|
WindowDecorLinearLayout oldRootView = mResult.mRootView;
|
||||||
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
|
final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;
|
||||||
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
|
|
||||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||||
relayout(taskInfo, R.layout.caption_window_decoration, oldRootView,
|
relayout(taskInfo, R.layout.caption_window_decoration, oldRootView,
|
||||||
DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, t, wct, mResult);
|
DECOR_CAPTION_HEIGHT_IN_DIP, outset, shadowRadiusDp, startT, finishT, wct, mResult);
|
||||||
taskInfo = null; // Clear it just in case we use it accidentally
|
taskInfo = null; // Clear it just in case we use it accidentally
|
||||||
|
|
||||||
mSyncQueue.runInSync(transaction -> {
|
|
||||||
transaction.merge(t);
|
|
||||||
t.close();
|
|
||||||
|
|
||||||
mTaskOrganizer.applyTransaction(wct);
|
mTaskOrganizer.applyTransaction(wct);
|
||||||
});
|
|
||||||
|
|
||||||
if (mResult.mRootView == null) {
|
if (mResult.mRootView == null) {
|
||||||
// This means something blocks the window decor from showing, e.g. the task is hidden.
|
// This means something blocks the window decor from showing, e.g. the task is hidden.
|
||||||
|
|||||||
@@ -19,6 +19,10 @@ package com.android.wm.shell.windowdecor;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.view.SurfaceControl;
|
import android.view.SurfaceControl;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The interface used by some {@link com.android.wm.shell.ShellTaskOrganizer.TaskListener} to help
|
* The interface used by some {@link com.android.wm.shell.ShellTaskOrganizer.TaskListener} to help
|
||||||
* customize {@link WindowDecoration}. Its implementations are responsible to interpret user's
|
* customize {@link WindowDecoration}. Its implementations are responsible to interpret user's
|
||||||
@@ -29,14 +33,35 @@ import android.view.SurfaceControl;
|
|||||||
*/
|
*/
|
||||||
public interface WindowDecorViewModel<T extends AutoCloseable> {
|
public interface WindowDecorViewModel<T extends AutoCloseable> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the transition starter that starts freeform task transitions.
|
||||||
|
*
|
||||||
|
* @param transitionStarter the transition starter that starts freeform task transitions
|
||||||
|
*/
|
||||||
|
void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a window decoration for the given task.
|
* Creates a window decoration for the given task.
|
||||||
*
|
*
|
||||||
* @param taskInfo the initial task info of the task
|
* @param taskInfo the initial task info of the task
|
||||||
* @param taskSurface the surface of the task
|
* @param taskSurface the surface of the task
|
||||||
|
* @param startT the start transaction to be applied before the transition
|
||||||
|
* @param finishT the finish transaction to restore states after the transition
|
||||||
* @return the window decoration object
|
* @return the window decoration object
|
||||||
*/
|
*/
|
||||||
T createWindowDecoration(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface);
|
T createWindowDecoration(
|
||||||
|
ActivityManager.RunningTaskInfo taskInfo,
|
||||||
|
SurfaceControl taskSurface,
|
||||||
|
SurfaceControl.Transaction startT,
|
||||||
|
SurfaceControl.Transaction finishT);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adopts the window decoration if possible.
|
||||||
|
*
|
||||||
|
* @param windowDecor the potential window decoration to adopt
|
||||||
|
* @return the window decoration if it can be adopted, or {@code null} otherwise.
|
||||||
|
*/
|
||||||
|
T adoptWindowDecoration(@Nullable AutoCloseable windowDecor);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies a task info update on the given task, with the window decoration created previously
|
* Notifies a task info update on the given task, with the window decoration created previously
|
||||||
@@ -46,4 +71,18 @@ public interface WindowDecorViewModel<T extends AutoCloseable> {
|
|||||||
* @param windowDecoration the window decoration created for the task
|
* @param windowDecoration the window decoration created for the task
|
||||||
*/
|
*/
|
||||||
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo, T windowDecoration);
|
void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo, T windowDecoration);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies a transition is about to start about the given task to give the window decoration a
|
||||||
|
* chance to prepare for this transition.
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -140,8 +140,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
abstract void relayout(RunningTaskInfo taskInfo);
|
abstract void relayout(RunningTaskInfo taskInfo);
|
||||||
|
|
||||||
void relayout(RunningTaskInfo taskInfo, int layoutResId, T rootView, float captionHeightDp,
|
void relayout(RunningTaskInfo taskInfo, int layoutResId, T rootView, float captionHeightDp,
|
||||||
Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction t,
|
Rect outsetsDp, float shadowRadiusDp, SurfaceControl.Transaction startT,
|
||||||
WindowContainerTransaction wct, RelayoutResult<T> outResult) {
|
SurfaceControl.Transaction finishT, WindowContainerTransaction wct,
|
||||||
|
RelayoutResult<T> outResult) {
|
||||||
outResult.reset();
|
outResult.reset();
|
||||||
|
|
||||||
final Configuration oldTaskConfig = mTaskInfo.getConfiguration();
|
final Configuration oldTaskConfig = mTaskInfo.getConfiguration();
|
||||||
@@ -151,7 +152,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
|
|
||||||
if (!mTaskInfo.isVisible) {
|
if (!mTaskInfo.isVisible) {
|
||||||
releaseViews();
|
releaseViews();
|
||||||
t.hide(mTaskSurface);
|
finishT.hide(mTaskSurface);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +193,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
.setParent(mTaskSurface)
|
.setParent(mTaskSurface)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
t.setTrustedOverlay(mDecorationContainerSurface, true);
|
startT.setTrustedOverlay(mDecorationContainerSurface, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
|
final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
|
||||||
@@ -205,7 +206,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
outResult.mHeight = taskBounds.height()
|
outResult.mHeight = taskBounds.height()
|
||||||
+ (int) (outsetsDp.bottom * outResult.mDensity)
|
+ (int) (outsetsDp.bottom * outResult.mDensity)
|
||||||
- decorContainerOffsetY;
|
- decorContainerOffsetY;
|
||||||
t.setPosition(mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
|
startT.setPosition(
|
||||||
|
mDecorationContainerSurface, decorContainerOffsetX, decorContainerOffsetY)
|
||||||
.setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight)
|
.setWindowCrop(mDecorationContainerSurface, outResult.mWidth, outResult.mHeight)
|
||||||
.setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1)
|
.setLayer(mDecorationContainerSurface, mTaskInfo.numActivities + 1)
|
||||||
.show(mDecorationContainerSurface);
|
.show(mDecorationContainerSurface);
|
||||||
@@ -225,7 +227,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
|
mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
|
||||||
mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
|
mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
|
||||||
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
|
mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
|
||||||
t.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
|
startT.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
|
||||||
.setShadowRadius(mTaskBackgroundSurface, shadowRadius)
|
.setShadowRadius(mTaskBackgroundSurface, shadowRadius)
|
||||||
.setColor(mTaskBackgroundSurface, mTmpColor);
|
.setColor(mTaskBackgroundSurface, mTmpColor);
|
||||||
|
|
||||||
@@ -264,9 +266,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
|
|||||||
decorContainerOffsetY,
|
decorContainerOffsetY,
|
||||||
outResult.mWidth + decorContainerOffsetX,
|
outResult.mWidth + decorContainerOffsetX,
|
||||||
outResult.mHeight + decorContainerOffsetY);
|
outResult.mHeight + decorContainerOffsetY);
|
||||||
t.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
|
startT.show(mTaskSurface);
|
||||||
.setCrop(mTaskSurface, mTaskSurfaceCrop)
|
finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
|
||||||
.show(mTaskSurface);
|
.setCrop(mTaskSurface, mTaskSurfaceCrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ import com.android.wm.shell.common.DisplayImeController;
|
|||||||
import com.android.wm.shell.common.DisplayInsetsController;
|
import com.android.wm.shell.common.DisplayInsetsController;
|
||||||
import com.android.wm.shell.common.ShellExecutor;
|
import com.android.wm.shell.common.ShellExecutor;
|
||||||
import com.android.wm.shell.draganddrop.DragAndDropController;
|
import com.android.wm.shell.draganddrop.DragAndDropController;
|
||||||
import com.android.wm.shell.freeform.FreeformTaskListener;
|
import com.android.wm.shell.freeform.FreeformComponents;
|
||||||
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
|
||||||
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
|
||||||
import com.android.wm.shell.pip.phone.PipTouchHandler;
|
import com.android.wm.shell.pip.phone.PipTouchHandler;
|
||||||
@@ -71,7 +71,7 @@ public class ShellInitTest extends ShellTestCase {
|
|||||||
@Mock private FullscreenTaskListener mFullscreenTaskListener;
|
@Mock private FullscreenTaskListener mFullscreenTaskListener;
|
||||||
@Mock private Optional<UnfoldAnimationController> mUnfoldAnimationController;
|
@Mock private Optional<UnfoldAnimationController> mUnfoldAnimationController;
|
||||||
@Mock private Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
@Mock private Optional<UnfoldTransitionHandler> mUnfoldTransitionHandler;
|
||||||
@Mock private Optional<FreeformTaskListener<?>> mFreeformTaskListenerOptional;
|
@Mock private Optional<FreeformComponents> mFreeformComponentsOptional;
|
||||||
@Mock private Optional<RecentTasksController> mRecentTasks;
|
@Mock private Optional<RecentTasksController> mRecentTasks;
|
||||||
@Mock private Optional<ActivityEmbeddingController> mActivityEmbeddingController;
|
@Mock private Optional<ActivityEmbeddingController> mActivityEmbeddingController;
|
||||||
@Mock private Transitions mTransitions;
|
@Mock private Transitions mTransitions;
|
||||||
@@ -87,7 +87,7 @@ public class ShellInitTest extends ShellTestCase {
|
|||||||
mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer,
|
mDisplayInsetsController, mDragAndDropController, mShellTaskOrganizer,
|
||||||
mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional,
|
mKidsModeTaskOrganizer, mBubblesOptional, mSplitScreenOptional,
|
||||||
mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController,
|
mPipTouchHandlerOptional, mFullscreenTaskListener, mUnfoldAnimationController,
|
||||||
mUnfoldTransitionHandler, mFreeformTaskListenerOptional, mRecentTasks,
|
mUnfoldTransitionHandler, mFreeformComponentsOptional, mRecentTasks,
|
||||||
mActivityEmbeddingController, mTransitions, mStartingWindow, mMainExecutor);
|
mActivityEmbeddingController, mTransitions, mStartingWindow, mMainExecutor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,11 +98,13 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
private WindowContainerTransaction mMockWindowContainerTransaction;
|
private WindowContainerTransaction mMockWindowContainerTransaction;
|
||||||
|
|
||||||
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
|
private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
|
||||||
private SurfaceControl.Transaction mMockSurfaceControlTransaction;
|
private SurfaceControl.Transaction mMockSurfaceControlStartT;
|
||||||
|
private SurfaceControl.Transaction mMockSurfaceControlFinishT;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mMockSurfaceControlTransaction = createMockSurfaceControlTransaction();
|
mMockSurfaceControlStartT = createMockSurfaceControlTransaction();
|
||||||
|
mMockSurfaceControlFinishT = createMockSurfaceControlTransaction();
|
||||||
|
|
||||||
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
|
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
|
||||||
.create(any(), any(), any(), anyBoolean());
|
.create(any(), any(), any(), anyBoolean());
|
||||||
@@ -149,7 +151,7 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
verify(mMockSurfaceControlViewHostFactory, never())
|
verify(mMockSurfaceControlViewHostFactory, never())
|
||||||
.create(any(), any(), any(), anyBoolean());
|
.create(any(), any(), any(), anyBoolean());
|
||||||
|
|
||||||
verify(mMockSurfaceControlTransaction).hide(taskSurface);
|
verify(mMockSurfaceControlFinishT).hide(taskSurface);
|
||||||
|
|
||||||
assertNull(mRelayoutResult.mRootView);
|
assertNull(mRelayoutResult.mRootView);
|
||||||
}
|
}
|
||||||
@@ -192,16 +194,16 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
|
|
||||||
verify(decorContainerSurfaceBuilder).setParent(taskSurface);
|
verify(decorContainerSurfaceBuilder).setParent(taskSurface);
|
||||||
verify(decorContainerSurfaceBuilder).setContainerLayer();
|
verify(decorContainerSurfaceBuilder).setContainerLayer();
|
||||||
verify(mMockSurfaceControlTransaction).setTrustedOverlay(decorContainerSurface, true);
|
verify(mMockSurfaceControlStartT).setTrustedOverlay(decorContainerSurface, true);
|
||||||
verify(mMockSurfaceControlTransaction).setPosition(decorContainerSurface, -20, -40);
|
verify(mMockSurfaceControlStartT).setPosition(decorContainerSurface, -20, -40);
|
||||||
verify(mMockSurfaceControlTransaction).setWindowCrop(decorContainerSurface, 380, 220);
|
verify(mMockSurfaceControlStartT).setWindowCrop(decorContainerSurface, 380, 220);
|
||||||
|
|
||||||
verify(taskBackgroundSurfaceBuilder).setParent(taskSurface);
|
verify(taskBackgroundSurfaceBuilder).setParent(taskSurface);
|
||||||
verify(taskBackgroundSurfaceBuilder).setEffectLayer();
|
verify(taskBackgroundSurfaceBuilder).setEffectLayer();
|
||||||
verify(mMockSurfaceControlTransaction).setWindowCrop(taskBackgroundSurface, 300, 100);
|
verify(mMockSurfaceControlStartT).setWindowCrop(taskBackgroundSurface, 300, 100);
|
||||||
verify(mMockSurfaceControlTransaction)
|
verify(mMockSurfaceControlStartT)
|
||||||
.setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f});
|
.setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f});
|
||||||
verify(mMockSurfaceControlTransaction).setShadowRadius(taskBackgroundSurface, 10);
|
verify(mMockSurfaceControlStartT).setShadowRadius(taskBackgroundSurface, 10);
|
||||||
|
|
||||||
verify(mMockSurfaceControlViewHostFactory)
|
verify(mMockSurfaceControlViewHostFactory)
|
||||||
.create(any(), eq(defaultDisplay), any(), anyBoolean());
|
.create(any(), eq(defaultDisplay), any(), anyBoolean());
|
||||||
@@ -218,11 +220,11 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
new int[] { InsetsState.ITYPE_CAPTION_BAR });
|
new int[] { InsetsState.ITYPE_CAPTION_BAR });
|
||||||
}
|
}
|
||||||
|
|
||||||
verify(mMockSurfaceControlTransaction)
|
verify(mMockSurfaceControlFinishT)
|
||||||
.setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
|
.setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y);
|
||||||
verify(mMockSurfaceControlTransaction)
|
verify(mMockSurfaceControlFinishT)
|
||||||
.setCrop(taskSurface, new Rect(-20, -40, 360, 180));
|
.setCrop(taskSurface, new Rect(-20, -40, 360, 180));
|
||||||
verify(mMockSurfaceControlTransaction)
|
verify(mMockSurfaceControlStartT)
|
||||||
.show(taskSurface);
|
.show(taskSurface);
|
||||||
|
|
||||||
assertEquals(380, mRelayoutResult.mWidth);
|
assertEquals(380, mRelayoutResult.mWidth);
|
||||||
@@ -319,8 +321,8 @@ public class WindowDecorationTests extends ShellTestCase {
|
|||||||
@Override
|
@Override
|
||||||
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
|
||||||
relayout(null /* taskInfo */, 0 /* layoutResId */, mMockView, CAPTION_HEIGHT_DP,
|
relayout(null /* taskInfo */, 0 /* layoutResId */, mMockView, CAPTION_HEIGHT_DP,
|
||||||
mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlTransaction,
|
mOutsetsDp, SHADOW_RADIUS_DP, mMockSurfaceControlStartT,
|
||||||
mMockWindowContainerTransaction, mRelayoutResult);
|
mMockSurfaceControlFinishT, mMockWindowContainerTransaction, mRelayoutResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user