Fix regression in app drag target windows

- Only disallow non-local, non-global intercepting windows from
  receiving drags.  The window which originated the drag still might
  want to receive drag events to kick off animations/etc.

Bug: 178690347
Test: atest DragDropControllerTests
Change-Id: I856d179993e687ba343e35d87bd1f3c613e637db
This commit is contained in:
Winson Chung
2021-05-18 22:25:09 -07:00
parent b9034aba83
commit 7aeb642c91
2 changed files with 18 additions and 11 deletions

View File

@@ -497,9 +497,10 @@ class DragState {
if (targetWin == null) {
return false;
}
if (!interceptsGlobalDrag && containsAppExtras) {
// App-drags can only go to windows that can intercept global drag, and not to normal
// app windows
final boolean isLocalWindow = mLocalWin == targetWin.mClient.asBinder();
if (!isLocalWindow && !interceptsGlobalDrag && containsAppExtras) {
// App-drags can only go to local windows or windows that can intercept global drag, and
// not to other app windows
return false;
}
if (!targetWin.isPotentialDragTarget(interceptsGlobalDrag)) {
@@ -507,7 +508,7 @@ class DragState {
}
if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0 || !targetWindowSupportsGlobalDrag(targetWin)) {
// Drag is limited to the current window.
if (mLocalWin != targetWin.mClient.asBinder()) {
if (!isLocalWindow) {
return false;
}
}

View File

@@ -239,25 +239,31 @@ public class DragDropControllerTests extends WindowTestsBase {
}
@Test
public void testInterceptGlobalDragDropIgnoresOtherWindows() {
public void testPrivateInterceptGlobalDragDropIgnoresNonLocalWindows() {
WindowState nonLocalWindow = createDropTargetWindow("App drag test window", 0);
WindowState globalInterceptWindow = createDropTargetWindow("Global drag test window", 0);
globalInterceptWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
// Necessary for now since DragState.sendDragStartedLocked() will recycle drag events
// immediately after dispatching, which is a problem when using mockito arguments captor
// because it returns and modifies the same drag event
TestIWindow iwindow = (TestIWindow) mWindow.mClient;
final ArrayList<DragEvent> dragEvents = new ArrayList<>();
iwindow.setDragEventJournal(dragEvents);
TestIWindow localIWindow = (TestIWindow) mWindow.mClient;
final ArrayList<DragEvent> localWindowDragEvents = new ArrayList<>();
localIWindow.setDragEventJournal(localWindowDragEvents);
TestIWindow nonLocalIWindow = (TestIWindow) nonLocalWindow.mClient;
final ArrayList<DragEvent> nonLocalWindowDragEvents = new ArrayList<>();
nonLocalIWindow.setDragEventJournal(nonLocalWindowDragEvents);
TestIWindow globalInterceptIWindow = (TestIWindow) globalInterceptWindow.mClient;
final ArrayList<DragEvent> globalInterceptWindowDragEvents = new ArrayList<>();
globalInterceptIWindow.setDragEventJournal(globalInterceptWindowDragEvents);
startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ,
createClipDataForActivity(null, mock(UserHandle.class)), () -> {
// Verify the start-drag event is sent for the intercept window but not the
// other window
assertTrue(dragEvents.isEmpty());
// Verify the start-drag event is sent for the local and global intercept window
// but not the other window
assertTrue(nonLocalWindowDragEvents.isEmpty());
assertTrue(localWindowDragEvents.get(0).getAction()
== ACTION_DRAG_STARTED);
assertTrue(globalInterceptWindowDragEvents.get(0).getAction()
== ACTION_DRAG_STARTED);