Merge "Move drag event to InputDispatcher (6/n)" into sc-dev

This commit is contained in:
Arthur Hung
2021-03-19 06:16:20 +00:00
committed by Android (Google) Code Review
7 changed files with 124 additions and 88 deletions

View File

@@ -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);
}
/**

View File

@@ -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.

View File

@@ -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() {

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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");

View File

@@ -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();
});