Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1381cac2 authored by Chris Tate's avatar Chris Tate Committed by Android (Google) Code Review
Browse files

Merge "Report drag success/fail in the DRAG_ENDED message"

parents c5152cad d4533f14
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -190770,6 +190770,17 @@
 visibility="public"
>
</method>
<method name="getResult"
 return="boolean"
 abstract="false"
 native="false"
 synchronized="false"
 static="false"
 final="false"
 deprecated="not deprecated"
 visibility="public"
>
</method>
<method name="getX"
 return="float"
 abstract="false"
@@ -190812,6 +190823,8 @@
</parameter>
<parameter name="data" type="android.content.ClipData">
</parameter>
<parameter name="result" type="boolean">
</parameter>
</method>
<method name="obtain"
 return="android.view.DragEvent"
+16 −7
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ public class DragEvent implements Parcelable {
    float mX, mY;
    ClipDescription mClipDescription;
    ClipData mClipData;
    boolean mDragResult;

    private DragEvent mNext;
    private RuntimeException mRecycledLocation;
@@ -53,25 +54,27 @@ public class DragEvent implements Parcelable {
    private DragEvent() {
    }

    private void init(int action, float x, float y, ClipDescription description, ClipData data) {
    private void init(int action, float x, float y, ClipDescription description, ClipData data,
            boolean result) {
        mAction = action;
        mX = x;
        mY = y;
        mClipDescription = description;
        mClipData = data;
        mDragResult = result;
    }

    static DragEvent obtain() {
        return DragEvent.obtain(0, 0f, 0f, null, null);
        return DragEvent.obtain(0, 0f, 0f, null, null, false);
    }

    public static DragEvent obtain(int action, float x, float y,
            ClipDescription description, ClipData data) {
            ClipDescription description, ClipData data, boolean result) {
        final DragEvent ev;
        synchronized (gRecyclerLock) {
            if (gRecyclerTop == null) {
                ev = new DragEvent();
                ev.init(action, x, y, description, data);
                ev.init(action, x, y, description, data, result);
                return ev;
            }
            ev = gRecyclerTop;
@@ -82,14 +85,14 @@ public class DragEvent implements Parcelable {
        ev.mRecycled = false;
        ev.mNext = null;

        ev.init(action, x, y, description, data);
        ev.init(action, x, y, description, data, result);

        return ev;
    }

    public static DragEvent obtain(DragEvent source) {
        return obtain(source.mAction, source.mX, source.mY,
                source.mClipDescription, source.mClipData);
                source.mClipDescription, source.mClipData, source.mDragResult);
    }

    public int getAction() {
@@ -112,6 +115,10 @@ public class DragEvent implements Parcelable {
        return mClipDescription;
    }

    public boolean getResult() {
        return mDragResult;
    }

    /**
     * Recycle the DragEvent, to be re-used by a later caller.  After calling
     * this function you must never touch the event again.
@@ -146,7 +153,7 @@ public class DragEvent implements Parcelable {
    public String toString() {
        return "DragEvent{" + Integer.toHexString(System.identityHashCode(this))
        + " action=" + mAction + " @ (" + mX + ", " + mY + ") desc=" + mClipDescription
        + " data=" + mClipData
        + " data=" + mClipData + " result=" + mDragResult
        + "}";
    }

@@ -160,6 +167,7 @@ public class DragEvent implements Parcelable {
        dest.writeInt(mAction);
        dest.writeFloat(mX);
        dest.writeFloat(mY);
        dest.writeInt(mDragResult ? 1 : 0);
        if (mClipData == null) {
            dest.writeInt(0);
        } else {
@@ -181,6 +189,7 @@ public class DragEvent implements Parcelable {
            event.mAction = in.readInt();
            event.mX = in.readFloat();
            event.mY = in.readFloat();
            event.mDragResult = (in.readInt() != 0);
            if (in.readInt() != 0) {
                event.mClipData = ClipData.CREATOR.createFromParcel(in);
            }
+7 −0
Original line number Diff line number Diff line
@@ -130,6 +130,13 @@ interface IWindowSession {
    boolean performDrag(IWindow window, IBinder dragToken, float touchX, float touchY,
            float thumbCenterX, float thumbCenterY, in ClipData data);

	/**
	 * Report the result of a drop action targeted to the given window.
	 * consumed is 'true' when the drop was accepted by a valid recipient,
	 * 'false' otherwise.
	 */
	void reportDropResult(IWindow window, boolean consumed);

    /**
     * Tell the OS that we've just dragged into a View that is willing to accept the drop
     */
+11 −1
Original line number Diff line number Diff line
@@ -2506,7 +2506,7 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
                final View prevDragView = mCurrentDragView;

                // Now dispatch the drag/drop event
                mView.dispatchDragEvent(event);
                boolean result = mView.dispatchDragEvent(event);

                // If we changed apparent drag target, tell the OS about it
                if (prevDragView != mCurrentDragView) {
@@ -2521,6 +2521,16 @@ public final class ViewRoot extends Handler implements ViewParent, View.AttachIn
                        Slog.e(TAG, "Unable to note drag target change");
                    }
                }

                // Report the drop result if necessary
                if (what == DragEvent.ACTION_DROP) {
                    try {
                        Log.i(TAG, "Reporting drop result: " + result);
                        sWindowSession.reportDropResult(mWindow, result);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Unable to report drop result");
                    }
                }
            }
        }
        event.recycle();
+106 −42
Original line number Diff line number Diff line
@@ -501,6 +501,7 @@ public class WindowManagerService extends IWindowManager.Stub
        boolean mLocalOnly;
        ClipData mData;
        ClipDescription mDataDescription;
        boolean mDragResult;
        float mCurrentX, mCurrentY;
        float mThumbOffsetX, mThumbOffsetY;
        InputChannel mServerChannel, mClientChannel;
@@ -594,7 +595,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (mDragInProgress && newWin.isPotentialDragTarget()) {
                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
                        touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
                        desc, null);
                        desc, null, false);
                try {
                    newWin.mClient.dispatchDragEvent(event);
                    // track each window that we've notified that the drag is starting
@@ -629,12 +630,12 @@ public class WindowManagerService extends IWindowManager.Stub
            }
        }

        void broadcastDragEnded() {
        void broadcastDragEndedLw() {
            if (DEBUG_DRAG) {
                Slog.d(TAG, "broadcasting DRAG_ENDED");
            }
            DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, 0, 0, null, null);
            synchronized (mWindowMap) {
            DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
                    0, 0, null, null, mDragResult);
            for (WindowState ws: mNotifiedWindows) {
                try {
                    ws.mClient.dispatchDragEvent(evt);
@@ -644,10 +645,21 @@ public class WindowManagerService extends IWindowManager.Stub
            }
            mNotifiedWindows.clear();
            mDragInProgress = false;
            }
            evt.recycle();
        }

        void endDragLw() {
            mDragState.broadcastDragEndedLw();

            // stop intercepting input
            mDragState.unregister();
            mInputMonitor.updateInputWindowsLw();

            // free our resources and drop all the object references
            mDragState.reset();
            mDragState = null;
        }

        void notifyMoveLw(float x, float y) {
            final int myPid = Process.myPid();

@@ -667,7 +679,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    // force DRAG_EXITED_EVENT if appropriate
                    DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
                            x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
                            null, null);
                            null, null, false);
                    mTargetWindow.mClient.dispatchDragEvent(evt);
                    if (myPid != mTargetWindow.mSession.mPid) {
                        evt.recycle();
@@ -679,7 +691,7 @@ public class WindowManagerService extends IWindowManager.Stub
                    }
                    DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
                            x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
                            null, null);
                            null, null, false);
                    touchedWin.mClient.dispatchDragEvent(evt);
                    if (myPid != touchedWin.mSession.mPid) {
                        evt.recycle();
@@ -691,26 +703,43 @@ public class WindowManagerService extends IWindowManager.Stub
            mTargetWindow = touchedWin;
        }

        // Tell the drop target about the data, and then broadcast the drag-ended notification
        void notifyDropLw(float x, float y) {
        // Tell the drop target about the data.  Returns 'true' if we can immediately
        // dispatch the global drag-ended message, 'false' if we need to wait for a
        // result from the recipient.
        boolean notifyDropLw(float x, float y) {
            WindowState touchedWin = getTouchedWinAtPointLw(x, y);
            if (touchedWin != null) {
            if (touchedWin == null) {
                // "drop" outside a valid window -- no recipient to apply a
                // timeout to, and we can send the drag-ended message immediately.
                mDragResult = false;
                return true;
            }

            if (DEBUG_DRAG) {
                Slog.d(TAG, "sending DROP to " + touchedWin);
            }
            final int myPid = Process.myPid();
            final IBinder token = touchedWin.mClient.asBinder();
            DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
                    x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
                        null, mData);
                    null, mData, false);
            try {
                touchedWin.mClient.dispatchDragEvent(evt);

                // 5 second timeout for this window to respond to the drop
                mH.removeMessages(H.DRAG_END_TIMEOUT, token);
                Message msg = mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
                mH.sendMessageDelayed(msg, 5000);
            } catch (RemoteException e) {
                Slog.w(TAG, "can't send drop notification to win " + touchedWin);
                }
                return true;
            } finally {
                if (myPid != touchedWin.mSession.mPid) {
                    evt.recycle();
                }
            }
            mToken = token;
            return false;
        }

        // Find the visible, touch-deliverable window under the given point
