Loading core/java/android/content/ClipDescription.java +8 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,14 @@ public class ClipDescription implements Parcelable { public static final String EXTRA_LOGGING_INSTANCE_ID = "android.intent.extra.LOGGING_INSTANCE_ID"; /** * The id of the task containing the window that initiated the drag that should be hidden. * Only provided to internal drag handlers as a part of the DRAG_START event. * @hide */ public static final String EXTRA_HIDE_DRAG_SOURCE_TASK_ID = "android.intent.extra.HIDE_DRAG_SOURCE_TASK_ID"; /** * Indicates that a ClipData contains potentially sensitive information, such as a * password or credit card number. Loading core/java/android/view/View.java +8 −0 Original line number Diff line number Diff line Loading @@ -5511,6 +5511,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS) public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13; /** * Flag indicating that this drag will result in the caller activity's task to be hidden for the * duration of the drag, this means that the source activity will not receive drag events for * the current drag gesture. Only the current voice interaction service may use this flag. * @hide */ public static final int DRAG_FLAG_HIDE_CALLING_TASK_ON_DRAG_START = 1 << 14; /** * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. */ libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +16 −0 Original line number Diff line number Diff line Loading @@ -699,6 +699,22 @@ public class ShellTaskOrganizer extends TaskOrganizer { } } /** * Shows/hides the given task surface. Not for general use as changing the task visibility may * conflict with other Transitions. This is currently ONLY used to temporarily hide a task * while a drag is in session. */ public void setTaskSurfaceVisibility(int taskId, boolean visible) { synchronized (mLock) { final TaskAppearedInfo info = mTasks.get(taskId); if (info != null) { SurfaceControl.Transaction t = new SurfaceControl.Transaction(); t.setVisibility(info.getLeash(), visible); t.apply(); } } } private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash, TaskListener oldListener, TaskListener newListener) { if (oldListener == newListener) return false; Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +24 −1 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.BinderThread; Loading Loading @@ -353,6 +354,12 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll pd.dragSession.initialize(); pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); if (pd.dragSession.hideDragSourceTaskId != -1) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Hiding task surface: taskId=%d", pd.dragSession.hideDragSourceTaskId); mShellTaskOrganizer.setTaskSurfaceVisibility( pd.dragSession.hideDragSourceTaskId, false /* visible */); } setDropTargetWindowVisibility(pd, View.VISIBLE); notifyListeners(l -> { l.onDragStarted(); Loading Loading @@ -382,6 +389,13 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll if (pd.dragLayout.hasDropped()) { mLogger.logDrop(); } else { if (pd.dragSession.hideDragSourceTaskId != -1) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Re-showing task surface: taskId=%d", pd.dragSession.hideDragSourceTaskId); mShellTaskOrganizer.setTaskSurfaceVisibility( pd.dragSession.hideDragSourceTaskId, true /* visible */); } pd.activeDragCount--; pd.dragLayout.hide(event, () -> { if (pd.activeDragCount == 0) { Loading Loading @@ -435,7 +449,16 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll private boolean handleDrop(DragEvent event, PerDisplay pd) { final SurfaceControl dragSurface = event.getDragSurface(); pd.activeDragCount--; return pd.dragLayout.drop(event, dragSurface, () -> { // Find the token of the task to hide as a part of entering split WindowContainerToken hideTaskToken = null; if (pd.dragSession.hideDragSourceTaskId != -1) { ActivityManager.RunningTaskInfo info = mShellTaskOrganizer.getRunningTaskInfo( pd.dragSession.hideDragSourceTaskId); if (info != null) { hideTaskToken = info.token; } } return pd.dragLayout.drop(event, dragSurface, hideTaskToken, () -> { if (pd.activeDragCount == 0) { // Hide the window if another drag hasn't been started while animating the drop setDropTargetWindowVisibility(pd, View.INVISIBLE); Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +36 −12 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; import android.window.WindowContainerToken; import androidx.annotation.IntDef; import androidx.annotation.NonNull; Loading Loading @@ -234,8 +235,13 @@ public class DragAndDropPolicy { return null; } /** * Handles the drop on a given {@param target}. If a {@param hideTaskToken} is set, then the * handling of the drop will attempt to hide the given task as a part of the same window * container transaction if possible. */ @VisibleForTesting void handleDrop(Target target) { void handleDrop(Target target, @Nullable WindowContainerToken hideTaskToken) { if (target == null || !mTargets.contains(target)) { return; } Loading @@ -254,16 +260,17 @@ public class DragAndDropPolicy { ? mFullscreenStarter : mSplitscreenStarter; if (mSession.appData != null) { launchApp(mSession, starter, position); launchApp(mSession, starter, position, hideTaskToken); } else { launchIntent(mSession, starter, position); launchIntent(mSession, starter, position, hideTaskToken); } } /** * Launches an app provided by SysUI. */ private void launchApp(DragSession session, Starter starter, @SplitPosition int position) { private void launchApp(DragSession session, Starter starter, @SplitPosition int position, @Nullable WindowContainerToken hideTaskToken) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching app data at position=%d", position); final ClipDescription description = session.getClipDescription(); Loading @@ -283,8 +290,12 @@ public class DragAndDropPolicy { if (isTask) { final int taskId = session.appData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); starter.startTask(taskId, position, opts); starter.startTask(taskId, position, opts, hideTaskToken); } else if (isShortcut) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Can not hide task token with starting shortcut"); } final String packageName = session.appData.getStringExtra(EXTRA_PACKAGE_NAME); final String id = session.appData.getStringExtra(EXTRA_SHORTCUT_ID); starter.startShortcut(packageName, id, position, opts, user); Loading @@ -297,14 +308,15 @@ public class DragAndDropPolicy { } } starter.startIntent(launchIntent, user.getIdentifier(), null /* fillIntent */, position, opts); position, opts, hideTaskToken); } } /** * Launches an intent sender provided by an application. */ private void launchIntent(DragSession session, Starter starter, @SplitPosition int position) { private void launchIntent(DragSession session, Starter starter, @SplitPosition int position, @Nullable WindowContainerToken hideTaskToken) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching intent at position=%d", position); final ActivityOptions baseActivityOpts = ActivityOptions.makeBasic(); Loading @@ -319,18 +331,20 @@ public class DragAndDropPolicy { final Bundle opts = baseActivityOpts.toBundle(); starter.startIntent(session.launchableIntent, session.launchableIntent.getCreatorUserHandle().getIdentifier(), null /* fillIntent */, position, opts); null /* fillIntent */, position, opts, hideTaskToken); } /** * Interface for actually committing the task launches. */ public interface Starter { void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options); void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken); void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user); void startIntent(PendingIntent intent, int userId, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options); @SplitPosition int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken); void enterSplitScreen(int taskId, boolean leftOrTop); /** Loading @@ -352,7 +366,12 @@ public class DragAndDropPolicy { } @Override public void startTask(int taskId, int position, @Nullable Bundle options) { public void startTask(int taskId, int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Default starter does not support hide task token"); } try { ActivityTaskManager.getService().startActivityFromRecents(taskId, options); } catch (RemoteException e) { Loading @@ -375,7 +394,12 @@ public class DragAndDropPolicy { @Override public void startIntent(PendingIntent intent, int userId, @Nullable Intent fillInIntent, int position, @Nullable Bundle options) { int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Default starter does not support hide task token"); } try { intent.send(mContext, 0, fillInIntent, null, null, null, options); } catch (PendingIntent.CanceledException e) { Loading Loading
core/java/android/content/ClipDescription.java +8 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,14 @@ public class ClipDescription implements Parcelable { public static final String EXTRA_LOGGING_INSTANCE_ID = "android.intent.extra.LOGGING_INSTANCE_ID"; /** * The id of the task containing the window that initiated the drag that should be hidden. * Only provided to internal drag handlers as a part of the DRAG_START event. * @hide */ public static final String EXTRA_HIDE_DRAG_SOURCE_TASK_ID = "android.intent.extra.HIDE_DRAG_SOURCE_TASK_ID"; /** * Indicates that a ClipData contains potentially sensitive information, such as a * password or credit card number. Loading
core/java/android/view/View.java +8 −0 Original line number Diff line number Diff line Loading @@ -5511,6 +5511,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback, @FlaggedApi(FLAG_DELEGATE_UNHANDLED_DRAGS) public static final int DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG = 1 << 13; /** * Flag indicating that this drag will result in the caller activity's task to be hidden for the * duration of the drag, this means that the source activity will not receive drag events for * the current drag gesture. Only the current voice interaction service may use this flag. * @hide */ public static final int DRAG_FLAG_HIDE_CALLING_TASK_ON_DRAG_START = 1 << 14; /** * Vertical scroll factor cached by {@link #getVerticalScrollFactor}. */
libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +16 −0 Original line number Diff line number Diff line Loading @@ -699,6 +699,22 @@ public class ShellTaskOrganizer extends TaskOrganizer { } } /** * Shows/hides the given task surface. Not for general use as changing the task visibility may * conflict with other Transitions. This is currently ONLY used to temporarily hide a task * while a drag is in session. */ public void setTaskSurfaceVisibility(int taskId, boolean visible) { synchronized (mLock) { final TaskAppearedInfo info = mTasks.get(taskId); if (info != null) { SurfaceControl.Transaction t = new SurfaceControl.Transaction(); t.setVisibility(info.getLeash(), visible); t.apply(); } } } private boolean updateTaskListenerIfNeeded(RunningTaskInfo taskInfo, SurfaceControl leash, TaskListener oldListener, TaskListener newListener) { if (oldListener == newListener) return false; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +24 −1 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.FrameLayout; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; import androidx.annotation.BinderThread; Loading Loading @@ -353,6 +354,12 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll pd.dragSession.initialize(); pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); if (pd.dragSession.hideDragSourceTaskId != -1) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Hiding task surface: taskId=%d", pd.dragSession.hideDragSourceTaskId); mShellTaskOrganizer.setTaskSurfaceVisibility( pd.dragSession.hideDragSourceTaskId, false /* visible */); } setDropTargetWindowVisibility(pd, View.VISIBLE); notifyListeners(l -> { l.onDragStarted(); Loading Loading @@ -382,6 +389,13 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll if (pd.dragLayout.hasDropped()) { mLogger.logDrop(); } else { if (pd.dragSession.hideDragSourceTaskId != -1) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Re-showing task surface: taskId=%d", pd.dragSession.hideDragSourceTaskId); mShellTaskOrganizer.setTaskSurfaceVisibility( pd.dragSession.hideDragSourceTaskId, true /* visible */); } pd.activeDragCount--; pd.dragLayout.hide(event, () -> { if (pd.activeDragCount == 0) { Loading Loading @@ -435,7 +449,16 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll private boolean handleDrop(DragEvent event, PerDisplay pd) { final SurfaceControl dragSurface = event.getDragSurface(); pd.activeDragCount--; return pd.dragLayout.drop(event, dragSurface, () -> { // Find the token of the task to hide as a part of entering split WindowContainerToken hideTaskToken = null; if (pd.dragSession.hideDragSourceTaskId != -1) { ActivityManager.RunningTaskInfo info = mShellTaskOrganizer.getRunningTaskInfo( pd.dragSession.hideDragSourceTaskId); if (info != null) { hideTaskToken = info.token; } } return pd.dragLayout.drop(event, dragSurface, hideTaskToken, () -> { if (pd.activeDragCount == 0) { // Hide the window if another drag hasn't been started while animating the drop setDropTargetWindowVisibility(pd, View.INVISIBLE); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +36 −12 Original line number Diff line number Diff line Loading @@ -59,6 +59,7 @@ import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; import android.window.WindowContainerToken; import androidx.annotation.IntDef; import androidx.annotation.NonNull; Loading Loading @@ -234,8 +235,13 @@ public class DragAndDropPolicy { return null; } /** * Handles the drop on a given {@param target}. If a {@param hideTaskToken} is set, then the * handling of the drop will attempt to hide the given task as a part of the same window * container transaction if possible. */ @VisibleForTesting void handleDrop(Target target) { void handleDrop(Target target, @Nullable WindowContainerToken hideTaskToken) { if (target == null || !mTargets.contains(target)) { return; } Loading @@ -254,16 +260,17 @@ public class DragAndDropPolicy { ? mFullscreenStarter : mSplitscreenStarter; if (mSession.appData != null) { launchApp(mSession, starter, position); launchApp(mSession, starter, position, hideTaskToken); } else { launchIntent(mSession, starter, position); launchIntent(mSession, starter, position, hideTaskToken); } } /** * Launches an app provided by SysUI. */ private void launchApp(DragSession session, Starter starter, @SplitPosition int position) { private void launchApp(DragSession session, Starter starter, @SplitPosition int position, @Nullable WindowContainerToken hideTaskToken) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching app data at position=%d", position); final ClipDescription description = session.getClipDescription(); Loading @@ -283,8 +290,12 @@ public class DragAndDropPolicy { if (isTask) { final int taskId = session.appData.getIntExtra(EXTRA_TASK_ID, INVALID_TASK_ID); starter.startTask(taskId, position, opts); starter.startTask(taskId, position, opts, hideTaskToken); } else if (isShortcut) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Can not hide task token with starting shortcut"); } final String packageName = session.appData.getStringExtra(EXTRA_PACKAGE_NAME); final String id = session.appData.getStringExtra(EXTRA_SHORTCUT_ID); starter.startShortcut(packageName, id, position, opts, user); Loading @@ -297,14 +308,15 @@ public class DragAndDropPolicy { } } starter.startIntent(launchIntent, user.getIdentifier(), null /* fillIntent */, position, opts); position, opts, hideTaskToken); } } /** * Launches an intent sender provided by an application. */ private void launchIntent(DragSession session, Starter starter, @SplitPosition int position) { private void launchIntent(DragSession session, Starter starter, @SplitPosition int position, @Nullable WindowContainerToken hideTaskToken) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Launching intent at position=%d", position); final ActivityOptions baseActivityOpts = ActivityOptions.makeBasic(); Loading @@ -319,18 +331,20 @@ public class DragAndDropPolicy { final Bundle opts = baseActivityOpts.toBundle(); starter.startIntent(session.launchableIntent, session.launchableIntent.getCreatorUserHandle().getIdentifier(), null /* fillIntent */, position, opts); null /* fillIntent */, position, opts, hideTaskToken); } /** * Interface for actually committing the task launches. */ public interface Starter { void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options); void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken); void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user); void startIntent(PendingIntent intent, int userId, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options); @SplitPosition int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken); void enterSplitScreen(int taskId, boolean leftOrTop); /** Loading @@ -352,7 +366,12 @@ public class DragAndDropPolicy { } @Override public void startTask(int taskId, int position, @Nullable Bundle options) { public void startTask(int taskId, int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Default starter does not support hide task token"); } try { ActivityTaskManager.getService().startActivityFromRecents(taskId, options); } catch (RemoteException e) { Loading @@ -375,7 +394,12 @@ public class DragAndDropPolicy { @Override public void startIntent(PendingIntent intent, int userId, @Nullable Intent fillInIntent, int position, @Nullable Bundle options) { int position, @Nullable Bundle options, @Nullable WindowContainerToken hideTaskToken) { if (hideTaskToken != null) { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Default starter does not support hide task token"); } try { intent.send(mContext, 0, fillInIntent, null, null, null, options); } catch (PendingIntent.CanceledException e) { Loading