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

Commit 76a26aaa authored by Daichi Hirono's avatar Daichi Hirono
Browse files

Move mDragState from WindowManagerService to DragDropController

Bug: 65564090
Test: android.server.wm.CrossAppDragAndDropTests, manually check the drag
      and drop behavior on test app.
Change-Id: I2445ccff6e2cfd673c47f591ac88f3f60a7a6ddc
parent 1b3cf5a4
Loading
Loading
Loading
Loading
+71 −80
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.server.wm;

import static android.graphics.PixelFormat.TRANSLUCENT;
import static android.view.SurfaceControl.HIDDEN;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -26,14 +24,12 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.content.ClipData;
import android.graphics.PixelFormat;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Slog;
import android.view.Display;
import android.view.IWindow;
import android.view.Surface;
import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.View;
@@ -45,6 +41,11 @@ import com.android.server.wm.WindowManagerService.H;
class DragDropController {
    private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
    private static final long DRAG_TIMEOUT_MS = 5000;
    DragState mDragState;

    boolean dragDropActiveLocked() {
        return mDragState != null;
    }

    IBinder prepareDrag(WindowManagerService service, SurfaceSession session, int callerPid,
            int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
@@ -57,8 +58,11 @@ class DragDropController {
        IBinder token = null;

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

            // TODO(multi-display): support other displays
            final DisplayContent displayContent =
                    service.getDefaultDisplayContentLocked();
@@ -76,33 +80,20 @@ class DragDropController {
            }
            surface.setAlpha(alpha);

                    if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
                            + surface + ": CREATE");
            if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG " + surface + ": CREATE");
            outSurface.copyFrom(surface);
            final IBinder winBinder = window.asBinder();
            token = new Binder();
                    service.mDragState =
                            new DragState(service, token, surface, flags, winBinder);
                    service.mDragState.mPid = callerPid;
                    service.mDragState.mUid = callerUid;
                    service.mDragState.mOriginalAlpha = alpha;
                    token = service.mDragState.mToken = new Binder();
            mDragState = new DragState(service, token, surface, 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
            service.mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
            Message msg = service.mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
            service.mH.sendMessageDelayed(msg, DRAG_TIMEOUT_MS);
                } else {
                    Slog.w(TAG_WM, "Drag already in progress");
                }
            } catch (OutOfResourcesException e) {
                Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height,
                        e);
                if (service.mDragState != null) {
                    service.mDragState.reset();
                    service.mDragState = null;
                }
            }
        }

        return token;
@@ -116,12 +107,12 @@ class DragDropController {
        }

        synchronized (service.mWindowMap) {
            if (service.mDragState == null) {
            if (mDragState == null) {
                Slog.w(TAG_WM, "No drag prepared");
                throw new IllegalStateException("performDrag() without prepareDrag()");
            }

            if (dragToken != service.mDragState.mToken) {
            if (dragToken != mDragState.mToken) {
                Slog.w(TAG_WM, "Performing mismatched drag");
                throw new IllegalStateException("performDrag() does not match prepareDrag()");
            }
@@ -149,34 +140,34 @@ class DragDropController {
                return false;
            }
            Display display = displayContent.getDisplay();
            service.mDragState.register(display);
            mDragState.register(display);
            if (!service.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                    service.mDragState.getInputChannel())) {
                    mDragState.getInputChannel())) {
                Slog.e(TAG_WM, "Unable to transfer touch focus");
                service.mDragState.unregister();
                service.mDragState.reset();
                service.mDragState = null;
                mDragState.unregister();
                mDragState.reset();
                mDragState = null;
                return false;
            }

            service.mDragState.mDisplayContent = displayContent;
            service.mDragState.mData = data;
            service.mDragState.broadcastDragStartedLw(touchX, touchY);
            service.mDragState.overridePointerIconLw(touchSource);
            mDragState.mDisplayContent = displayContent;
            mDragState.mData = data;
            mDragState.broadcastDragStartedLw(touchX, touchY);
            mDragState.overridePointerIconLw(touchSource);

            // remember the thumb offsets for later
            service.mDragState.mThumbOffsetX = thumbCenterX;
            service.mDragState.mThumbOffsetY = thumbCenterY;
            mDragState.mThumbOffsetX = thumbCenterX;
            mDragState.mThumbOffsetY = thumbCenterY;

            // Make the surface visible at the proper location
            final SurfaceControl surfaceControl = service.mDragState.mSurfaceControl;
            final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
            if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
                    TAG_WM, ">>> OPEN TRANSACTION performDrag");
            service.openSurfaceTransaction();
            try {
                surfaceControl.setPosition(touchX - thumbCenterX,
                        touchY - thumbCenterY);
                surfaceControl.setLayer(service.mDragState.getDragLayerLw());
                surfaceControl.setLayer(mDragState.getDragLayerLw());
                surfaceControl.setLayerStack(display.getLayerStack());
                surfaceControl.show();
            } finally {
@@ -185,7 +176,7 @@ class DragDropController {
                        TAG_WM, "<<< CLOSE TRANSACTION performDrag");
            }

            service.mDragState.notifyLocationLw(touchX, touchY);
            mDragState.notifyLocationLw(touchX, touchY);
        }

        return true;    // success!
