DragState.java revision 6e1eb76f02ccc9dbc309b938f62d39312da8cafe
16e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn/*
26e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * Copyright (C) 2011 The Android Open Source Project
36e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn *
46e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
56e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * you may not use this file except in compliance with the License.
66e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * You may obtain a copy of the License at
76e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn *
86e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
96e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn *
106e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * Unless required by applicable law or agreed to in writing, software
116e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
126e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * See the License for the specific language governing permissions and
146e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * limitations under the License.
156e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn */
166e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
176e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornpackage com.android.server.wm;
186e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
196e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport com.android.server.wm.WindowManagerService.H;
206e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
216e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.content.ClipData;
226e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.content.ClipDescription;
236e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.graphics.Region;
246e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.os.IBinder;
256e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.os.Message;
266e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.os.Process;
276e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.os.RemoteException;
286e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.util.Slog;
296e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.DragEvent;
306e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.InputChannel;
316e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.InputQueue;
326e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.Surface;
336e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.View;
346e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.WindowManager;
356e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport android.view.WindowManagerPolicy;
366e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
376e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornimport java.util.ArrayList;
386e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
396e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn/**
406e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn * Drag/drop state
416e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn */
426e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackbornclass DragState {
436e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    final WindowManagerService mService;
446e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    IBinder mToken;
456e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    Surface mSurface;
466e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    int mFlags;
476e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    IBinder mLocalWin;
486e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    ClipData mData;
496e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    ClipDescription mDataDescription;
506e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    boolean mDragResult;
516e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    float mCurrentX, mCurrentY;
526e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    float mThumbOffsetX, mThumbOffsetY;
536e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    InputChannel mServerChannel, mClientChannel;
546e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    WindowState mTargetWindow;
556e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    ArrayList<WindowState> mNotifiedWindows;
566e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    boolean mDragInProgress;
576e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
586e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    private final Region mTmpRegion = new Region();
596e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
606e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    DragState(WindowManagerService service, IBinder token, Surface surface,
616e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            int flags, IBinder localWin) {
626e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService = service;
636e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mToken = token;
646e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mSurface = surface;
656e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mFlags = flags;
666e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mLocalWin = localWin;
676e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mNotifiedWindows = new ArrayList<WindowState>();
686e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
696e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
706e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void reset() {
716e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (mSurface != null) {
726e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mSurface.destroy();
736e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
746e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mSurface = null;
756e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mFlags = 0;
766e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mLocalWin = null;
776e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mToken = null;
786e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mData = null;
796e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mThumbOffsetX = mThumbOffsetY = 0;
806e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mNotifiedWindows = null;
816e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
826e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
836e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void register() {
846e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "registering drag input channel");
856e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (mClientChannel != null) {
866e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.e(WindowManagerService.TAG, "Duplicate register of drag input channel");
876e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } else {
886e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            InputChannel[] channels = InputChannel.openInputChannelPair("drag");
896e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mServerChannel = channels[0];
906e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mClientChannel = channels[1];
916e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mService.mInputManager.registerInputChannel(mServerChannel, null);
926e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            InputQueue.registerInputChannel(mClientChannel, mService.mDragInputHandler,
936e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    mService.mH.getLooper().getQueue());
946e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
956e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
966e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
976e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void unregister() {
986e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "unregistering drag input channel");
996e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (mClientChannel == null) {
1006e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.e(WindowManagerService.TAG, "Unregister of nonexistent drag input channel");
1016e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } else {
1026e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mService.mInputManager.unregisterInputChannel(mServerChannel);
1036e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            InputQueue.unregisterInputChannel(mClientChannel);
1046e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mClientChannel.dispose();
1056e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mServerChannel.dispose();
1066e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mClientChannel = null;
1076e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mServerChannel = null;
1086e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1096e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
1106e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1116e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    int getDragLayerLw() {
1126e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
1136e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                * WindowManagerService.TYPE_LAYER_MULTIPLIER
1146e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                + WindowManagerService.TYPE_LAYER_OFFSET;
1156e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
1166e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1176e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    /* call out to each visible window/session informing it about the drag
1186e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     */
1196e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void broadcastDragStartedLw(final float touchX, final float touchY) {
1206e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // Cache a base-class instance of the clip metadata so that parceling
1216e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // works correctly in calling out to the apps.
1226e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mDataDescription = (mData != null) ? mData.getDescription() : null;
1236e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mNotifiedWindows.clear();
1246e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mDragInProgress = true;
1256e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1266e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_DRAG) {
1276e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.d(WindowManagerService.TAG, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
1286e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1296e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1306e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int N = mService.mWindows.size();
1316e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        for (int i = 0; i < N; i++) {
1326e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            sendDragStartedLw(mService.mWindows.get(i), touchX, touchY, mDataDescription);
1336e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1346e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
1356e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1366e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    /* helper - send a caller-provided event, presumed to be DRAG_STARTED, if the
1376e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * designated window is potentially a drop recipient.  There are race situations
1386e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * around DRAG_ENDED broadcast, so we make sure that once we've declared that
1396e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * the drag has ended, we never send out another DRAG_STARTED for this drag action.
1406e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     *
1416e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * This method clones the 'event' parameter if it's being delivered to the same
1426e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * process, so it's safe for the caller to call recycle() on the event afterwards.
1436e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     */
1446e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
1456e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            ClipDescription desc) {
1466e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // Don't actually send the event if the drag is supposed to be pinned
1476e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // to the originating window but 'newWin' is not that window.
1486e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
1496e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            final IBinder winBinder = newWin.mClient.asBinder();
1506e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (winBinder != mLocalWin) {
1516e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (WindowManagerService.DEBUG_DRAG) {
1526e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    Slog.d(WindowManagerService.TAG, "Not dispatching local DRAG_STARTED to " + newWin);
1536e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
1546e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                return;
1556e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
1566e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1576e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1586e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (mDragInProgress && newWin.isPotentialDragTarget()) {
1596e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_STARTED,
1606e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    touchX - newWin.mFrame.left, touchY - newWin.mFrame.top,
1616e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    null, desc, null, false);
1626e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            try {
1636e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                newWin.mClient.dispatchDragEvent(event);
1646e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // track each window that we've notified that the drag is starting
1656e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                mNotifiedWindows.add(newWin);
1666e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            } catch (RemoteException e) {
1676e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                Slog.w(WindowManagerService.TAG, "Unable to drag-start window " + newWin);
1686e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            } finally {
1696e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // if the callee was local, the dispatch has already recycled the event
1706e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (Process.myPid() != newWin.mSession.mPid) {
1716e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    event.recycle();
1726e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
1736e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
1746e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1756e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
1766e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1776e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    /* helper - construct and send a DRAG_STARTED event only if the window has not
1786e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * previously been notified, i.e. it became visible after the drag operation
1796e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     * was begun.  This is a rare case.
1806e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn     */
1816e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void sendDragStartedIfNeededLw(WindowState newWin) {
1826e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (mDragInProgress) {
1836e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            // If we have sent the drag-started, we needn't do so again
1846e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            for (WindowState ws : mNotifiedWindows) {
1856e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (ws == newWin) {
1866e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    return;
1876e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
1886e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
1896e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (WindowManagerService.DEBUG_DRAG) {
1906e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                Slog.d(WindowManagerService.TAG, "need to send DRAG_STARTED to new window " + newWin);
1916e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
1926e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
1936e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
1946e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
1956e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
1966e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void broadcastDragEndedLw() {
1976e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_DRAG) {
1986e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.d(WindowManagerService.TAG, "broadcasting DRAG_ENDED");
1996e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2006e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
2016e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                0, 0, null, null, null, mDragResult);
2026e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        for (WindowState ws: mNotifiedWindows) {
2036e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            try {
2046e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                ws.mClient.dispatchDragEvent(evt);
2056e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            } catch (RemoteException e) {
2066e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                Slog.w(WindowManagerService.TAG, "Unable to drag-end window " + ws);
2076e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
2086e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2096e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mNotifiedWindows.clear();
2106e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mDragInProgress = false;
2116e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        evt.recycle();
2126e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
2136e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2146e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void endDragLw() {
2156e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService.mDragState.broadcastDragEndedLw();
2166e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2176e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // stop intercepting input
2186e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService.mDragState.unregister();
2196e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
2206e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2216e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // free our resources and drop all the object references
2226e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService.mDragState.reset();
2236e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mService.mDragState = null;
2246e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2256e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_ORIENTATION) Slog.d(WindowManagerService.TAG, "Performing post-drag rotation");
2266e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        boolean changed = mService.setRotationUncheckedLocked(
2276e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
2286e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (changed) {
2296e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mService.mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
2306e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2316e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
2326e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2336e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    void notifyMoveLw(float x, float y) {
2346e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int myPid = Process.myPid();
2356e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2366e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // Move the surface to the given touch
2376e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
2386e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        Surface.openTransaction();
2396e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        try {
2406e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mSurface.setPosition((int)(x - mThumbOffsetX), (int)(y - mThumbOffsetY));
2416e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DRAG "
2426e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    + mSurface + ": pos=(" +
2436e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
2446e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } finally {
2456e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Surface.closeTransaction();
2466e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
2476e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2486e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2496e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        // Tell the affected window
2506e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        WindowState touchedWin = getTouchedWinAtPointLw(x, y);
2516e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (touchedWin == null) {
2526e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (WindowManagerService.DEBUG_DRAG) Slog.d(WindowManagerService.TAG, "No touched win at x=" + x + " y=" + y);
2536e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            return;
2546e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2556e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
2566e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            final IBinder touchedBinder = touchedWin.mClient.asBinder();
2576e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (touchedBinder != mLocalWin) {
2586e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // This drag is pinned only to the originating window, but the drag
2596e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // point is outside that window.  Pretend it's over empty space.
2606e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                touchedWin = null;
2616e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
2626e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2636e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        try {
2646e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            // have we dragged over a new window?
2656e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
2666e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (WindowManagerService.DEBUG_DRAG) {
2676e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    Slog.d(WindowManagerService.TAG, "sending DRAG_EXITED to " + mTargetWindow);
2686e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
2696e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // force DRAG_EXITED_EVENT if appropriate
2706e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_EXITED,
2716e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                        x - mTargetWindow.mFrame.left, y - mTargetWindow.mFrame.top,
2726e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                        null, null, null, false);
2736e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                mTargetWindow.mClient.dispatchDragEvent(evt);
2746e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (myPid != mTargetWindow.mSession.mPid) {
2756e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    evt.recycle();
2766e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
2776e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
2786e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (touchedWin != null) {
2796e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (false && WindowManagerService.DEBUG_DRAG) {
2806e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    Slog.d(WindowManagerService.TAG, "sending DRAG_LOCATION to " + touchedWin);
2816e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
2826e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_LOCATION,
2836e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                        x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
2846e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                        null, null, null, false);
2856e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                touchedWin.mClient.dispatchDragEvent(evt);
2866e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                if (myPid != touchedWin.mSession.mPid) {
2876e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    evt.recycle();
2886e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                }
2896e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
2906e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } catch (RemoteException e) {
2916e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.w(WindowManagerService.TAG, "can't send drag notification to windows");
2926e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
2936e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mTargetWindow = touchedWin;
2946e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
2956e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
2966e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    // Tell the drop target about the data.  Returns 'true' if we can immediately
2976e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    // dispatch the global drag-ended message, 'false' if we need to wait for a
2986e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    // result from the recipient.
2996e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    boolean notifyDropLw(float x, float y) {
3006e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        WindowState touchedWin = getTouchedWinAtPointLw(x, y);
3016e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (touchedWin == null) {
3026e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            // "drop" outside a valid window -- no recipient to apply a
3036e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            // timeout to, and we can send the drag-ended message immediately.
3046e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mDragResult = false;
3056e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            return true;
3066e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
3076e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3086e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        if (WindowManagerService.DEBUG_DRAG) {
3096e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.d(WindowManagerService.TAG, "sending DROP to " + touchedWin);
3106e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
3116e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int myPid = Process.myPid();
3126e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final IBinder token = touchedWin.mClient.asBinder();
3136e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DROP,
3146e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                x - touchedWin.mFrame.left, y - touchedWin.mFrame.top,
3156e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                null, null, mData, false);
3166e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        try {
3176e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            touchedWin.mClient.dispatchDragEvent(evt);
3186e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3196e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            // 5 second timeout for this window to respond to the drop
3206e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
3216e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
3226e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            mService.mH.sendMessageDelayed(msg, 5000);
3236e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } catch (RemoteException e) {
3246e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            Slog.w(WindowManagerService.TAG, "can't send drop notification to win " + touchedWin);
3256e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            return true;
3266e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        } finally {
3276e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (myPid != touchedWin.mSession.mPid) {
3286e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                evt.recycle();
3296e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
3306e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
3316e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        mToken = token;
3326e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        return false;
3336e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
3346e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3356e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    // Find the visible, touch-deliverable window under the given point
3366e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    private WindowState getTouchedWinAtPointLw(float xf, float yf) {
3376e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        WindowState touchedWin = null;
3386e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int x = (int) xf;
3396e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int y = (int) yf;
3406e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final ArrayList<WindowState> windows = mService.mWindows;
3416e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        final int N = windows.size();
3426e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        for (int i = N - 1; i >= 0; i--) {
3436e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            WindowState child = windows.get(i);
3446e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            final int flags = child.mAttrs.flags;
3456e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (!child.isVisibleLw()) {
3466e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // not visible == don't tell about drags
3476e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                continue;
3486e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
3496e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
3506e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // not touchable == don't tell about drags
3516e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                continue;
3526e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
3536e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3546e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            child.getTouchableRegion(mTmpRegion);
3556e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3566e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            final int touchFlags = flags &
3576e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                    (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
3586e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                            | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
3596e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
3606e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                // Found it
3616e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                touchedWin = child;
3626e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn                break;
3636e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn            }
3646e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        }
3656e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn
3666e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn        return touchedWin;
3676e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn    }
3686e1eb76f02ccc9dbc309b938f62d39312da8cafeDianne Hackborn}