Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +11 −25 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.wm.shell.draganddrop; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DragEvent.ACTION_DRAG_ENDED; import static android.view.DragEvent.ACTION_DRAG_ENTERED; Loading @@ -38,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP; import android.app.ActivityTaskManager; import android.content.ClipDescription; import android.content.ComponentCallbacks2; import android.content.Context; Loading Loading @@ -205,8 +203,6 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll final Context context = mDisplayController.getDisplayContext(displayId) .createWindowContext(TYPE_APPLICATION_OVERLAY, null); final WindowManager wm = context.getSystemService(WindowManager.class); // TODO(b/169894807): Figure out the right layer for this, needs to be below the task bar final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, TYPE_APPLICATION_OVERLAY, Loading Loading @@ -279,15 +275,11 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll } if (event.getAction() == ACTION_DRAG_STARTED) { final boolean hasValidClipData = event.getClipData().getItemCount() > 0 && (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY) || description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT) || description.hasMimeType(MIMETYPE_APPLICATION_TASK)); pd.isHandlingDrag = hasValidClipData; pd.isHandlingDrag = DragUtils.canHandleDrag(event); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Clip description: handlingDrag=%b itemCount=%d mimeTypes=%s", pd.isHandlingDrag, event.getClipData().getItemCount(), getMimeTypes(description)); DragUtils.getMimeTypesConcatenated(description)); } if (!pd.isHandlingDrag) { Loading @@ -300,10 +292,13 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll Slog.w(TAG, "Unexpected drag start during an active drag"); return false; } // TODO(b/290391688): Also update the session data with task stack changes InstanceId loggerSessionId = mLogger.logStart(event); pd.activeDragCount++; pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId), event.getClipData(), loggerSessionId); pd.dragSession = new DragSession(mContext, ActivityTaskManager.getInstance(), mDisplayController.getDisplayLayout(displayId), event.getClipData()); pd.dragSession.update(); pd.dragLayout.prepare(pd.dragSession, loggerSessionId); setDropTargetWindowVisibility(pd, View.VISIBLE); notifyDragStarted(); break; Loading @@ -324,7 +319,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll break; } case ACTION_DRAG_ENDED: // TODO(b/169894807): Ensure sure it's not possible to get ENDED without DROP // TODO(b/290391688): Ensure sure it's not possible to get ENDED without DROP // or EXITED if (pd.dragLayout.hasDropped()) { mLogger.logDrop(); Loading Loading @@ -362,17 +357,6 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll pd.setWindowVisibility(visibility); } private String getMimeTypes(ClipDescription description) { String mimeTypes = ""; for (int i = 0; i < description.getMimeTypeCount(); i++) { if (i > 0) { mimeTypes += ", "; } mimeTypes += description.getMimeType(i); } return mimeTypes; } /** * Returns if any displays are currently ready to handle a drag/drop. */ Loading Loading @@ -462,6 +446,8 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll // A count of the number of active drags in progress to ensure that we only hide the window // when all the drag animations have completed int activeDragCount; // The active drag session DragSession dragSession; PerDisplay(int dispId, Context c, WindowManager w, FrameLayout rv, DragLayout dl) { displayId = dispId; Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +4 −65 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVIT import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.ClipDescription.EXTRA_ACTIVITY_OPTIONS; import static android.content.ClipDescription.EXTRA_PENDING_INTENT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; Loading @@ -41,16 +40,13 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.LauncherApps; import android.graphics.Insets; import android.graphics.Rect; Loading @@ -67,14 +63,12 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreenController; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; /** * The policy for handling drag and drop operations to shell. Loading @@ -84,7 +78,6 @@ public class DragAndDropPolicy { private static final String TAG = DragAndDropPolicy.class.getSimpleName(); private final Context mContext; private final ActivityTaskManager mActivityTaskManager; private final Starter mStarter; private final SplitScreenController mSplitScreen; private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>(); Loading @@ -94,14 +87,12 @@ public class DragAndDropPolicy { private DragSession mSession; public DragAndDropPolicy(Context context, SplitScreenController splitScreen) { this(context, ActivityTaskManager.getInstance(), splitScreen, new DefaultStarter(context)); this(context, splitScreen, new DefaultStarter(context)); } @VisibleForTesting DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager, SplitScreenController splitScreen, Starter starter) { DragAndDropPolicy(Context context, SplitScreenController splitScreen, Starter starter) { mContext = context; mActivityTaskManager = activityTaskManager; mSplitScreen = splitScreen; mStarter = mSplitScreen != null ? mSplitScreen : starter; } Loading @@ -109,11 +100,9 @@ public class DragAndDropPolicy { /** * Starts a new drag session with the given initial drag data. */ void start(DisplayLayout displayLayout, ClipData data, InstanceId loggerSessionId) { void start(DragSession session, InstanceId loggerSessionId) { mLoggerSessionId = loggerSessionId; mSession = new DragSession(mActivityTaskManager, displayLayout, data); // TODO(b/169894807): Also update the session data with task stack changes mSession.update(); mSession = session; RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION); if (disallowHitRegion == null) { mDisallowHitRegion.setEmpty(); Loading @@ -122,13 +111,6 @@ public class DragAndDropPolicy { } } /** * Returns the last running task. */ ActivityManager.RunningTaskInfo getLatestRunningTask() { return mSession.runningTaskInfo; } /** * Returns the number of targets. */ Loading Loading @@ -285,49 +267,6 @@ public class DragAndDropPolicy { } } /** * Per-drag session data. */ private static class DragSession { private final ActivityTaskManager mActivityTaskManager; private final ClipData mInitialDragData; final DisplayLayout displayLayout; Intent dragData; ActivityManager.RunningTaskInfo runningTaskInfo; @WindowConfiguration.WindowingMode int runningTaskWinMode = WINDOWING_MODE_UNDEFINED; @WindowConfiguration.ActivityType int runningTaskActType = ACTIVITY_TYPE_STANDARD; boolean dragItemSupportsSplitscreen; DragSession(ActivityTaskManager activityTaskManager, DisplayLayout dispLayout, ClipData data) { mActivityTaskManager = activityTaskManager; mInitialDragData = data; displayLayout = dispLayout; } /** * Updates the session data based on the current state of the system. */ void update() { List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1, false /* filterOnlyVisibleRecents */); if (!tasks.isEmpty()) { final ActivityManager.RunningTaskInfo task = tasks.get(0); runningTaskInfo = task; runningTaskWinMode = task.getWindowingMode(); runningTaskActType = task.getActivityType(); } final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo(); dragItemSupportsSplitscreen = info == null || ActivityInfo.isResizeableMode(info.resizeMode); dragData = mInitialDragData.getItemAt(0).getIntent(); } } /** * Interface for actually committing the task launches. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +19 −8 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.StatusBarManager; import android.content.ClipData; import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; Loading @@ -53,14 +52,13 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.ArrayList; /** * Coordinates the visible drop targets for the current drag. * Coordinates the visible drop targets for the current drag within a single display. */ public class DragLayout extends LinearLayout { Loading @@ -86,6 +84,7 @@ public class DragLayout extends LinearLayout { private boolean mIsShowing; private boolean mHasDropped; private DragSession mSession; @SuppressLint("WrongConstant") public DragLayout(Context context, SplitScreenController splitScreenController, Loading Loading @@ -182,16 +181,19 @@ public class DragLayout extends LinearLayout { return mHasDropped; } public void prepare(DisplayLayout displayLayout, ClipData initialData, InstanceId loggerSessionId) { mPolicy.start(displayLayout, initialData, loggerSessionId); /** * Called when a new drag is started. */ public void prepare(DragSession session, InstanceId loggerSessionId) { mPolicy.start(session, loggerSessionId); mSession = session; mHasDropped = false; mCurrentTarget = null; boolean alreadyInSplit = mSplitScreenController != null && mSplitScreenController.isSplitScreenVisible(); if (!alreadyInSplit) { ActivityManager.RunningTaskInfo taskInfo1 = mPolicy.getLatestRunningTask(); ActivityManager.RunningTaskInfo taskInfo1 = mSession.runningTaskInfo; if (taskInfo1 != null) { final int activityType = taskInfo1.getActivityType(); if (activityType == ACTIVITY_TYPE_STANDARD) { Loading Loading @@ -356,7 +358,16 @@ public class DragLayout extends LinearLayout { */ public void hide(DragEvent event, Runnable hideCompleteCallback) { mIsShowing = false; animateSplitContainers(false, hideCompleteCallback); animateSplitContainers(false, () -> { if (hideCompleteCallback != null) { hideCompleteCallback.run(); } switch (event.getAction()) { case DragEvent.ACTION_DROP: case DragEvent.ACTION_DRAG_ENDED: mSession = null; } }); // Reset the state if we previously force-ignore the bottom margin mDropZoneView1.setForceIgnoreBottomMargin(false); mDropZoneView2.setForceIgnoreBottomMargin(false); Loading libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.draganddrop; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.ClipDescription.EXTRA_PENDING_INTENT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.content.Intent.EXTRA_USER; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.UserHandle; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.android.wm.shell.common.DisplayLayout; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; /** * Per-drag session data. */ public class DragSession { private final ActivityTaskManager mActivityTaskManager; private final ClipData mInitialDragData; final DisplayLayout displayLayout; Intent dragData; ActivityManager.RunningTaskInfo runningTaskInfo; @WindowConfiguration.WindowingMode int runningTaskWinMode = WINDOWING_MODE_UNDEFINED; @WindowConfiguration.ActivityType int runningTaskActType = ACTIVITY_TYPE_STANDARD; boolean dragItemSupportsSplitscreen; DragSession(Context context, ActivityTaskManager activityTaskManager, DisplayLayout dispLayout, ClipData data) { mActivityTaskManager = activityTaskManager; mInitialDragData = data; displayLayout = dispLayout; } /** * Updates the session data based on the current state of the system. */ void update() { List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1, false /* filterOnlyVisibleRecents */); if (!tasks.isEmpty()) { final ActivityManager.RunningTaskInfo task = tasks.get(0); runningTaskInfo = task; runningTaskWinMode = task.getWindowingMode(); runningTaskActType = task.getActivityType(); } final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo(); dragItemSupportsSplitscreen = info == null || ActivityInfo.isResizeableMode(info.resizeMode); dragData = mInitialDragData.getItemAt(0).getIntent(); } } libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.draganddrop; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import android.content.ClipDescription; import android.view.DragEvent; /** Collection of utility classes for handling drag and drop. */ public class DragUtils { private static final String TAG = "DragUtils"; /** * Returns whether we can handle this particular drag. */ public static boolean canHandleDrag(DragEvent event) { return event.getClipData().getItemCount() > 0 && (isAppDrag(event.getClipDescription())); } /** * Returns whether this clip data description represents an app drag. */ public static boolean isAppDrag(ClipDescription description) { return description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY) || description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT) || description.hasMimeType(MIMETYPE_APPLICATION_TASK); } /** * Returns a list of the mime types provided in the clip description. */ public static String getMimeTypesConcatenated(ClipDescription description) { String mimeTypes = ""; for (int i = 0; i < description.getMimeTypeCount(); i++) { if (i > 0) { mimeTypes += ", "; } mimeTypes += description.getMimeType(i); } return mimeTypes; } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +11 −25 Original line number Diff line number Diff line Loading @@ -16,9 +16,6 @@ package com.android.wm.shell.draganddrop; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.DragEvent.ACTION_DRAG_ENDED; import static android.view.DragEvent.ACTION_DRAG_ENTERED; Loading @@ -38,6 +35,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission; import static com.android.wm.shell.sysui.ShellSharedConstants.KEY_EXTRA_SHELL_DRAG_AND_DROP; import android.app.ActivityTaskManager; import android.content.ClipDescription; import android.content.ComponentCallbacks2; import android.content.Context; Loading Loading @@ -205,8 +203,6 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll final Context context = mDisplayController.getDisplayContext(displayId) .createWindowContext(TYPE_APPLICATION_OVERLAY, null); final WindowManager wm = context.getSystemService(WindowManager.class); // TODO(b/169894807): Figure out the right layer for this, needs to be below the task bar final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, TYPE_APPLICATION_OVERLAY, Loading Loading @@ -279,15 +275,11 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll } if (event.getAction() == ACTION_DRAG_STARTED) { final boolean hasValidClipData = event.getClipData().getItemCount() > 0 && (description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY) || description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT) || description.hasMimeType(MIMETYPE_APPLICATION_TASK)); pd.isHandlingDrag = hasValidClipData; pd.isHandlingDrag = DragUtils.canHandleDrag(event); ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Clip description: handlingDrag=%b itemCount=%d mimeTypes=%s", pd.isHandlingDrag, event.getClipData().getItemCount(), getMimeTypes(description)); DragUtils.getMimeTypesConcatenated(description)); } if (!pd.isHandlingDrag) { Loading @@ -300,10 +292,13 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll Slog.w(TAG, "Unexpected drag start during an active drag"); return false; } // TODO(b/290391688): Also update the session data with task stack changes InstanceId loggerSessionId = mLogger.logStart(event); pd.activeDragCount++; pd.dragLayout.prepare(mDisplayController.getDisplayLayout(displayId), event.getClipData(), loggerSessionId); pd.dragSession = new DragSession(mContext, ActivityTaskManager.getInstance(), mDisplayController.getDisplayLayout(displayId), event.getClipData()); pd.dragSession.update(); pd.dragLayout.prepare(pd.dragSession, loggerSessionId); setDropTargetWindowVisibility(pd, View.VISIBLE); notifyDragStarted(); break; Loading @@ -324,7 +319,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll break; } case ACTION_DRAG_ENDED: // TODO(b/169894807): Ensure sure it's not possible to get ENDED without DROP // TODO(b/290391688): Ensure sure it's not possible to get ENDED without DROP // or EXITED if (pd.dragLayout.hasDropped()) { mLogger.logDrop(); Loading Loading @@ -362,17 +357,6 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll pd.setWindowVisibility(visibility); } private String getMimeTypes(ClipDescription description) { String mimeTypes = ""; for (int i = 0; i < description.getMimeTypeCount(); i++) { if (i > 0) { mimeTypes += ", "; } mimeTypes += description.getMimeType(i); } return mimeTypes; } /** * Returns if any displays are currently ready to handle a drag/drop. */ Loading Loading @@ -462,6 +446,8 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll // A count of the number of active drags in progress to ensure that we only hide the window // when all the drag animations have completed int activeDragCount; // The active drag session DragSession dragSession; PerDisplay(int dispId, Context c, WindowManager w, FrameLayout rv, DragLayout dl) { displayId = dispId; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java +4 −65 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVIT import static android.app.ComponentOptions.KEY_PENDING_INTENT_BACKGROUND_ACTIVITY_ALLOWED_BY_PERMISSION; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.ClipDescription.EXTRA_ACTIVITY_OPTIONS; import static android.content.ClipDescription.EXTRA_PENDING_INTENT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; Loading @@ -41,16 +40,13 @@ import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPL import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT; import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_TOP; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.ActivityNotFoundException; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.LauncherApps; import android.graphics.Insets; import android.graphics.Rect; Loading @@ -67,14 +63,12 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.InstanceId; import com.android.wm.shell.R; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.splitscreen.SplitScreenController; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.List; /** * The policy for handling drag and drop operations to shell. Loading @@ -84,7 +78,6 @@ public class DragAndDropPolicy { private static final String TAG = DragAndDropPolicy.class.getSimpleName(); private final Context mContext; private final ActivityTaskManager mActivityTaskManager; private final Starter mStarter; private final SplitScreenController mSplitScreen; private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>(); Loading @@ -94,14 +87,12 @@ public class DragAndDropPolicy { private DragSession mSession; public DragAndDropPolicy(Context context, SplitScreenController splitScreen) { this(context, ActivityTaskManager.getInstance(), splitScreen, new DefaultStarter(context)); this(context, splitScreen, new DefaultStarter(context)); } @VisibleForTesting DragAndDropPolicy(Context context, ActivityTaskManager activityTaskManager, SplitScreenController splitScreen, Starter starter) { DragAndDropPolicy(Context context, SplitScreenController splitScreen, Starter starter) { mContext = context; mActivityTaskManager = activityTaskManager; mSplitScreen = splitScreen; mStarter = mSplitScreen != null ? mSplitScreen : starter; } Loading @@ -109,11 +100,9 @@ public class DragAndDropPolicy { /** * Starts a new drag session with the given initial drag data. */ void start(DisplayLayout displayLayout, ClipData data, InstanceId loggerSessionId) { void start(DragSession session, InstanceId loggerSessionId) { mLoggerSessionId = loggerSessionId; mSession = new DragSession(mActivityTaskManager, displayLayout, data); // TODO(b/169894807): Also update the session data with task stack changes mSession.update(); mSession = session; RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION); if (disallowHitRegion == null) { mDisallowHitRegion.setEmpty(); Loading @@ -122,13 +111,6 @@ public class DragAndDropPolicy { } } /** * Returns the last running task. */ ActivityManager.RunningTaskInfo getLatestRunningTask() { return mSession.runningTaskInfo; } /** * Returns the number of targets. */ Loading Loading @@ -285,49 +267,6 @@ public class DragAndDropPolicy { } } /** * Per-drag session data. */ private static class DragSession { private final ActivityTaskManager mActivityTaskManager; private final ClipData mInitialDragData; final DisplayLayout displayLayout; Intent dragData; ActivityManager.RunningTaskInfo runningTaskInfo; @WindowConfiguration.WindowingMode int runningTaskWinMode = WINDOWING_MODE_UNDEFINED; @WindowConfiguration.ActivityType int runningTaskActType = ACTIVITY_TYPE_STANDARD; boolean dragItemSupportsSplitscreen; DragSession(ActivityTaskManager activityTaskManager, DisplayLayout dispLayout, ClipData data) { mActivityTaskManager = activityTaskManager; mInitialDragData = data; displayLayout = dispLayout; } /** * Updates the session data based on the current state of the system. */ void update() { List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1, false /* filterOnlyVisibleRecents */); if (!tasks.isEmpty()) { final ActivityManager.RunningTaskInfo task = tasks.get(0); runningTaskInfo = task; runningTaskWinMode = task.getWindowingMode(); runningTaskActType = task.getActivityType(); } final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo(); dragItemSupportsSplitscreen = info == null || ActivityInfo.isResizeableMode(info.resizeMode); dragData = mInitialDragData.getItemAt(0).getIntent(); } } /** * Interface for actually committing the task launches. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +19 −8 Original line number Diff line number Diff line Loading @@ -35,7 +35,6 @@ import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.ActivityManager; import android.app.StatusBarManager; import android.content.ClipData; import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; Loading @@ -53,14 +52,13 @@ import com.android.internal.protolog.common.ProtoLog; import com.android.launcher3.icons.IconProvider; import com.android.wm.shell.R; import com.android.wm.shell.animation.Interpolators; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.ArrayList; /** * Coordinates the visible drop targets for the current drag. * Coordinates the visible drop targets for the current drag within a single display. */ public class DragLayout extends LinearLayout { Loading @@ -86,6 +84,7 @@ public class DragLayout extends LinearLayout { private boolean mIsShowing; private boolean mHasDropped; private DragSession mSession; @SuppressLint("WrongConstant") public DragLayout(Context context, SplitScreenController splitScreenController, Loading Loading @@ -182,16 +181,19 @@ public class DragLayout extends LinearLayout { return mHasDropped; } public void prepare(DisplayLayout displayLayout, ClipData initialData, InstanceId loggerSessionId) { mPolicy.start(displayLayout, initialData, loggerSessionId); /** * Called when a new drag is started. */ public void prepare(DragSession session, InstanceId loggerSessionId) { mPolicy.start(session, loggerSessionId); mSession = session; mHasDropped = false; mCurrentTarget = null; boolean alreadyInSplit = mSplitScreenController != null && mSplitScreenController.isSplitScreenVisible(); if (!alreadyInSplit) { ActivityManager.RunningTaskInfo taskInfo1 = mPolicy.getLatestRunningTask(); ActivityManager.RunningTaskInfo taskInfo1 = mSession.runningTaskInfo; if (taskInfo1 != null) { final int activityType = taskInfo1.getActivityType(); if (activityType == ACTIVITY_TYPE_STANDARD) { Loading Loading @@ -356,7 +358,16 @@ public class DragLayout extends LinearLayout { */ public void hide(DragEvent event, Runnable hideCompleteCallback) { mIsShowing = false; animateSplitContainers(false, hideCompleteCallback); animateSplitContainers(false, () -> { if (hideCompleteCallback != null) { hideCompleteCallback.run(); } switch (event.getAction()) { case DragEvent.ACTION_DROP: case DragEvent.ACTION_DRAG_ENDED: mSession = null; } }); // Reset the state if we previously force-ignore the bottom margin mDropZoneView1.setForceIgnoreBottomMargin(false); mDropZoneView2.setForceIgnoreBottomMargin(false); Loading
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java 0 → 100644 +89 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.draganddrop; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.ClipDescription.EXTRA_PENDING_INTENT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import static android.content.Intent.EXTRA_USER; import android.app.ActivityManager; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.ClipData; import android.content.ClipDescription; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.net.Uri; import android.os.UserHandle; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.android.wm.shell.common.DisplayLayout; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; /** * Per-drag session data. */ public class DragSession { private final ActivityTaskManager mActivityTaskManager; private final ClipData mInitialDragData; final DisplayLayout displayLayout; Intent dragData; ActivityManager.RunningTaskInfo runningTaskInfo; @WindowConfiguration.WindowingMode int runningTaskWinMode = WINDOWING_MODE_UNDEFINED; @WindowConfiguration.ActivityType int runningTaskActType = ACTIVITY_TYPE_STANDARD; boolean dragItemSupportsSplitscreen; DragSession(Context context, ActivityTaskManager activityTaskManager, DisplayLayout dispLayout, ClipData data) { mActivityTaskManager = activityTaskManager; mInitialDragData = data; displayLayout = dispLayout; } /** * Updates the session data based on the current state of the system. */ void update() { List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1, false /* filterOnlyVisibleRecents */); if (!tasks.isEmpty()) { final ActivityManager.RunningTaskInfo task = tasks.get(0); runningTaskInfo = task; runningTaskWinMode = task.getWindowingMode(); runningTaskActType = task.getActivityType(); } final ActivityInfo info = mInitialDragData.getItemAt(0).getActivityInfo(); dragItemSupportsSplitscreen = info == null || ActivityInfo.isResizeableMode(info.resizeMode); dragData = mInitialDragData.getItemAt(0).getIntent(); } }
libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java 0 → 100644 +60 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 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.draganddrop; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT; import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK; import android.content.ClipDescription; import android.view.DragEvent; /** Collection of utility classes for handling drag and drop. */ public class DragUtils { private static final String TAG = "DragUtils"; /** * Returns whether we can handle this particular drag. */ public static boolean canHandleDrag(DragEvent event) { return event.getClipData().getItemCount() > 0 && (isAppDrag(event.getClipDescription())); } /** * Returns whether this clip data description represents an app drag. */ public static boolean isAppDrag(ClipDescription description) { return description.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY) || description.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT) || description.hasMimeType(MIMETYPE_APPLICATION_TASK); } /** * Returns a list of the mime types provided in the clip description. */ public static String getMimeTypesConcatenated(ClipDescription description) { String mimeTypes = ""; for (int i = 0; i < description.getMimeTypeCount(); i++) { if (i > 0) { mimeTypes += ", "; } mimeTypes += description.getMimeType(i); } return mimeTypes; } }