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

Commit e6b8e7cf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add pre/post callback to IDragDropCallback"

parents 29086aca bb28efb6
Loading
Loading
Loading
Loading
+83 −120
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.view.View;
import com.android.internal.util.Preconditions;
import com.android.server.input.InputWindowHandle;
import com.android.server.wm.WindowManagerInternal.IDragDropCallback;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Managing drag and drop operations initiated by View#startDragAndDrop.
@@ -66,43 +67,11 @@ class DragDropController {
    private WindowManagerService mService;
    private final Handler mHandler;

    /**
     * Lock to preserve the order of state updates.
     * The lock is used to process drag and drop state updates in order without having the window
     * manager lock.
     *
     * Suppose DragDropController invokes a callback method A, then processes the following update
     * A'. Same for a callback method B and the following update B'. The callback wants
     * DragDropController to processes the updates in the order of  A' then B'.
     *
     * Without mWriteLock: the following race can happen.
     *
     * 1. Thread a calls A.
     * 2. Thread b calls B.
     * 3. Thread b acquires the window manager lock
     * 4. thread b processes the update B'
     * 5. Thread a acquires the window manager lock
     * 6. thread a processes the update A'
     *
     * With mWriteLock we can ensure the order of A' and B'
     *
     * 1. Thread a acquire mWriteLock
     * 2. Thread a calls A
     * 3. Thread a acquire the window manager lock
     * 4. Thread a processes A'
     * 5. Thread b acquire mWriteLock
     * 6. Thread b calls B
     * 7. Thread b acquire the window manager lock
     * 8. Thread b processes B'
     *
     * Don't acquire the lock while holding the window manager lock, otherwise it causes a deadlock.
     */
    private final Object mWriteLock = new Object();

    /**
     * Callback which is used to sync drag state with the vendor-specific code.
     */
    @NonNull private IDragDropCallback mCallback = new IDragDropCallback() {};
    @NonNull private AtomicReference<IDragDropCallback> mCallback = new AtomicReference<>(
            new IDragDropCallback() {});

    boolean dragDropActiveLocked() {
        return mDragState != null;
@@ -114,9 +83,7 @@ class DragDropController {

    void registerCallback(IDragDropCallback callback) {
        Preconditions.checkNotNull(callback);
        synchronized (mWriteLock) {
            mCallback = callback;
        }
        mCallback.set(callback);
    }

    DragDropController(WindowManagerService service, Looper looper) {
@@ -136,7 +103,6 @@ class DragDropController {
                    + " asbinder=" + window.asBinder());
        }

        synchronized (mWriteLock) {
        synchronized (mService.mWindowMap) {
            if (dragDropActiveLocked()) {
                Slog.w(TAG_WM, "Drag already in progress");
@@ -176,7 +142,6 @@ class DragDropController {
            return token;
        }
    }
    }

    boolean performDrag(IWindow window, IBinder dragToken,
            int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
@@ -185,11 +150,11 @@ class DragDropController {
            Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
        }

        synchronized (mWriteLock) {
            if (!mCallback.performDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX,
        if (!mCallback.get().prePerformDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX,
                thumbCenterY, data)) {
            return false;
        }
        try {
            synchronized (mService.mWindowMap) {
                if (mDragState == null) {
                    Slog.w(TAG_WM, "No drag prepared");
@@ -260,9 +225,10 @@ class DragDropController {

                mDragState.notifyLocationLocked(touchX, touchY);
            }
        }

            return true;    // success!
        } finally {
            mCallback.get().postPerformDrag();
        }
    }

    void reportDropResult(IWindow window, boolean consumed) {
@@ -271,8 +237,8 @@ class DragDropController {
            Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token);
        }

        synchronized (mWriteLock) {
            mCallback.reportDropResult(window, consumed);
        mCallback.get().preReportDropResult(window, consumed);
        try {
            synchronized (mService.mWindowMap) {
                if (mDragState == null) {
                    // Most likely the drop recipient ANRed and we ended the drag
@@ -297,10 +263,11 @@ class DragDropController {
                    return;  // !!! TODO: throw here?
                }


                mDragState.mDragResult = consumed;
                mDragState.endDragLocked();
            }
        } finally {
            mCallback.get().postReportDropResult();
        }
    }

@@ -309,8 +276,8 @@ class DragDropController {
            Slog.d(TAG_WM, "cancelDragAndDrop");
        }

        synchronized (mWriteLock) {
            mCallback.cancelDragAndDrop(dragToken);
        mCallback.get().preCancelDragAndDrop(dragToken);
        try {
            synchronized (mService.mWindowMap) {
                if (mDragState == null) {
                    Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
@@ -327,6 +294,8 @@ class DragDropController {
                mDragState.mDragResult = false;
                mDragState.cancelDragLocked();
            }
        } finally {
            mCallback.get().postCancelDragAndDrop();
        }
    }

@@ -338,7 +307,6 @@ class DragDropController {
     * @param newY Y coordinate value in dp in the screen coordinate
     */
    void handleMotionEvent(boolean keepHandling, float newX, float newY) {
        synchronized (mWriteLock) {
        synchronized (mService.mWindowMap) {
            if (!dragDropActiveLocked()) {
                // The drag has ended but the clean-up message has not been processed by
@@ -354,7 +322,6 @@ class DragDropController {
            }
        }
    }
    }

    void dragRecipientEntered(IWindow window) {
        if (DEBUG_DRAG) {
@@ -414,14 +381,13 @@ class DragDropController {
                    if (DEBUG_DRAG) {
                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
                    }
                    synchronized (mWriteLock) {

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

@@ -430,7 +396,7 @@ class DragDropController {
                    if (DEBUG_DRAG) {
                        Slog.w(TAG_WM, "Timeout ending drag to win " + win);
                    }
                    synchronized (mWriteLock) {

                    synchronized (mService.mWindowMap) {
                        // !!! TODO: ANR the drag-receiving app
                        if (mDragState != null) {
@@ -438,7 +404,6 @@ class DragDropController {
                            mDragState.endDragLocked();
                        }
                    }
                    }
                    break;
                }

@@ -455,7 +420,6 @@ class DragDropController {
                }

                case MSG_ANIMATION_END: {
                    synchronized (mWriteLock) {
                    synchronized (mService.mWindowMap) {
                        if (mDragState == null) {
                            Slog.wtf(TAG_WM, "mDragState unexpectedly became null while " +
@@ -464,7 +428,6 @@ class DragDropController {
                        }
                        mDragState.closeLocked();
                    }
                    }
                    break;
                }
            }
+21 −6
Original line number Diff line number Diff line
@@ -151,23 +151,38 @@ public abstract class WindowManagerInternal {
     */
    public interface IDragDropCallback {
        /**
         * Called when drag operation is started.
         * Called when drag operation is starting.
         */
        default boolean performDrag(IWindow window, IBinder dragToken,
        default boolean prePerformDrag(IWindow window, IBinder dragToken,
                int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
                ClipData data) {
            return true;
        }

        /**
         * Called when drop result is reported.
         * Called when drag operation is started.
         */
        default void postPerformDrag() {}

        /**
         * Called when drop result is being reported.
         */
        default void preReportDropResult(IWindow window, boolean consumed) {}

        /**
         * Called when drop result was reported.
         */
        default void postReportDropResult() {}

        /**
         * Called when drag operation is being cancelled.
         */
        default void reportDropResult(IWindow window, boolean consumed) {}
        default void preCancelDragAndDrop(IBinder dragToken) {}

        /**
         * Called when drag operation is cancelled.
         * Called when drag operation was cancelled.
         */
        default void cancelDragAndDrop(IBinder dragToken) {}
        default void postCancelDragAndDrop() {}
    }

    /**