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

Commit 571074be authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Stop resetting app drag drop state when startDrag is invoked twice.

Before P, if startDragAndDrop is invoked twice, the system goes to wired state
where:

 * the system server keeps processing the first drag operation.
 * the application loses the drag token but keeps the user local state.
 * cancelDrag() no longer cancels the ongoing operation.
 * DragEvents are still delivered with the user local state.

At P we unintentionally changed the behavior to:

 * the system server keeps processing the first drag operation.
 * the application loses the drag token and the user local state.
 * cancelDrag() no longer cancels the ongoing operation.
 * DragEvents are still delivered without the user local state.

The CL fixed the behavior so that the second startDragAndDrop() calls
does not affect the internal state of drag and drop as it's failed due
to existing ongoing operation.

 * the system server keeps processing the first drag operation.
 * the application keeps the drag token and the user local state.
 * cancelDrag() is still able to cancel the ongoing operation.
 * DragEvents are still delivered with the user local state.

Bug: 113310888
Test: Manually invoke startDragAndDrop() and ensures the user local
      state delivered with DragEvents is not cleared.

Change-Id: I0a8315a44d655a8a73b7034f340e50e2f50601a8
parent 3a6c71c1
Loading
Loading
Loading
Loading
+22 −22
Original line number Original line Diff line number Diff line
@@ -24173,7 +24173,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *     </ul>
     *     </ul>
     * @return {@code true} if the method completes successfully, or
     * @return {@code true} if the method completes successfully, or
     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
     * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
     * do a drag, and so no drag operation is in progress.
     * do a drag because of another ongoing operation or some other reasons.
     */
     */
    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
    public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
            Object myLocalState, int flags) {
            Object myLocalState, int flags) {
@@ -24216,51 +24216,51 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
            Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
                    + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
        }
        }
        if (mAttachInfo.mDragSurface != null) {
            mAttachInfo.mDragSurface.release();
        }
        mAttachInfo.mDragSurface = new Surface();
        mAttachInfo.mDragToken = null;
        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
        final SurfaceSession session = new SurfaceSession(root.mSurface);
        final SurfaceSession session = new SurfaceSession(root.mSurface);
        final SurfaceControl surface = new SurfaceControl.Builder(session)
        final SurfaceControl surfaceControl = new SurfaceControl.Builder(session)
                .setName("drag surface")
                .setName("drag surface")
                .setSize(shadowSize.x, shadowSize.y)
                .setSize(shadowSize.x, shadowSize.y)
                .setFormat(PixelFormat.TRANSLUCENT)
                .setFormat(PixelFormat.TRANSLUCENT)
                .build();
                .build();
        final Surface surface = new Surface();
        surface.copyFrom(surfaceControl);
        IBinder token = null;
        try {
        try {
            mAttachInfo.mDragSurface.copyFrom(surface);
            final Canvas canvas = surface.lockCanvas(null);
            final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
            try {
            try {
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                canvas.drawColor(0, PorterDuff.Mode.CLEAR);
                shadowBuilder.onDrawShadow(canvas);
                shadowBuilder.onDrawShadow(canvas);
            } finally {
            } finally {
                mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas);
                surface.unlockCanvasAndPost(canvas);
            }
            }
            // Cache the local state object for delivery with DragEvents
            root.setLocalDragState(myLocalState);
            // repurpose 'shadowSize' for the last touch point
            // repurpose 'shadowSize' for the last touch point
            root.getLastTouchPoint(shadowSize);
            root.getLastTouchPoint(shadowSize);
            mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
            token = mAttachInfo.mSession.performDrag(
                    mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
                    mAttachInfo.mWindow, flags, surfaceControl, root.getLastTouchSource(),
                    shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
                    shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
            if (ViewDebug.DEBUG_DRAG) {
            if (ViewDebug.DEBUG_DRAG) {
                Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
                Log.d(VIEW_LOG_TAG, "performDrag returned " + token);
            }
            }
            if (token != null) {
            return mAttachInfo.mDragToken != null;
                if (mAttachInfo.mDragSurface != null) {
                    mAttachInfo.mDragSurface.release();
                }
                mAttachInfo.mDragSurface = surface;
                mAttachInfo.mDragToken = token;
                // Cache the local state object for delivery with DragEvents
                root.setLocalDragState(myLocalState);
            }
            return token != null;
        } catch (Exception e) {
        } catch (Exception e) {
            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
            return false;
            return false;
        } finally {
        } finally {
            if (mAttachInfo.mDragToken == null) {
            if (token == null) {
                mAttachInfo.mDragSurface.destroy();
                surface.destroy();
                mAttachInfo.mDragSurface = null;
                root.setLocalDragState(null);
            }
            }
            session.kill();
            session.kill();
        }
        }