Only initialize the drag session after we confirm we can handle the drag
- In ag/28686955 we moved the initialization of the drag session earlier
in the flow to optimize the call to update the running task, but we
should only need to initialize if there is valid drag data.
Flag: EXEMPT bugfix
Fixes: 383034393
Test: atest WMShellUnitTests
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:1b3ccc22ec6f1c3df5dfe6d964853ca4d1d1f49a)
Merged-In: I8005cee8b7c0d4e58a173ea5de3b53e343f4523d
Change-Id: I8005cee8b7c0d4e58a173ea5de3b53e343f4523d
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 491b577..e24b2c5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -332,7 +332,9 @@
dragSession = new DragSession(ActivityTaskManager.getInstance(),
mDisplayController.getDisplayLayout(displayId), event.getClipData(),
event.getDragFlags());
- dragSession.initialize();
+ // Only update the running task for now to determine if we should defer to desktop to
+ // handle the drag
+ dragSession.updateRunningTask();
final ActivityManager.RunningTaskInfo taskInfo = dragSession.runningTaskInfo;
// Desktop tasks will have their own drag handling.
final boolean isDesktopDrag = taskInfo != null && taskInfo.isFreeform()
@@ -340,7 +342,8 @@
pd.isHandlingDrag = DragUtils.canHandleDrag(event) && !isDesktopDrag;
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP,
"Clip description: handlingDrag=%b itemCount=%d mimeTypes=%s flags=%s",
- pd.isHandlingDrag, event.getClipData().getItemCount(),
+ pd.isHandlingDrag,
+ event.getClipData() != null ? event.getClipData().getItemCount() : -1,
DragUtils.getMimeTypesConcatenated(description),
DragUtils.dragFlagsToString(event.getDragFlags()));
}
@@ -355,6 +358,8 @@
Slog.w(TAG, "Unexpected drag start during an active drag");
return false;
}
+ // Only initialize the session after we've checked that we're handling the drag
+ dragSession.initialize(true /* skipUpdateRunningTask */);
pd.dragSession = dragSession;
pd.activeDragCount++;
pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
index c4ff87d..279452e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragSession.java
@@ -29,7 +29,6 @@
import android.content.ClipDescription;
import android.content.Intent;
import android.content.pm.ActivityInfo;
-import android.os.PersistableBundle;
import androidx.annotation.Nullable;
@@ -44,6 +43,7 @@
*/
public class DragSession {
private final ActivityTaskManager mActivityTaskManager;
+ @Nullable
private final ClipData mInitialDragData;
private final int mInitialDragFlags;
@@ -66,7 +66,7 @@
@WindowConfiguration.ActivityType
int runningTaskActType = ACTIVITY_TYPE_STANDARD;
boolean dragItemSupportsSplitscreen;
- int hideDragSourceTaskId = -1;
+ final int hideDragSourceTaskId;
DragSession(ActivityTaskManager activityTaskManager,
DisplayLayout dispLayout, ClipData data, int dragFlags) {
@@ -83,7 +83,6 @@
/**
* Returns the clip description associated with the drag.
- * @return
*/
ClipDescription getClipDescription() {
return mInitialDragData.getDescription();
@@ -125,8 +124,10 @@
/**
* Updates the session data based on the current state of the system at the start of the drag.
*/
- void initialize() {
- updateRunningTask();
+ void initialize(boolean skipUpdateRunningTask) {
+ if (!skipUpdateRunningTask) {
+ updateRunningTask();
+ }
activityInfo = mInitialDragData.getItemAt(0).getActivityInfo();
// TODO: This should technically check & respect config_supportsNonResizableMultiWindow
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java
index 248a112..a62dd1c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragUtils.java
@@ -49,7 +49,7 @@
* Returns whether we can handle this particular drag.
*/
public static boolean canHandleDrag(DragEvent event) {
- if (event.getClipData().getItemCount() <= 0) {
+ if (event.getClipData() == null || event.getClipData().getItemCount() <= 0) {
// No clip data, ignore this drag
return false;
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
index e40bbad..32bb8bb 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
@@ -150,4 +150,25 @@
mController.onDrag(dragLayout, event);
verify(mDragAndDropListener, never()).onDragStarted();
}
+
+ @Test
+ public void testOnDragStarted_withNoClipData() {
+ final View dragLayout = mock(View.class);
+ final Display display = mock(Display.class);
+ doReturn(display).when(dragLayout).getDisplay();
+ doReturn(DEFAULT_DISPLAY).when(display).getDisplayId();
+
+ final ClipData clipData = createAppClipData(MIMETYPE_APPLICATION_SHORTCUT);
+ final DragEvent event = mock(DragEvent.class);
+ doReturn(ACTION_DRAG_STARTED).when(event).getAction();
+ doReturn(null).when(event).getClipData();
+ doReturn(clipData.getDescription()).when(event).getClipDescription();
+
+ // Ensure there's a target so that onDrag will execute
+ mController.addDisplayDropTarget(0, mContext, mock(WindowManager.class),
+ mock(FrameLayout.class), mock(DragLayout.class));
+
+ // Verify the listener is called on a valid drag action.
+ mController.onDrag(dragLayout, event);
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/SplitDragPolicyTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/SplitDragPolicyTest.java
index 0cf15ba..a284663 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/SplitDragPolicyTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/SplitDragPolicyTest.java
@@ -220,7 +220,7 @@
setRunningTask(mHomeTask);
DragSession dragSession = new DragSession(mActivityTaskManager,
mLandscapeDisplayLayout, data, 0 /* dragFlags */);
- dragSession.initialize();
+ dragSession.initialize(false /* skipUpdateRunningTask */);
mPolicy.start(dragSession, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_FULLSCREEN);
@@ -235,7 +235,7 @@
setRunningTask(mFullscreenAppTask);
DragSession dragSession = new DragSession(mActivityTaskManager,
mLandscapeDisplayLayout, data, 0 /* dragFlags */);
- dragSession.initialize();
+ dragSession.initialize(false /* skipUpdateRunningTask */);
mPolicy.start(dragSession, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_LEFT, TYPE_SPLIT_RIGHT);
@@ -255,7 +255,7 @@
setRunningTask(mFullscreenAppTask);
DragSession dragSession = new DragSession(mActivityTaskManager,
mPortraitDisplayLayout, data, 0 /* dragFlags */);
- dragSession.initialize();
+ dragSession.initialize(false /* skipUpdateRunningTask */);
mPolicy.start(dragSession, mLoggerSessionId);
ArrayList<Target> targets = assertExactTargetTypes(
mPolicy.getTargets(mInsets), TYPE_SPLIT_TOP, TYPE_SPLIT_BOTTOM);
@@ -276,7 +276,7 @@
setRunningTask(mFullscreenAppTask);
DragSession dragSession = new DragSession(mActivityTaskManager,
mLandscapeDisplayLayout, mActivityClipData, 0 /* dragFlags */);
- dragSession.initialize();
+ dragSession.initialize(false /* skipUpdateRunningTask */);
mPolicy.start(dragSession, mLoggerSessionId);
ArrayList<Target> targets = mPolicy.getTargets(mInsets);
for (Target t : targets) {