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

Commit fabca09f authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Remove DragDropController#prepareDrag()

The prepareDrag() call is used by apps to ask the system server to
create a surface for drag shadow. Now the app creates a surface by
itself, thus we can reduce the method.

Bug: 70818582
Test: com.android.server.wm.DragDropControllerTests,
      android.server.wm.CrossAppDragAndDropTests,
      manually check the drag and drop behavior on test app.
Change-Id: Iae4acbff4f9ad68faa6324beb32bf9a28dcd67be
parent a1fb9be4
Loading
Loading
Loading
Loading
+18 −11
Original line number Diff line number Diff line
@@ -150,19 +150,26 @@ interface IWindowSession {

    boolean performHapticFeedback(IWindow window, int effectId, boolean always);

    /**
     * Allocate the drag's thumbnail surface.  Also assigns a token that identifies
     * the drag to the OS and passes that as the return value.  A return value of
     * null indicates failure.
     */
    IBinder prepareDrag(IWindow window, int flags, int thumbnailWidth, int thumbnailHeight);

    /**
     * Initiate the drag operation itself
     */
    boolean performDrag(IWindow window, IBinder dragToken, in SurfaceControl surface,
            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
            in ClipData data);
     *
     * @param window Window which initiates drag operation.
     * @param flags See {@code View#startDragAndDrop}
     * @param surface Surface containing drag shadow image
     * @param touchSource See {@code InputDevice#getSource()}
     * @param touchX TODO (b/72072998): Fix the issue that the system server misuse the arguments as
     *         initial touch point while the framework passes drag shadow size.
     * @param touchY TODO (b/72072998): Fix the issue that the system server misuse the arguments as
     *         initial touch point while the framework passes drag shadow size.
     * @param thumbCenterX X coordinate for the position within the shadow image that should be
     *         underneath the touch point during the drag and drop operation.
     * @param thumbCenterY Y coordinate for the position within the shadow image that should be
     *         underneath the touch point during the drag and drop operation.
     * @param data Data transferred by drag and drop
     * @return Token of drag operation which will be passed to cancelDragAndDrop.
     */
    IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource,
            float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data);

    /**
     * Report the result of a drop action targeted to the given window.
+31 −33
Original line number Diff line number Diff line
@@ -23496,8 +23496,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0);
        }
        boolean okay = false;
        Point shadowSize = new Point();
        Point shadowTouchPoint = new Point();
        shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
@@ -23515,20 +23513,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            mAttachInfo.mDragSurface.release();
        }
        mAttachInfo.mDragSurface = new Surface();
        mAttachInfo.mDragToken = null;
        final ViewRootImpl root = mAttachInfo.mViewRootImpl;
        final SurfaceSession session = new SurfaceSession(root.mSurface);
        try {
            mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
                    flags, shadowSize.x, shadowSize.y);
            if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token="
                    + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface);
            if (mAttachInfo.mDragToken != null) {
        final SurfaceControl surface = new SurfaceControl.Builder(session)
                .setName("drag surface")
                .setSize(shadowSize.x, shadowSize.y)
                .setFormat(PixelFormat.TRANSLUCENT)
                .build();
        try {
            mAttachInfo.mDragSurface.copyFrom(surface);
            final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
            try {
@@ -23544,21 +23538,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
            // repurpose 'shadowSize' for the last touch point
            root.getLastTouchPoint(shadowSize);
                okay = mAttachInfo.mSession.performDrag(
                        mAttachInfo.mWindow, mAttachInfo.mDragToken, surface,
                        root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x,
                        shadowTouchPoint.y, data);
                if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
            mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag(
                    mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(),
                    shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data);
            if (ViewDebug.DEBUG_DRAG) {
                Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken);
            }
            return mAttachInfo.mDragToken != null;
        } catch (Exception e) {
            Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
            return false;
        } finally {
            if (mAttachInfo.mDragToken == null) {
                mAttachInfo.mDragSurface.destroy();
                mAttachInfo.mDragSurface = null;
        } finally {
                root.setLocalDragState(null);
            }
            session.kill();
        }
        return okay;
    }
    /**
+32 −74
Original line number Diff line number Diff line
@@ -48,10 +48,9 @@ class DragDropController {
    private static final long DRAG_TIMEOUT_MS = 5000;

    // Messages for Handler.
    private static final int MSG_DRAG_START_TIMEOUT = 0;
    static final int MSG_DRAG_END_TIMEOUT = 1;
    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2;
    static final int MSG_ANIMATION_END = 3;
    static final int MSG_DRAG_END_TIMEOUT = 0;
    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1;
    static final int MSG_ANIMATION_END = 2;

    /**
     * Drag state per operation.
@@ -93,72 +92,35 @@ class DragDropController {
        mDragState.sendDragStartedIfNeededLocked(window);
    }

    IBinder prepareDrag(SurfaceSession session, int callerPid,
            int callerUid, IWindow window, int flags, int width, int height) {
    IBinder performDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window,
            int flags, SurfaceControl surface, int touchSource, float touchX, float touchY,
            float thumbCenterX, float thumbCenterY, ClipData data) {
        if (DEBUG_DRAG) {
            Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
                    + " flags=" + Integer.toHexString(flags) + " win=" + window
                    + " asbinder=" + window.asBinder());
        }

        if (width <= 0 || height <= 0) {
            Slog.w(TAG_WM, "width and height of drag shadow must be positive");
            return null;
        }

        synchronized (mService.mWindowMap) {
            if (dragDropActiveLocked()) {
                Slog.w(TAG_WM, "Drag already in progress");
                return null;
            }

            // TODO(multi-display): support other displays
            float alpha = 1;
            if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
                alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
            }
            final IBinder winBinder = window.asBinder();
            IBinder token = new Binder();
            mDragState = new DragState(mService, this, token, /* surface */ null, flags, winBinder);
            mDragState.mPid = callerPid;
            mDragState.mUid = callerUid;
            mDragState.mOriginalAlpha = alpha;
            token = mDragState.mToken = new Binder();

            // 5 second timeout for this window to actually begin the drag
            sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder);
            return token;
        }
    }

    boolean performDrag(SurfaceSession session, IWindow window, IBinder dragToken,
            SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX,
            float thumbCenterY, ClipData data) {
        if (DEBUG_DRAG) {
            Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
            Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" +
                            Integer.toHexString(flags) + " data=" + data);
        }

        final IBinder dragToken = new Binder();
        final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken,
                touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
        try {
            synchronized (mService.mWindowMap) {
                mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder());
                try {
                    if (!callbackResult) {
                        return false;
                        Slog.w(TAG_WM, "IDragDropCallback rejects the performDrag request");
                        return null;
                    }

                    Preconditions.checkState(
                            mDragState != null, "performDrag() without prepareDrag()");
                    Preconditions.checkState(
                            mDragState.mToken == dragToken,
                            "performDrag() does not match prepareDrag()");
                    if (dragDropActiveLocked()) {
                        Slog.w(TAG_WM, "Drag already in progress");
                        return null;
                    }

                    final WindowState callingWin = mService.windowForClientLocked(
                            null, window, false);
                    if (callingWin == null) {
                        Slog.w(TAG_WM, "Bad requesting window " + window);
                        return false;  // !!! TODO: throw here?
                        return null;  // !!! TODO: throw here?
                    }

                    // !!! TODO: if input is not still focused on the initiating window, fail
@@ -171,22 +133,33 @@ class DragDropController {
                    // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as
                    // the actual drag event dispatch stuff in the dragstate

                    // !!! TODO(multi-display): support other displays

                    final DisplayContent displayContent = callingWin.getDisplayContent();
                    if (displayContent == null) {
                        Slog.w(TAG_WM, "display content is null");
                        return false;
                        return null;
                    }

                    final float alpha = (flags & View.DRAG_FLAG_OPAQUE) == 0 ?
                            DRAG_SHADOW_ALPHA_TRANSPARENT : 1;
                    final IBinder winBinder = window.asBinder();
                    IBinder token = new Binder();
                    mDragState = new DragState(mService, this, token, surface, flags, winBinder);
                    surface = null;
                    mDragState.mPid = callerPid;
                    mDragState.mUid = callerUid;
                    mDragState.mOriginalAlpha = alpha;
                    mDragState.mToken = dragToken;

                    final Display display = displayContent.getDisplay();
                    mDragState.register(display);
                    if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                            mDragState.getInputChannel())) {
                        Slog.e(TAG_WM, "Unable to transfer touch focus");
                        return false;
                        return null;
                    }

                    mDragState.mSurfaceControl = surface;
                    surface = null;
                    mDragState.mDisplayContent = displayContent;
                    mDragState.mData = data;
                    mDragState.broadcastDragStartedLocked(touchX, touchY);
@@ -222,7 +195,7 @@ class DragDropController {
                    }
                }
            }
            return true;    // success!
            return dragToken;    // success!
        } finally {
            mCallback.get().postPerformDrag();
        }
