Loading core/java/android/window/WindowContainerTransaction.java +54 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRA import static android.window.TaskFragmentOperation.OP_TYPE_SET_COMPANION_TASK_FRAGMENT; import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; Loading @@ -44,6 +45,8 @@ import android.view.InsetsFrameProvider; import android.view.SurfaceControl; import android.view.WindowInsets.Type.InsetsType; import com.android.window.flags.Flags; import java.util.ArrayList; import java.util.Arrays; import java.util.List; Loading Loading @@ -961,6 +964,23 @@ public final class WindowContainerTransaction implements Parcelable { return this; } /** * Sets the task as trimmable or not. This can be used to prevent the task from being trimmed by * recents. This attribute is set to true on task creation by default. * * @param isTrimmableFromRecents When {@code true}, task is set as trimmable from recents. * @hide */ @NonNull public WindowContainerTransaction setTaskTrimmableFromRecents( @NonNull WindowContainerToken container, boolean isTrimmableFromRecents) { mHierarchyOps.add( HierarchyOp.createForSetTaskTrimmableFromRecents(container.asBinder(), isTrimmableFromRecents)); return this; } /** * Merges another WCT into this one. * @param transfer When true, this will transfer everything from other potentially leaving Loading Loading @@ -1412,6 +1432,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH = 16; public static final int HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION = 17; public static final int HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK = 18; public static final int HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE = 19; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. Loading Loading @@ -1473,6 +1494,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentLeafTaskIfRelaunch; private boolean mIsTrimmableFromRecents; public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) Loading Loading @@ -1575,6 +1598,16 @@ public final class WindowContainerTransaction implements Parcelable { .build(); } /** Create a hierarchy op for setting a task non-trimmable by recents. */ @FlaggedApi(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) public static HierarchyOp createForSetTaskTrimmableFromRecents(@NonNull IBinder container, boolean isTrimmableFromRecents) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE) .setContainer(container) .setIsTrimmableFromRecents(isTrimmableFromRecents) .build(); } /** Only creates through {@link Builder}. */ private HierarchyOp(int type) { mType = type; Loading @@ -1599,6 +1632,7 @@ public final class WindowContainerTransaction implements Parcelable { mShortcutInfo = copy.mShortcutInfo; mAlwaysOnTop = copy.mAlwaysOnTop; mReparentLeafTaskIfRelaunch = copy.mReparentLeafTaskIfRelaunch; mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents; } protected HierarchyOp(Parcel in) { Loading @@ -1620,6 +1654,7 @@ public final class WindowContainerTransaction implements Parcelable { mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR); mAlwaysOnTop = in.readBoolean(); mReparentLeafTaskIfRelaunch = in.readBoolean(); mIsTrimmableFromRecents = in.readBoolean(); } public int getType() { Loading Loading @@ -1715,6 +1750,12 @@ public final class WindowContainerTransaction implements Parcelable { return mIncludingParents; } /** Set the task to be trimmable */ @NonNull public boolean isTrimmableFromRecents() { return mIsTrimmableFromRecents; } /** Gets a string representation of a hierarchy-op type. */ public static String hopToString(int type) { switch (type) { Loading Loading @@ -1811,6 +1852,10 @@ public final class WindowContainerTransaction implements Parcelable { sb.append("fragmentToken= ").append(mContainer) .append(" operation= ").append(mTaskFragmentOperation); break; case HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE: sb.append("container= ").append(mContainer) .append(" isTrimmable= ") .append(mIsTrimmableFromRecents); default: sb.append("container=").append(mContainer) .append(" reparent=").append(mReparent) Loading Loading @@ -1841,6 +1886,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeTypedObject(mShortcutInfo, flags); dest.writeBoolean(mAlwaysOnTop); dest.writeBoolean(mReparentLeafTaskIfRelaunch); dest.writeBoolean(mIsTrimmableFromRecents); } @Override Loading Loading @@ -1910,6 +1956,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentLeafTaskIfRelaunch; private boolean mIsTrimmableFromRecents; Builder(int type) { mType = type; } Loading Loading @@ -2000,6 +2048,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setIsTrimmableFromRecents(boolean isTrimmableFromRecents) { mIsTrimmableFromRecents = isTrimmableFromRecents; return this; } HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; Loading @@ -2023,6 +2076,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mBounds = mBounds; hierarchyOp.mIncludingParents = mIncludingParents; hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents; return hierarchyOp; } Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +2 −1 Original line number Diff line number Diff line Loading @@ -604,11 +604,12 @@ public abstract class WMShellModule { Context context, Optional<DesktopModeTaskRepository> desktopModeTaskRepository, Transitions transitions, ShellTaskOrganizer shellTaskOrganizer, ShellInit shellInit ) { return desktopModeTaskRepository.flatMap(repository -> Optional.of(new DesktopTasksTransitionObserver( context, repository, transitions, shellInit)) context, repository, transitions, shellTaskOrganizer, shellInit)) ); } Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt +18 −7 Original line number Diff line number Diff line Loading @@ -21,29 +21,32 @@ import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager import android.window.TransitionInfo import android.window.WindowContainerTransaction import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions /** * A [Transitions.TransitionObserver] that observes shell transitions and updates * the [DesktopModeTaskRepository] state TODO: b/332682201 * This observes transitions related to desktop mode * and other transitions that originate both within and outside shell. * A [Transitions.TransitionObserver] that observes shell transitions and updates the * [DesktopModeTaskRepository] state TODO: b/332682201 This observes transitions related to desktop * mode and other transitions that originate both within and outside shell. */ class DesktopTasksTransitionObserver( context: Context, private val desktopModeTaskRepository: DesktopModeTaskRepository, private val transitions: Transitions, private val shellTaskOrganizer: ShellTaskOrganizer, shellInit: ShellInit ) : Transitions.TransitionObserver { init { if (Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context)) { if ( Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context) ) { shellInit.addInitCallback(::onInit, this) } } Loading Loading @@ -83,8 +86,16 @@ class DesktopTasksTransitionObserver( change.taskInfo?.let { taskInfo -> if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) { when (change.mode) { WindowManager.TRANSIT_OPEN -> WindowManager.TRANSIT_OPEN -> { desktopModeTaskRepository.wallpaperActivityToken = taskInfo.token // After the task for the wallpaper is created, set it non-trimmable. // This is important to prevent recents from trimming and removing the // task. shellTaskOrganizer.applyTransaction( WindowContainerTransaction() .setTaskTrimmableFromRecents(taskInfo.token, false) ) } WindowManager.TRANSIT_CLOSE -> desktopModeTaskRepository.wallpaperActivityToken = null else -> {} Loading services/core/java/com/android/server/wm/RecentTasks.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Environment; import android.os.IBinder; Loading @@ -76,7 +75,6 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.InsetsState; import android.view.MotionEvent; import android.view.WindowInsets; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -1536,6 +1534,11 @@ class RecentTasks { return true; } // The task is marked as non-trimmable. Don't trim the task. if (!task.mIsTrimmableFromRecents) { return false; } // Ignore tasks from different displays // TODO (b/115289124): No Recents on non-default displays. if (!task.isOnHomeDisplay()) { Loading services/core/java/com/android/server/wm/Task.java +12 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,12 @@ class Task extends TaskFragment { */ boolean mReparentLeafTaskIfRelaunch; /** * Set to affect whether recents should be able to trim this task or not. It's set to true by * default. */ boolean mIsTrimmableFromRecents; private final AnimatingActivityRegistry mAnimatingActivityRegistry = new AnimatingActivityRegistry(); Loading Loading @@ -666,6 +672,7 @@ class Task extends TaskFragment { mLaunchCookie = _launchCookie; mDeferTaskAppear = _deferTaskAppear; mRemoveWithTaskOrganizer = _removeWithTaskOrganizer; mIsTrimmableFromRecents = true; EventLogTags.writeWmTaskCreated(mTaskId); } Loading Loading @@ -3856,6 +3863,7 @@ class Task extends TaskFragment { pw.print(" isResizeable="); pw.println(isResizeable()); pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime); pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)"); pw.print(prefix); pw.println(" isTrimmable=" + mIsTrimmableFromRecents); } @Override Loading Loading @@ -6296,6 +6304,10 @@ class Task extends TaskFragment { } } void setTrimmableFromRecents(boolean isTrimmable) { mIsTrimmableFromRecents = isTrimmable; } /** * Return true if the activityInfo has the same requiredDisplayCategory as this task. */ Loading Loading
core/java/android/window/WindowContainerTransaction.java +54 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import static android.window.TaskFragmentOperation.OP_TYPE_SET_ADJACENT_TASK_FRA import static android.window.TaskFragmentOperation.OP_TYPE_SET_COMPANION_TASK_FRAGMENT; import static android.window.TaskFragmentOperation.OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; Loading @@ -44,6 +45,8 @@ import android.view.InsetsFrameProvider; import android.view.SurfaceControl; import android.view.WindowInsets.Type.InsetsType; import com.android.window.flags.Flags; import java.util.ArrayList; import java.util.Arrays; import java.util.List; Loading Loading @@ -961,6 +964,23 @@ public final class WindowContainerTransaction implements Parcelable { return this; } /** * Sets the task as trimmable or not. This can be used to prevent the task from being trimmed by * recents. This attribute is set to true on task creation by default. * * @param isTrimmableFromRecents When {@code true}, task is set as trimmable from recents. * @hide */ @NonNull public WindowContainerTransaction setTaskTrimmableFromRecents( @NonNull WindowContainerToken container, boolean isTrimmableFromRecents) { mHierarchyOps.add( HierarchyOp.createForSetTaskTrimmableFromRecents(container.asBinder(), isTrimmableFromRecents)); return this; } /** * Merges another WCT into this one. * @param transfer When true, this will transfer everything from other potentially leaving Loading Loading @@ -1412,6 +1432,7 @@ public final class WindowContainerTransaction implements Parcelable { public static final int HIERARCHY_OP_TYPE_SET_REPARENT_LEAF_TASK_IF_RELAUNCH = 16; public static final int HIERARCHY_OP_TYPE_ADD_TASK_FRAGMENT_OPERATION = 17; public static final int HIERARCHY_OP_TYPE_MOVE_PIP_ACTIVITY_TO_PINNED_TASK = 18; public static final int HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE = 19; // The following key(s) are for use with mLaunchOptions: // When launching a task (eg. from recents), this is the taskId to be launched. Loading Loading @@ -1473,6 +1494,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentLeafTaskIfRelaunch; private boolean mIsTrimmableFromRecents; public static HierarchyOp createForReparent( @NonNull IBinder container, @Nullable IBinder reparent, boolean toTop) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_REPARENT) Loading Loading @@ -1575,6 +1598,16 @@ public final class WindowContainerTransaction implements Parcelable { .build(); } /** Create a hierarchy op for setting a task non-trimmable by recents. */ @FlaggedApi(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY) public static HierarchyOp createForSetTaskTrimmableFromRecents(@NonNull IBinder container, boolean isTrimmableFromRecents) { return new HierarchyOp.Builder(HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE) .setContainer(container) .setIsTrimmableFromRecents(isTrimmableFromRecents) .build(); } /** Only creates through {@link Builder}. */ private HierarchyOp(int type) { mType = type; Loading @@ -1599,6 +1632,7 @@ public final class WindowContainerTransaction implements Parcelable { mShortcutInfo = copy.mShortcutInfo; mAlwaysOnTop = copy.mAlwaysOnTop; mReparentLeafTaskIfRelaunch = copy.mReparentLeafTaskIfRelaunch; mIsTrimmableFromRecents = copy.mIsTrimmableFromRecents; } protected HierarchyOp(Parcel in) { Loading @@ -1620,6 +1654,7 @@ public final class WindowContainerTransaction implements Parcelable { mShortcutInfo = in.readTypedObject(ShortcutInfo.CREATOR); mAlwaysOnTop = in.readBoolean(); mReparentLeafTaskIfRelaunch = in.readBoolean(); mIsTrimmableFromRecents = in.readBoolean(); } public int getType() { Loading Loading @@ -1715,6 +1750,12 @@ public final class WindowContainerTransaction implements Parcelable { return mIncludingParents; } /** Set the task to be trimmable */ @NonNull public boolean isTrimmableFromRecents() { return mIsTrimmableFromRecents; } /** Gets a string representation of a hierarchy-op type. */ public static String hopToString(int type) { switch (type) { Loading Loading @@ -1811,6 +1852,10 @@ public final class WindowContainerTransaction implements Parcelable { sb.append("fragmentToken= ").append(mContainer) .append(" operation= ").append(mTaskFragmentOperation); break; case HIERARCHY_OP_TYPE_SET_IS_TRIMMABLE: sb.append("container= ").append(mContainer) .append(" isTrimmable= ") .append(mIsTrimmableFromRecents); default: sb.append("container=").append(mContainer) .append(" reparent=").append(mReparent) Loading Loading @@ -1841,6 +1886,7 @@ public final class WindowContainerTransaction implements Parcelable { dest.writeTypedObject(mShortcutInfo, flags); dest.writeBoolean(mAlwaysOnTop); dest.writeBoolean(mReparentLeafTaskIfRelaunch); dest.writeBoolean(mIsTrimmableFromRecents); } @Override Loading Loading @@ -1910,6 +1956,8 @@ public final class WindowContainerTransaction implements Parcelable { private boolean mReparentLeafTaskIfRelaunch; private boolean mIsTrimmableFromRecents; Builder(int type) { mType = type; } Loading Loading @@ -2000,6 +2048,11 @@ public final class WindowContainerTransaction implements Parcelable { return this; } Builder setIsTrimmableFromRecents(boolean isTrimmableFromRecents) { mIsTrimmableFromRecents = isTrimmableFromRecents; return this; } HierarchyOp build() { final HierarchyOp hierarchyOp = new HierarchyOp(mType); hierarchyOp.mContainer = mContainer; Loading @@ -2023,6 +2076,7 @@ public final class WindowContainerTransaction implements Parcelable { hierarchyOp.mBounds = mBounds; hierarchyOp.mIncludingParents = mIncludingParents; hierarchyOp.mReparentLeafTaskIfRelaunch = mReparentLeafTaskIfRelaunch; hierarchyOp.mIsTrimmableFromRecents = mIsTrimmableFromRecents; return hierarchyOp; } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +2 −1 Original line number Diff line number Diff line Loading @@ -604,11 +604,12 @@ public abstract class WMShellModule { Context context, Optional<DesktopModeTaskRepository> desktopModeTaskRepository, Transitions transitions, ShellTaskOrganizer shellTaskOrganizer, ShellInit shellInit ) { return desktopModeTaskRepository.flatMap(repository -> Optional.of(new DesktopTasksTransitionObserver( context, repository, transitions, shellInit)) context, repository, transitions, shellTaskOrganizer, shellInit)) ); } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksTransitionObserver.kt +18 −7 Original line number Diff line number Diff line Loading @@ -21,29 +21,32 @@ import android.os.IBinder import android.view.SurfaceControl import android.view.WindowManager import android.window.TransitionInfo import android.window.WindowContainerTransaction import com.android.internal.protolog.ProtoLog import com.android.window.flags.Flags.enableDesktopWindowingWallpaperActivity import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.sysui.ShellInit import com.android.wm.shell.transition.Transitions /** * A [Transitions.TransitionObserver] that observes shell transitions and updates * the [DesktopModeTaskRepository] state TODO: b/332682201 * This observes transitions related to desktop mode * and other transitions that originate both within and outside shell. * A [Transitions.TransitionObserver] that observes shell transitions and updates the * [DesktopModeTaskRepository] state TODO: b/332682201 This observes transitions related to desktop * mode and other transitions that originate both within and outside shell. */ class DesktopTasksTransitionObserver( context: Context, private val desktopModeTaskRepository: DesktopModeTaskRepository, private val transitions: Transitions, private val shellTaskOrganizer: ShellTaskOrganizer, shellInit: ShellInit ) : Transitions.TransitionObserver { init { if (Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context)) { if ( Transitions.ENABLE_SHELL_TRANSITIONS && DesktopModeStatus.canEnterDesktopMode(context) ) { shellInit.addInitCallback(::onInit, this) } } Loading Loading @@ -83,8 +86,16 @@ class DesktopTasksTransitionObserver( change.taskInfo?.let { taskInfo -> if (DesktopWallpaperActivity.isWallpaperTask(taskInfo)) { when (change.mode) { WindowManager.TRANSIT_OPEN -> WindowManager.TRANSIT_OPEN -> { desktopModeTaskRepository.wallpaperActivityToken = taskInfo.token // After the task for the wallpaper is created, set it non-trimmable. // This is important to prevent recents from trimming and removing the // task. shellTaskOrganizer.applyTransaction( WindowContainerTransaction() .setTaskTrimmableFromRecents(taskInfo.token, false) ) } WindowManager.TRANSIT_CLOSE -> desktopModeTaskRepository.wallpaperActivityToken = null else -> {} Loading
services/core/java/com/android/server/wm/RecentTasks.java +5 −2 Original line number Diff line number Diff line Loading @@ -61,7 +61,6 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Insets; import android.graphics.Rect; import android.os.Environment; import android.os.IBinder; Loading @@ -76,7 +75,6 @@ import android.util.SparseArray; import android.util.SparseBooleanArray; import android.view.InsetsState; import android.view.MotionEvent; import android.view.WindowInsets; import android.view.WindowManagerPolicyConstants.PointerEventListener; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -1536,6 +1534,11 @@ class RecentTasks { return true; } // The task is marked as non-trimmable. Don't trim the task. if (!task.mIsTrimmableFromRecents) { return false; } // Ignore tasks from different displays // TODO (b/115289124): No Recents on non-default displays. if (!task.isOnHomeDisplay()) { Loading
services/core/java/com/android/server/wm/Task.java +12 −0 Original line number Diff line number Diff line Loading @@ -495,6 +495,12 @@ class Task extends TaskFragment { */ boolean mReparentLeafTaskIfRelaunch; /** * Set to affect whether recents should be able to trim this task or not. It's set to true by * default. */ boolean mIsTrimmableFromRecents; private final AnimatingActivityRegistry mAnimatingActivityRegistry = new AnimatingActivityRegistry(); Loading Loading @@ -666,6 +672,7 @@ class Task extends TaskFragment { mLaunchCookie = _launchCookie; mDeferTaskAppear = _deferTaskAppear; mRemoveWithTaskOrganizer = _removeWithTaskOrganizer; mIsTrimmableFromRecents = true; EventLogTags.writeWmTaskCreated(mTaskId); } Loading Loading @@ -3856,6 +3863,7 @@ class Task extends TaskFragment { pw.print(" isResizeable="); pw.println(isResizeable()); pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime); pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)"); pw.print(prefix); pw.println(" isTrimmable=" + mIsTrimmableFromRecents); } @Override Loading Loading @@ -6296,6 +6304,10 @@ class Task extends TaskFragment { } } void setTrimmableFromRecents(boolean isTrimmable) { mIsTrimmableFromRecents = isTrimmable; } /** * Return true if the activityInfo has the same requiredDisplayCategory as this task. */ Loading