Merge "Move drag event to InputDispatcher (6/n)" into sc-dev
This commit is contained in:
@@ -2605,6 +2605,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
mWindowManagerCallbacks.notifyFocusChanged(oldToken, newToken);
|
||||
}
|
||||
|
||||
// Native callback
|
||||
private void notifyDropWindow(IBinder token, float x, float y) {
|
||||
mWindowManagerCallbacks.notifyDropWindow(token, x, y);
|
||||
}
|
||||
|
||||
// Native callback
|
||||
private void notifyUntrustedTouch(String packageName) {
|
||||
// TODO(b/169067926): Remove toast after gathering feedback on dogfood.
|
||||
@@ -3035,6 +3040,11 @@ public class InputManagerService extends IInputManager.Stub
|
||||
* Called when the focused window has changed.
|
||||
*/
|
||||
void notifyFocusChanged(IBinder oldToken, IBinder newToken);
|
||||
|
||||
/**
|
||||
* Called when the drag over window has changed.
|
||||
*/
|
||||
void notifyDropWindow(IBinder token, float x, float y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -283,11 +283,7 @@ class DragDropController {
|
||||
return;
|
||||
}
|
||||
|
||||
if (keepHandling) {
|
||||
mDragState.notifyMoveLocked(newX, newY);
|
||||
} else {
|
||||
mDragState.notifyDropLocked(newX, newY);
|
||||
}
|
||||
mDragState.updateDragSurfaceLocked(keepHandling, newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,6 +326,12 @@ class DragDropController {
|
||||
mDragState = null;
|
||||
}
|
||||
|
||||
void reportDropWindow(IBinder token, float x, float y) {
|
||||
synchronized (mService.mGlobalLock) {
|
||||
mDragState.reportDropWindowLock(token, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
private class DragHandler extends Handler {
|
||||
/**
|
||||
* Lock for window manager.
|
||||
|
||||
@@ -109,7 +109,6 @@ class DragState {
|
||||
float mCurrentX, mCurrentY;
|
||||
float mThumbOffsetX, mThumbOffsetY;
|
||||
InputInterceptor mInputInterceptor;
|
||||
WindowState mTargetWindow;
|
||||
ArrayList<WindowState> mNotifiedWindows;
|
||||
boolean mDragInProgress;
|
||||
/**
|
||||
@@ -217,18 +216,18 @@ class DragState {
|
||||
x = mCurrentX;
|
||||
y = mCurrentY;
|
||||
}
|
||||
DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
|
||||
DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
|
||||
x, y, mThumbOffsetX, mThumbOffsetY, null, null, null, null, null,
|
||||
mDragResult);
|
||||
try {
|
||||
ws.mClient.dispatchDragEvent(evt);
|
||||
ws.mClient.dispatchDragEvent(event);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG_WM, "Unable to drag-end window " + ws);
|
||||
}
|
||||
// if the current window is in the same process,
|
||||
// the dispatch has already recycled the event
|
||||
if (myPid != ws.mSession.mPid) {
|
||||
evt.recycle();
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
mNotifiedWindows.clear();
|
||||
@@ -270,6 +269,68 @@ class DragState {
|
||||
mDragDropController.onDragStateClosedLocked(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify the drop target and tells it about the data. If the drop event is not sent to the
|
||||
* target, invokes {@code endDragLocked} immediately.
|
||||
*/
|
||||
void reportDropWindowLock(IBinder token, float x, float y) {
|
||||
if (mAnimator != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final WindowState touchedWin = mService.mInputToWindowMap.get(token);
|
||||
if (!isWindowNotified(touchedWin)) {
|
||||
// "drop" outside a valid window -- no recipient to apply a
|
||||
// timeout to, and we can send the drag-ended message immediately.
|
||||
mDragResult = false;
|
||||
endDragLocked();
|
||||
if (DEBUG_DRAG) Slog.d(TAG_WM, "Drop outside a valid window " + touchedWin);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_DRAG) Slog.d(TAG_WM, "sending DROP to " + touchedWin);
|
||||
|
||||
final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
|
||||
|
||||
final DragAndDropPermissionsHandler dragAndDropPermissions;
|
||||
if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
|
||||
&& mData != null) {
|
||||
dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
|
||||
mData,
|
||||
mUid,
|
||||
touchedWin.getOwningPackage(),
|
||||
mFlags & DRAG_FLAGS_URI_PERMISSIONS,
|
||||
mSourceUserId,
|
||||
targetUserId);
|
||||
} else {
|
||||
dragAndDropPermissions = null;
|
||||
}
|
||||
if (mSourceUserId != targetUserId) {
|
||||
if (mData != null) {
|
||||
mData.fixUris(mSourceUserId);
|
||||
}
|
||||
}
|
||||
final int myPid = Process.myPid();
|
||||
final IBinder clientToken = touchedWin.mClient.asBinder();
|
||||
final DragEvent event = obtainDragEvent(DragEvent.ACTION_DROP, x, y,
|
||||
true /* includeData */, targetInterceptsGlobalDrag(touchedWin),
|
||||
dragAndDropPermissions);
|
||||
try {
|
||||
touchedWin.mClient.dispatchDragEvent(event);
|
||||
|
||||
// 5 second timeout for this window to respond to the drop
|
||||
mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, clientToken);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
|
||||
endDragLocked();
|
||||
} finally {
|
||||
if (myPid != touchedWin.mSession.mPid) {
|
||||
event.recycle();
|
||||
}
|
||||
}
|
||||
mToken = clientToken;
|
||||
}
|
||||
|
||||
class InputInterceptor {
|
||||
InputChannel mClientChannel;
|
||||
DragInputEventReceiver mInputEventReceiver;
|
||||
@@ -397,9 +458,9 @@ class DragState {
|
||||
ClipDescription desc, ClipData data) {
|
||||
final boolean interceptsGlobalDrag = targetInterceptsGlobalDrag(newWin);
|
||||
if (mDragInProgress && isValidDropTarget(newWin, interceptsGlobalDrag)) {
|
||||
DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
|
||||
touchX, touchY, mThumbOffsetX, mThumbOffsetY, null, desc,
|
||||
interceptsGlobalDrag ? data : null, null, null, false);
|
||||
DragEvent event = obtainDragEvent(DragEvent.ACTION_DRAG_STARTED, touchX, touchY,
|
||||
interceptsGlobalDrag, false /* includeDragSurface */,
|
||||
null /* dragAndDropPermission */);
|
||||
try {
|
||||
newWin.mClient.dispatchDragEvent(event);
|
||||
// track each window that we've notified that the drag is starting
|
||||
@@ -501,13 +562,17 @@ class DragState {
|
||||
mAnimator = createCancelAnimationLocked();
|
||||
}
|
||||
|
||||
void notifyMoveLocked(float x, float y) {
|
||||
void updateDragSurfaceLocked(boolean keepHandling, float x, float y) {
|
||||
if (mAnimator != null) {
|
||||
return;
|
||||
}
|
||||
mCurrentX = x;
|
||||
mCurrentY = y;
|
||||
|
||||
if (!keepHandling) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Move the surface to the given touch
|
||||
if (SHOW_LIGHT_TRANSACTIONS) {
|
||||
Slog.i(TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
|
||||
@@ -517,71 +582,6 @@ class DragState {
|
||||
(int) (x - mThumbOffsetX), (int) (y - mThumbOffsetY));
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the drop target and tells it about the data. If the drop event is not sent to the
|
||||
* target, invokes {@code endDragLocked} immediately.
|
||||
*/
|
||||
void notifyDropLocked(float x, float y) {
|
||||
if (mAnimator != null) {
|
||||
return;
|
||||
}
|
||||
mCurrentX = x;
|
||||
mCurrentY = y;
|
||||
|
||||
final WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
|
||||
|
||||
if (!isWindowNotified(touchedWin)) {
|
||||
// "drop" outside a valid window -- no recipient to apply a
|
||||
// timeout to, and we can send the drag-ended message immediately.
|
||||
mDragResult = false;
|
||||
endDragLocked();
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_DRAG) Slog.d(TAG_WM, "sending DROP to " + touchedWin);
|
||||
|
||||
final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
|
||||
|
||||
final DragAndDropPermissionsHandler dragAndDropPermissions;
|
||||
if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
|
||||
&& mData != null) {
|
||||
dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
|
||||
mData,
|
||||
mUid,
|
||||
touchedWin.getOwningPackage(),
|
||||
mFlags & DRAG_FLAGS_URI_PERMISSIONS,
|
||||
mSourceUserId,
|
||||
targetUserId);
|
||||
} else {
|
||||
dragAndDropPermissions = null;
|
||||
}
|
||||
if (mSourceUserId != targetUserId){
|
||||
if (mData != null) {
|
||||
mData.fixUris(mSourceUserId);
|
||||
}
|
||||
}
|
||||
final int myPid = Process.myPid();
|
||||
final IBinder token = touchedWin.mClient.asBinder();
|
||||
final DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
|
||||
mThumbOffsetX, mThumbOffsetY, null, null, mData,
|
||||
targetInterceptsGlobalDrag(touchedWin) ? mSurfaceControl : null,
|
||||
dragAndDropPermissions, false);
|
||||
try {
|
||||
touchedWin.mClient.dispatchDragEvent(evt);
|
||||
|
||||
// 5 second timeout for this window to respond to the drop
|
||||
mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, token);
|
||||
} catch (RemoteException e) {
|
||||
Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
|
||||
endDragLocked();
|
||||
} finally {
|
||||
if (myPid != touchedWin.mSession.mPid) {
|
||||
evt.recycle();
|
||||
}
|
||||
}
|
||||
mToken = token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if it has sent DRAG_STARTED broadcast out but has not been sent DRAG_END
|
||||
* broadcast.
|
||||
@@ -590,14 +590,12 @@ class DragState {
|
||||
return mDragInProgress;
|
||||
}
|
||||
|
||||
private static DragEvent obtainDragEvent(WindowState win, int action, float x, float y,
|
||||
float offsetX, float offsetY, Object localState, ClipDescription description,
|
||||
ClipData data, SurfaceControl dragSurface,
|
||||
IDragAndDropPermissions dragAndDropPermissions, boolean result) {
|
||||
final float winX = win.translateToWindowX(x);
|
||||
final float winY = win.translateToWindowY(y);
|
||||
return DragEvent.obtain(action, winX, winY, offsetX, offsetY, localState, description, data,
|
||||
dragSurface, dragAndDropPermissions, result);
|
||||
private DragEvent obtainDragEvent(int action, float x, float y, boolean includeData,
|
||||
boolean includeDragSurface, IDragAndDropPermissions dragAndDropPermissions) {
|
||||
return DragEvent.obtain(action, x, y, mThumbOffsetX, mThumbOffsetY,
|
||||
null /* localState */, mDataDescription,
|
||||
includeData ? mData : null, includeDragSurface ? mSurfaceControl : null,
|
||||
dragAndDropPermissions, false /* result */);
|
||||
}
|
||||
|
||||
private ValueAnimator createReturnAnimationLocked() {
|
||||
|
||||
@@ -229,6 +229,12 @@ final class InputManagerCallback implements InputManagerService.WindowManagerCal
|
||||
mService::reportFocusChanged, oldToken, newToken));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDropWindow(IBinder token, float x, float y) {
|
||||
mService.mH.sendMessage(PooledLambda.obtainMessage(
|
||||
mService.mDragDropController::reportDropWindow, token, x, y));
|
||||
}
|
||||
|
||||
/** Waits until the built-in input devices have been configured. */
|
||||
public boolean waitForInputDevicesReady(long timeoutMillis) {
|
||||
synchronized (mInputDevicesReadyMonitor) {
|
||||
|
||||
@@ -44,7 +44,7 @@ public class WindowManagerDebugConfig {
|
||||
static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
|
||||
static final boolean DEBUG_WALLPAPER = false;
|
||||
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
|
||||
static final boolean DEBUG_DRAG = false;
|
||||
static final boolean DEBUG_DRAG = true;
|
||||
static final boolean DEBUG_SCREENSHOT = false;
|
||||
static final boolean DEBUG_LAYOUT_REPEATS = false;
|
||||
static final boolean DEBUG_WINDOW_TRACE = false;
|
||||
|
||||
@@ -131,6 +131,7 @@ static struct {
|
||||
jmethodID getDeviceAlias;
|
||||
jmethodID getTouchCalibrationForInputDevice;
|
||||
jmethodID getContextForDisplay;
|
||||
jmethodID notifyDropWindow;
|
||||
} gServiceClassInfo;
|
||||
|
||||
static struct {
|
||||
@@ -335,6 +336,7 @@ public:
|
||||
bool checkInjectEventsPermissionNonReentrant(int32_t injectorPid, int32_t injectorUid) override;
|
||||
void onPointerDownOutsideFocus(const sp<IBinder>& touchedToken) override;
|
||||
void setPointerCapture(bool enabled) override;
|
||||
void notifyDropWindow(const sp<IBinder>& token, float x, float y) override;
|
||||
|
||||
/* --- PointerControllerPolicyInterface implementation --- */
|
||||
|
||||
@@ -905,6 +907,20 @@ void NativeInputManager::notifyFocusChanged(const sp<IBinder>& oldToken,
|
||||
checkAndClearExceptionFromCallback(env, "notifyFocusChanged");
|
||||
}
|
||||
|
||||
void NativeInputManager::notifyDropWindow(const sp<IBinder>& token, float x, float y) {
|
||||
#if DEBUG_INPUT_DISPATCHER_POLICY
|
||||
ALOGD("notifyDropWindow");
|
||||
#endif
|
||||
ATRACE_CALL();
|
||||
|
||||
JNIEnv* env = jniEnv();
|
||||
ScopedLocalFrame localFrame(env);
|
||||
|
||||
jobject tokenObj = javaObjectForIBinder(env, token);
|
||||
env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifyDropWindow, tokenObj, x, y);
|
||||
checkAndClearExceptionFromCallback(env, "notifyDropWindow");
|
||||
}
|
||||
|
||||
void NativeInputManager::notifySensorEvent(int32_t deviceId, InputDeviceSensorType sensorType,
|
||||
InputDeviceSensorAccuracy accuracy, nsecs_t timestamp,
|
||||
const std::vector<float>& values) {
|
||||
@@ -2350,6 +2366,8 @@ int register_android_server_InputManager(JNIEnv* env) {
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyFocusChanged, clazz,
|
||||
"notifyFocusChanged", "(Landroid/os/IBinder;Landroid/os/IBinder;)V");
|
||||
GET_METHOD_ID(gServiceClassInfo.notifyDropWindow, clazz, "notifyDropWindow",
|
||||
"(Landroid/os/IBinder;FF)V");
|
||||
|
||||
GET_METHOD_ID(gServiceClassInfo.notifySensorEvent, clazz, "notifySensorEvent", "(IIIJ[F)V");
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ public class DragDropControllerTests extends WindowTestsBase {
|
||||
null, TYPE_BASE_APPLICATION, activity, name, ownerId, false, new TestIWindow());
|
||||
window.mInputChannel = new InputChannel();
|
||||
window.mHasSurface = true;
|
||||
mWm.mInputToWindowMap.put(window.mInputChannelToken, window);
|
||||
return window;
|
||||
}
|
||||
|
||||
@@ -226,7 +227,7 @@ public class DragDropControllerTests extends WindowTestsBase {
|
||||
// Verify after consuming that the drag surface is relinquished
|
||||
try {
|
||||
mTarget.mDeferDragStateClosed = true;
|
||||
|
||||
mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
|
||||
// Verify the drop event includes the drag surface
|
||||
mTarget.handleMotionEvent(false, 0, 0);
|
||||
final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
|
||||
@@ -355,6 +356,7 @@ public class DragDropControllerTests extends WindowTestsBase {
|
||||
|
||||
private void doDragAndDrop(int flags, ClipData data, float dropX, float dropY) {
|
||||
startDrag(flags, data, () -> {
|
||||
mTarget.reportDropWindow(mWindow.mInputChannelToken, dropX, dropY);
|
||||
mTarget.handleMotionEvent(false, dropX, dropY);
|
||||
mToken = mWindow.mClient.asBinder();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user