@@ -373,21 +346,6 @@ class DragDropController {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_DRAG_START_TIMEOUT: {
                    IBinder win = (IBinder) msg.obj;
                    if (DEBUG_DRAG) {
                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
                    }

                    synchronized (mService.mWindowMap) {
                        // !!! TODO: ANR the app that has failed to start the drag in time
                        if (mDragState != null) {
                            mDragState.closeLocked();
                        }
                    }
                    break;
                }

                case MSG_DRAG_END_TIMEOUT: {
                    final IBinder win = (IBinder) msg.obj;
                    if (DEBUG_DRAG) {
+5 −11
Original line number Diff line number Diff line
@@ -309,27 +309,21 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
    }

    /* Drag/drop */

    @Override
    public IBinder prepareDrag(IWindow window, int flags, int width, int height) {
    public IBinder performDrag(IWindow window, int flags, SurfaceControl surface, int touchSource,
            float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) {
        final int callerPid = Binder.getCallingPid();
        final int callerUid = Binder.getCallingUid();
        final long ident = Binder.clearCallingIdentity();
        try {
            return mDragDropController.prepareDrag(mSurfaceSession, callerPid, callerUid, window,
                    flags, width, height);
            return mDragDropController.performDrag(mSurfaceSession, callerPid, callerUid, window,
                    flags, surface, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }

    @Override
    public boolean performDrag(IWindow window, IBinder dragToken, SurfaceControl surface,
            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
            ClipData data) {
        return mDragDropController.performDrag(mSurfaceSession, window, dragToken, surface,
                touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data);
    }

    @Override
    public void reportDropResult(IWindow window, boolean consumed) {
        final long ident = Binder.clearCallingIdentity();
+4 −12
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
@@ -37,7 +36,6 @@ import android.platform.test.annotations.Presubmit;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.view.InputChannel;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
@@ -147,12 +145,6 @@ public class DragDropControllerTests extends WindowTestsBase {
        dragFlow(0, ClipData.newPlainText("label", "Test"), 0, 0);
    }

    @Test
    public void testPrepareDrag_ZeroSizeSurface() throws Exception {
        mToken = mTarget.prepareDrag(new SurfaceSession(), 0, 0, mWindow.mClient, 0, 0, 0);
        assertNull(mToken);
    }

    @Test
    public void testPerformDrag_NullDataWithGrantUri() throws Exception {
        dragFlow(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_GLOBAL_URI_READ, null, 0, 0);
@@ -169,8 +161,6 @@ public class DragDropControllerTests extends WindowTestsBase {
    }

    private void dragFlow(int flag, ClipData data, float dropX, float dropY) {
        mToken = mTarget.prepareDrag(new SurfaceSession(), 0, 0, mWindow.mClient, flag, 100, 100);
        assertNotNull(mToken);
        final SurfaceSession appSession = new SurfaceSession();
        try {
            final SurfaceControl surface = new SurfaceControl.Builder(appSession)
@@ -180,8 +170,10 @@ public class DragDropControllerTests extends WindowTestsBase {
                    .build();

            assertTrue(sWm.mInputManager.transferTouchFocus(null, null));
            assertNotNull(mTarget.performDrag(
                    new SurfaceSession(), mWindow.mClient, mToken, surface, 0, 0, 0, 0, 0, data));
            mToken = mTarget.performDrag(
                    new SurfaceSession(), 0, 0, mWindow.mClient, flag, surface, 0, 0, 0, 0, 0,
                    data);
            assertNotNull(mToken);

            mTarget.handleMotionEvent(false, dropX, dropY);
            mToken = mWindow.mClient.asBinder();