@@ -198,14 +189,14 @@ class DragDropController {
        }

        synchronized (service.mWindowMap) {
            if (service.mDragState == null) {
            if (mDragState == null) {
                // Most likely the drop recipient ANRed and we ended the drag
                // out from under it.  Log the issue and move on.
                Slog.w(TAG_WM, "Drop result given but no drag in progress");
                return;
            }

            if (service.mDragState.mToken != token) {
            if (mDragState.mToken != token) {
                // We're in a drag, but the wrong window has responded.
                Slog.w(TAG_WM, "Invalid drop-result claim by " + window);
                throw new IllegalStateException("reportDropResult() by non-recipient");
@@ -221,8 +212,8 @@ class DragDropController {
                return;  // !!! TODO: throw here?
            }

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

@@ -232,20 +223,20 @@ class DragDropController {
        }

        synchronized (service.mWindowMap) {
            if (service.mDragState == null) {
            if (mDragState == null) {
                Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
                throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
            }

            if (service.mDragState.mToken != dragToken) {
            if (mDragState.mToken != dragToken) {
                Slog.w(TAG_WM,
                        "cancelDragAndDrop() does not match prepareDrag()");
                throw new IllegalStateException(
                        "cancelDragAndDrop() does not match prepareDrag()");
            }

            service.mDragState.mDragResult = false;
            service.mDragState.cancelDragLw();
            mDragState.mDragResult = false;
            mDragState.cancelDragLw();
        }
    }

@@ -270,10 +261,10 @@ class DragDropController {
                }
                synchronized (service.mWindowMap) {
                    // !!! TODO: ANR the app that has failed to start the drag in time
                    if (service.mDragState != null) {
                        service.mDragState.unregister();
                        service.mDragState.reset();
                        service.mDragState = null;
                    if (mDragState != null) {
                        mDragState.unregister();
                        mDragState.reset();
                        mDragState = null;
                    }
                }
                break;
@@ -286,9 +277,9 @@ class DragDropController {
                }
                synchronized (service.mWindowMap) {
                    // !!! TODO: ANR the drag-receiving app
                    if (service.mDragState != null) {
                        service.mDragState.mDragResult = false;
                        service.mDragState.endDragLw();
                    if (mDragState != null) {
                        mDragState.mDragResult = false;
                        mDragState.endDragLw();
                    }
                }
                break;
+3 −3
Original line number Diff line number Diff line
@@ -430,7 +430,7 @@ class DragState {
            //    WindowManagerService, which will cause DragState#reset() while playing the
            //    cancel animation.
            reset();
            mService.mDragState = null;
            mService.mDragDropController.mDragState = null;
            return;
        }
        mAnimator = createCancelAnimationLocked();
@@ -447,7 +447,7 @@ class DragState {

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

    void notifyMoveLw(float x, float y) {
@@ -658,7 +658,7 @@ class DragState {
            switch (msg.what) {
                case MSG_ANIMATION_END:
                    synchronized (mService.mWindowMap) {
                        if (mService.mDragState != DragState.this) {
                        if (mService.mDragDropController.mDragState != DragState.this) {
                            Slog.wtf(TAG_WM, "mDragState is updated unexpectedly while " +
                                    "playing animation");
                            return;
+4 −3
Original line number Diff line number Diff line
@@ -367,12 +367,13 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
        // currently has touch focus.

        // If there's a drag in flight, provide a pseudo-window to catch drag input
        final boolean inDrag = (mService.mDragState != null);
        final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
        if (inDrag) {
            if (DEBUG_DRAG) {
                Log.d(TAG_WM, "Inserting drag window");
            }
            final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
            final InputWindowHandle dragWindowHandle =
                    mService.mDragDropController.mDragState.getInputWindowHandle();
            if (dragWindowHandle != null) {
                addInputWindowHandle(dragWindowHandle);
            } else {
@@ -689,7 +690,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
            // If there's a drag in progress and 'child' is a potential drop target,
            // make sure it's been told about the drag
            if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
                mService.mDragState.sendDragStartedIfNeededLw(w);
                mService.mDragDropController.mDragState.sendDragStartedIfNeededLw(w);
            }

            addInputWindowHandle(
+6 −7
Original line number Diff line number Diff line
@@ -752,7 +752,6 @@ public class WindowManagerService extends IWindowManager.Stub

    TaskPositioner mTaskPositioner;
    final DragDropController mDragDropController = new DragDropController();
    DragState mDragState = null;

    // For frozen screen animations.
    private int mExitAnimId, mEnterAnimId;
@@ -789,7 +788,7 @@ public class WindowManagerService extends IWindowManager.Stub
        public void onInputEvent(InputEvent event, int displayId) {
            boolean handled = false;
            try {
                if (mDragState == null) {
                if (mDragDropController.mDragState == null) {
                    // The drag has ended but the clean-up message has not been processed by
                    // window manager. Drop events that occur after this until window manager
                    // has a chance to clean-up the input handle.
@@ -828,12 +827,12 @@ public class WindowManagerService extends IWindowManager.Stub
                                    + newX + "," + newY);
                            mMuteInput = true;
                            synchronized (mWindowMap) {
                                endDrag = mDragState.notifyDropLw(newX, newY);
                                endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
                            }
                        } else {
                            synchronized (mWindowMap) {
                                // move the surface and tell the involved window(s) where we are
                                mDragState.notifyMoveLw(newX, newY);
                                mDragDropController.mDragState.notifyMoveLw(newX, newY);
                            }
                        }
                    } break;
@@ -843,7 +842,7 @@ public class WindowManagerService extends IWindowManager.Stub
                                + newX + "," + newY);
                        mMuteInput = true;
                        synchronized (mWindowMap) {
                            endDrag = mDragState.notifyDropLw(newX, newY);
                            endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
                        }
                    } break;

@@ -860,7 +859,7 @@ public class WindowManagerService extends IWindowManager.Stub
                        synchronized (mWindowMap) {
                            // endDragLw will post back to looper to dispose the receiver
                            // since we still need the receiver for the last finishInputEvent.
                            mDragState.endDragLw();
                            mDragDropController.mDragState.endDragLw();
                        }
                        mStylusButtonDownAtStart = false;
                        mIsStartEvent = true;
@@ -7171,7 +7170,7 @@ public class WindowManagerService extends IWindowManager.Stub
        }

        synchronized (mWindowMap) {
            if (mDragState != null) {
            if (mDragDropController.mDragState != null) {
                // Drag cursor overrides the app cursor.
                return;
            }