Merge "Only allow app drags to go to global intercept windows" into sc-dev
This commit is contained in:
@@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
|
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.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
|
||||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
|
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
|
||||||
|
|
||||||
@@ -441,8 +444,9 @@ class DragState {
|
|||||||
Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
|
Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final boolean containsAppExtras = containsApplicationExtras(mDataDescription);
|
||||||
mService.mRoot.forAllWindows(w -> {
|
mService.mRoot.forAllWindows(w -> {
|
||||||
sendDragStartedLocked(w, touchX, touchY, mDataDescription, mData);
|
sendDragStartedLocked(w, touchX, touchY, containsAppExtras);
|
||||||
}, false /* traverseTopToBottom */);
|
}, false /* traverseTopToBottom */);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +459,9 @@ class DragState {
|
|||||||
* process, so it's safe for the caller to call recycle() on the event afterwards.
|
* process, so it's safe for the caller to call recycle() on the event afterwards.
|
||||||
*/
|
*/
|
||||||
private void sendDragStartedLocked(WindowState newWin, float touchX, float touchY,
|
private void sendDragStartedLocked(WindowState newWin, float touchX, float touchY,
|
||||||
ClipDescription desc, ClipData data) {
|
boolean containsAppExtras) {
|
||||||
final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin);
|
final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin);
|
||||||
if (mDragInProgress && isValidDropTarget(newWin, interceptsGlobalDrag)) {
|
if (mDragInProgress && isValidDropTarget(newWin, containsAppExtras, interceptsGlobalDrag)) {
|
||||||
DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY,
|
DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY,
|
||||||
interceptsGlobalDrag, false /* includeDragSurface */,
|
interceptsGlobalDrag, false /* includeDragSurface */,
|
||||||
null /* dragAndDropPermission */);
|
null /* dragAndDropPermission */);
|
||||||
@@ -476,10 +480,28 @@ class DragState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isValidDropTarget(WindowState targetWin, boolean interceptsGlobalDrag) {
|
/**
|
||||||
|
* Returns true if this is a drag of an application mime type.
|
||||||
|
*/
|
||||||
|
private boolean containsApplicationExtras(ClipDescription desc) {
|
||||||
|
if (desc == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return desc.hasMimeType(MIMETYPE_APPLICATION_ACTIVITY)
|
||||||
|
|| desc.hasMimeType(MIMETYPE_APPLICATION_SHORTCUT)
|
||||||
|
|| desc.hasMimeType(MIMETYPE_APPLICATION_TASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidDropTarget(WindowState targetWin, boolean containsAppExtras,
|
||||||
|
boolean interceptsGlobalDrag) {
|
||||||
if (targetWin == null) {
|
if (targetWin == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!interceptsGlobalDrag && containsAppExtras) {
|
||||||
|
// App-drags can only go to windows that can intercept global drag, and not to normal
|
||||||
|
// app windows
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!targetWin.isPotentialDragTarget(interceptsGlobalDrag)) {
|
if (!targetWin.isPotentialDragTarget(interceptsGlobalDrag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -522,7 +544,8 @@ class DragState {
|
|||||||
if (DEBUG_DRAG) {
|
if (DEBUG_DRAG) {
|
||||||
Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
|
Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
|
||||||
}
|
}
|
||||||
sendDragStartedLocked(newWin, mCurrentX, mCurrentY, mDataDescription, mData);
|
sendDragStartedLocked(newWin, mCurrentX, mCurrentY,
|
||||||
|
containsApplicationExtras(mDataDescription));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -238,6 +238,35 @@ public class DragDropControllerTests extends WindowTestsBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptGlobalDragDropIgnoresOtherWindows() {
|
||||||
|
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 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());
|
||||||
|
assertTrue(globalInterceptWindowDragEvents.get(0).getAction()
|
||||||
|
== ACTION_DRAG_STARTED);
|
||||||
|
|
||||||
|
mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0);
|
||||||
|
mTarget.handleMotionEvent(false, 0, 0);
|
||||||
|
mToken = globalInterceptWindow.mClient.asBinder();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testValidateAppActivityArguments() {
|
public void testValidateAppActivityArguments() {
|
||||||
final Session session = new Session(mWm, new IWindowSessionCallback.Stub() {
|
final Session session = new Session(mWm, new IWindowSessionCallback.Stub() {
|
||||||
|
|||||||
Reference in New Issue
Block a user