@@ -794,9 +823,8 @@ public class WindowManagerService extends IWindowManager.Stub
                        if (DEBUG_DRAG) Slog.d(TAG, "Got UP on move channel; dropping at "
                                + newX + "," + newY);
                        synchronized (mWindowMap) {
                            mDragState.notifyDropLw(newX, newY);
                            endDrag = mDragState.notifyDropLw(newX, newY);
                        }
                        endDrag = true;
                    } break;

                    case MotionEvent.ACTION_CANCEL: {
@@ -808,17 +836,9 @@ public class WindowManagerService extends IWindowManager.Stub
                    if (endDrag) {
                        if (DEBUG_DRAG) Slog.d(TAG, "Drag ended; tearing down state");
                        // tell all the windows that the drag has ended
                        mDragState.broadcastDragEnded();

                        // stop intercepting input
                        mDragState.unregister();
                        synchronized (mWindowMap) {
                            mInputMonitor.updateInputWindowsLw();
                            mDragState.endDragLw();
                        }

                        // free our resources and drop all the object references
                        mDragState.reset();
                        mDragState = null;
                    }
                }
            } catch (Exception e) {
@@ -6251,15 +6271,43 @@ public class WindowManagerService extends IWindowManager.Stub
            return true;    // success!
        }

        public void reportDropResult(IWindow window, boolean consumed) {
            IBinder token = window.asBinder();
            if (DEBUG_DRAG) {
                Slog.d(TAG, "Drop result=" + consumed + " reported by " + token);
            }

            synchronized (mWindowMap) {
                if (mDragState.mToken != token) {
                    Slog.w(TAG, "Invalid drop-result claim by " + window);
                    throw new IllegalStateException("reportDropResult() by non-recipient");
                }

                // The right window has responded, even if it's no longer around,
                // so be sure to halt the timeout even if the later WindowState
                // lookup fails.
                mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());

                WindowState callingWin = windowForClientLocked(null, window, false);
                if (callingWin == null) {
                    Slog.w(TAG, "Bad result-reporting window " + window);
                    return;  // !!! TODO: throw here?
                }

                mDragState.mDragResult = consumed;
                mDragState.endDragLw();
            }
        }

        public void dragRecipientEntered(IWindow window) {
            if (DEBUG_DRAG) {
                Slog.d(TAG, "Drag into new candidate view @ " + window);
                Slog.d(TAG, "Drag into new candidate view @ " + window.asBinder());
            }
        }

        public void dragRecipientExited(IWindow window) {
            if (DEBUG_DRAG) {
                Slog.d(TAG, "Drag from old candidate view @ " + window);
                Slog.d(TAG, "Drag from old candidate view @ " + window.asBinder());
            }
        }

@@ -8321,6 +8369,7 @@ public class WindowManagerService extends IWindowManager.Stub
        public static final int SEND_NEW_CONFIGURATION = 18;
        public static final int REPORT_WINDOWS_CHANGE = 19;
        public static final int DRAG_START_TIMEOUT = 20;
        public static final int DRAG_END_TIMEOUT = 21;

        private Session mLastReportedHold;

@@ -8671,12 +8720,27 @@ public class WindowManagerService extends IWindowManager.Stub
                    synchronized (mWindowMap) {
                        // !!! TODO: ANR the app that has failed to start the drag in time
                        if (mDragState != null) {
                            mDragState.unregister();
                            mInputMonitor.updateInputWindowsLw();
                            mDragState.reset();
                            mDragState = null;
                        }
                    }
                    break;
                }

                case DRAG_END_TIMEOUT: {
                    IBinder win = (IBinder)msg.obj;
                    if (DEBUG_DRAG) {
                        Slog.w(TAG, "Timeout ending drag to win " + win);
                    }
                    synchronized (mWindowMap) {
                        // !!! TODO: ANR the drag-receiving app
                        mDragState.mDragResult = false;
                        mDragState.endDragLw();
                    }
                    break;
                }
            }
        }
    }
Loading