diff options
3 files changed, 350 insertions, 266 deletions
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java new file mode 100644 index 000000000000..36871b1d8c5b --- /dev/null +++ b/services/core/java/com/android/server/wm/DragDropController.java @@ -0,0 +1,306 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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; +import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; + +import android.content.ClipData; +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; +import com.android.server.wm.WindowManagerService.H; + +/** + * Managing drag and drop operations initiated by View#startDragAndDrop. + */ +class DragDropController { + private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f; + private static final long DRAG_TIMEOUT_MS = 5000; + + IBinder prepareDrag(WindowManagerService service, SurfaceSession session, int callerPid, + int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height + + " flags=" + Integer.toHexString(flags) + " win=" + window + + " asbinder=" + window.asBinder()); + } + + IBinder token = null; + + synchronized (service.mWindowMap) { + try { + if (service.mDragState == null) { + // TODO(multi-display): support other displays + final DisplayContent displayContent = + service.getDefaultDisplayContentLocked(); + final Display display = displayContent.getDisplay(); + + SurfaceControl surface = new SurfaceControl(session, "drag surface", + width, height, TRANSLUCENT, HIDDEN); + surface.setLayerStack(display.getLayerStack()); + float alpha = 1; + if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { + alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; + } + surface.setAlpha(alpha); + + 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(); + + // 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; + } + + boolean performDrag(WindowManagerService service, IWindow window, IBinder dragToken, + 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); + } + + synchronized (service.mWindowMap) { + if (service.mDragState == null) { + Slog.w(TAG_WM, "No drag prepared"); + throw new IllegalStateException("performDrag() without prepareDrag()"); + } + + if (dragToken != service.mDragState.mToken) { + Slog.w(TAG_WM, "Performing mismatched drag"); + throw new IllegalStateException("performDrag() does not match prepareDrag()"); + } + + final WindowState callingWin = service.windowForClientLocked(null, window, false); + if (callingWin == null) { + Slog.w(TAG_WM, "Bad requesting window " + window); + return false; // !!! TODO: throw here? + } + + // !!! TODO: if input is not still focused on the initiating window, fail + // the drag initiation (e.g. an alarm window popped up just as the application + // called performDrag() + + service.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder()); + + // !!! TODO: extract the current touch (x, y) in screen coordinates. That + // will let us eliminate the (touchX,touchY) parameters from the API. + + // !!! FIXME: put all this heavy stuff onto the mH looper, as well as + // the actual drag event dispatch stuff in the dragstate + + final DisplayContent displayContent = callingWin.getDisplayContent(); + if (displayContent == null) { + return false; + } + Display display = displayContent.getDisplay(); + service.mDragState.register(display); + if (!service.mInputManager.transferTouchFocus(callingWin.mInputChannel, + service.mDragState.getInputChannel())) { + Slog.e(TAG_WM, "Unable to transfer touch focus"); + service.mDragState.unregister(); + service.mDragState.reset(); + service.mDragState = null; + return false; + } + + service.mDragState.mDisplayContent = displayContent; + service.mDragState.mData = data; + service.mDragState.broadcastDragStartedLw(touchX, touchY); + service.mDragState.overridePointerIconLw(touchSource); + + // remember the thumb offsets for later + service.mDragState.mThumbOffsetX = thumbCenterX; + service.mDragState.mThumbOffsetY = thumbCenterY; + + // Make the surface visible at the proper location + final SurfaceControl surfaceControl = service.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.setLayerStack(display.getLayerStack()); + surfaceControl.show(); + } finally { + service.closeSurfaceTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i( + TAG_WM, "<<< CLOSE TRANSACTION performDrag"); + } + + service.mDragState.notifyLocationLw(touchX, touchY); + } + + return true; // success! + } + + void reportDropResult(WindowManagerService service, IWindow window, boolean consumed) { + IBinder token = window.asBinder(); + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token); + } + + synchronized (service.mWindowMap) { + if (service.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) { + // 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"); + } + + // The right window has responded, even if it's no longer around, + // so be sure to halt the timeout even if the later WindowState + // lookup fails. + service.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder()); + WindowState callingWin = service.windowForClientLocked(null, window, false); + if (callingWin == null) { + Slog.w(TAG_WM, "Bad result-reporting window " + window); + return; // !!! TODO: throw here? + } + + service.mDragState.mDragResult = consumed; + service.mDragState.endDragLw(); + } + } + + void cancelDragAndDrop(WindowManagerService service, IBinder dragToken) { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "cancelDragAndDrop"); + } + + synchronized (service.mWindowMap) { + if (service.mDragState == null) { + Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()"); + throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()"); + } + + if (service.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(); + } + } + + void dragRecipientEntered(IWindow window) { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder()); + } + } + + void dragRecipientExited(IWindow window) { + if (DEBUG_DRAG) { + Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder()); + } + } + + void handleMessage(WindowManagerService service, Message msg) { + switch (msg.what) { + case H.DRAG_START_TIMEOUT: { + IBinder win = (IBinder) msg.obj; + if (DEBUG_DRAG) { + Slog.w(TAG_WM, "Timeout starting drag by win " + win); + } + 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; + } + } + break; + } + + case H.DRAG_END_TIMEOUT: { + IBinder win = (IBinder) msg.obj; + if (DEBUG_DRAG) { + Slog.w(TAG_WM, "Timeout ending drag to win " + win); + } + synchronized (service.mWindowMap) { + // !!! TODO: ANR the drag-receiving app + if (service.mDragState != null) { + service.mDragState.mDragResult = false; + service.mDragState.endDragLw(); + } + } + break; + } + + case H.TEAR_DOWN_DRAG_AND_DROP_INPUT: { + if (DEBUG_DRAG) + Slog.d(TAG_WM, "Drag ending; tearing down input channel"); + DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj; + if (interceptor != null) { + synchronized (service.mWindowMap) { + interceptor.tearDown(); + } + } + break; + } + } + } +} diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 2bb023557647..717c5774f9f3 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -81,6 +81,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { private final Set<WindowSurfaceController> mAppOverlaySurfaces = new HashSet<>(); // Set of visible alert window surfaces connected to this session. private final Set<WindowSurfaceController> mAlertWindowSurfaces = new HashSet<>(); + private final DragDropController mDragDropController; final boolean mCanAddInternalSystemWindow; final boolean mCanHideNonSystemOverlayWindows; final boolean mCanAcquireSleepToken; @@ -106,6 +107,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { mCanAcquireSleepToken = service.mContext.checkCallingOrSelfPermission(DEVICE_POWER) == PERMISSION_GRANTED; mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications; + mDragDropController = mService.mDragDropController; StringBuilder sb = new StringBuilder(); sb.append("Session{"); sb.append(Integer.toHexString(System.identityHashCode(this))); @@ -304,190 +306,68 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { /* Drag/drop */ @Override - public IBinder prepareDrag(IWindow window, int flags, - int width, int height, Surface outSurface) { - return mService.prepareDragSurface(window, mSurfaceSession, flags, - width, height, outSurface); + public IBinder prepareDrag(IWindow window, int flags, int width, int height, + Surface outSurface) { + final int callerPid = Binder.getCallingPid(); + final int callerUid = Binder.getCallingUid(); + final long ident = Binder.clearCallingIdentity(); + try { + return mDragDropController.prepareDrag( + mService, mSurfaceSession, callerPid, callerUid, window, flags, width, height, + outSurface); + } finally { + Binder.restoreCallingIdentity(ident); + } } @Override public boolean performDrag(IWindow window, IBinder dragToken, 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); - } - - synchronized (mService.mWindowMap) { - if (mService.mDragState == null) { - Slog.w(TAG_WM, "No drag prepared"); - throw new IllegalStateException("performDrag() without prepareDrag()"); - } - - if (dragToken != mService.mDragState.mToken) { - Slog.w(TAG_WM, "Performing mismatched drag"); - throw new IllegalStateException("performDrag() does not match prepareDrag()"); - } - - WindowState callingWin = mService.windowForClientLocked(null, window, false); - if (callingWin == null) { - Slog.w(TAG_WM, "Bad requesting window " + window); - return false; // !!! TODO: throw here? - } - - // !!! TODO: if input is not still focused on the initiating window, fail - // the drag initiation (e.g. an alarm window popped up just as the application - // called performDrag() - - mService.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder()); - - // !!! TODO: extract the current touch (x, y) in screen coordinates. That - // will let us eliminate the (touchX,touchY) parameters from the API. - - // !!! FIXME: put all this heavy stuff onto the mH looper, as well as - // the actual drag event dispatch stuff in the dragstate - - final DisplayContent displayContent = callingWin.getDisplayContent(); - if (displayContent == null) { - return false; - } - Display display = displayContent.getDisplay(); - mService.mDragState.register(display); - if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, - mService.mDragState.getInputChannel())) { - Slog.e(TAG_WM, "Unable to transfer touch focus"); - mService.mDragState.unregister(); - mService.mDragState.reset(); - mService.mDragState = null; - return false; - } - - mService.mDragState.mDisplayContent = displayContent; - mService.mDragState.mData = data; - mService.mDragState.broadcastDragStartedLw(touchX, touchY); - mService.mDragState.overridePointerIconLw(touchSource); - - // remember the thumb offsets for later - mService.mDragState.mThumbOffsetX = thumbCenterX; - mService.mDragState.mThumbOffsetY = thumbCenterY; - - // Make the surface visible at the proper location - final SurfaceControl surfaceControl = mService.mDragState.mSurfaceControl; - if (SHOW_LIGHT_TRANSACTIONS) Slog.i( - TAG_WM, ">>> OPEN TRANSACTION performDrag"); - mService.openSurfaceTransaction(); - try { - surfaceControl.setPosition(touchX - thumbCenterX, - touchY - thumbCenterY); - surfaceControl.setLayer(mService.mDragState.getDragLayerLw()); - surfaceControl.setLayerStack(display.getLayerStack()); - surfaceControl.show(); - } finally { - mService.closeSurfaceTransaction(); - if (SHOW_LIGHT_TRANSACTIONS) Slog.i( - TAG_WM, "<<< CLOSE TRANSACTION performDrag"); - } - - mService.mDragState.notifyLocationLw(touchX, touchY); - } - - return true; // success! + return mDragDropController.performDrag(mService, window, dragToken, touchSource, + touchX, touchY, thumbCenterX, thumbCenterY, data); } @Override - public boolean startMovingTask(IWindow window, float startX, float startY) { - if (DEBUG_TASK_POSITIONING) Slog.d( - TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); - - long ident = Binder.clearCallingIdentity(); + public void reportDropResult(IWindow window, boolean consumed) { + final long ident = Binder.clearCallingIdentity(); try { - return mService.startMovingTask(window, startX, startY); + mDragDropController.reportDropResult(mService, window, consumed); } finally { Binder.restoreCallingIdentity(ident); } } @Override - public void reportDropResult(IWindow window, boolean consumed) { - IBinder token = window.asBinder(); - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token); - } - - synchronized (mService.mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - if (mService.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 (mService.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"); - } - - // The right window has responded, even if it's no longer around, - // so be sure to halt the timeout even if the later WindowState - // lookup fails. - mService.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder()); - WindowState callingWin = mService.windowForClientLocked(null, window, false); - if (callingWin == null) { - Slog.w(TAG_WM, "Bad result-reporting window " + window); - return; // !!! TODO: throw here? - } - - mService.mDragState.mDragResult = consumed; - mService.mDragState.endDragLw(); - } finally { - Binder.restoreCallingIdentity(ident); - } - } - } - - @Override public void cancelDragAndDrop(IBinder dragToken) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "cancelDragAndDrop"); - } - - synchronized (mService.mWindowMap) { - long ident = Binder.clearCallingIdentity(); - try { - if (mService.mDragState == null) { - Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()"); - throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()"); - } - - if (mService.mDragState.mToken != dragToken) { - Slog.w(TAG_WM, - "cancelDragAndDrop() does not match prepareDrag()"); - throw new IllegalStateException( - "cancelDragAndDrop() does not match prepareDrag()"); - } - - mService.mDragState.mDragResult = false; - mService.mDragState.cancelDragLw(); - } finally { - Binder.restoreCallingIdentity(ident); - } + final long ident = Binder.clearCallingIdentity(); + try { + mDragDropController.cancelDragAndDrop(mService, dragToken); + } finally { + Binder.restoreCallingIdentity(ident); } } @Override public void dragRecipientEntered(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder()); - } + mDragDropController.dragRecipientEntered(window); } @Override public void dragRecipientExited(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder()); + mDragDropController.dragRecipientExited(window); + } + + @Override + public boolean startMovingTask(IWindow window, float startX, float startY) { + if (DEBUG_TASK_POSITIONING) Slog.d( + TAG_WM, "startMovingTask: {" + startX + "," + startY + "}"); + + long ident = Binder.clearCallingIdentity(); + try { + return mService.startMovingTask(window, startX, startY); + } finally { + Binder.restoreCallingIdentity(ident); } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f0da4742efa0..3d60475684e5 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -357,8 +357,6 @@ public class WindowManagerService extends IWindowManager.Stub // trying to apply a new one. private static final boolean ALWAYS_KEEP_CURRENT = true; - private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f; - // Enums for animation scale update types. @Retention(RetentionPolicy.SOURCE) @IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE}) @@ -752,6 +750,7 @@ public class WindowManagerService extends IWindowManager.Stub boolean mAllowTheaterModeWakeFromLayout; TaskPositioner mTaskPositioner; + final DragDropController mDragDropController = new DragDropController(); DragState mDragState = null; // For frozen screen animations. @@ -4637,73 +4636,6 @@ public class WindowManagerService extends IWindowManager.Stub } // ------------------------------------------------------------- - // Drag and drop - // ------------------------------------------------------------- - - IBinder prepareDragSurface(IWindow window, SurfaceSession session, - int flags, int width, int height, Surface outSurface) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height - + " flags=" + Integer.toHexString(flags) + " win=" + window - + " asbinder=" + window.asBinder()); - } - - final int callerPid = Binder.getCallingPid(); - final int callerUid = Binder.getCallingUid(); - final long origId = Binder.clearCallingIdentity(); - IBinder token = null; - - try { - synchronized (mWindowMap) { - try { - if (mDragState == null) { - // TODO(multi-display): support other displays - final DisplayContent displayContent = getDefaultDisplayContentLocked(); - final Display display = displayContent.getDisplay(); - - SurfaceControl surface = new SurfaceControl(session, "drag surface", - width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); - surface.setLayerStack(display.getLayerStack()); - float alpha = 1; - if ((flags & View.DRAG_FLAG_OPAQUE) == 0) { - alpha = DRAG_SHADOW_ALPHA_TRANSPARENT; - } - surface.setAlpha(alpha); - - if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG " - + surface + ": CREATE"); - outSurface.copyFrom(surface); - final IBinder winBinder = window.asBinder(); - token = new Binder(); - mDragState = new DragState(this, 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 - mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder); - Message msg = mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder); - mH.sendMessageDelayed(msg, 5000); - } 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 (mDragState != null) { - mDragState.reset(); - mDragState = null; - } - } - } - } finally { - Binder.restoreCallingIdentity(origId); - } - - return token; - } - - // ------------------------------------------------------------- // Input Events and Focus Management // ------------------------------------------------------------- @@ -4866,6 +4798,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int REPORT_WINDOWS_CHANGE = 19; public static final int DRAG_START_TIMEOUT = 20; public static final int DRAG_END_TIMEOUT = 21; + public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; public static final int BOOT_TIMEOUT = 23; public static final int WAITING_FOR_DRAWN_TIMEOUT = 24; @@ -5120,47 +5053,12 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case DRAG_START_TIMEOUT: { - IBinder win = (IBinder)msg.obj; - if (DEBUG_DRAG) { - Slog.w(TAG_WM, "Timeout starting drag by win " + win); - } - synchronized (mWindowMap) { - // !!! TODO: ANR the app that has failed to start the drag in time - if (mDragState != null) { - mDragState.unregister(); - mDragState.reset(); - mDragState = null; - } - } - break; - } - - case DRAG_END_TIMEOUT: { - IBinder win = (IBinder)msg.obj; - if (DEBUG_DRAG) { - Slog.w(TAG_WM, "Timeout ending drag to win " + win); - } - synchronized (mWindowMap) { - // !!! TODO: ANR the drag-receiving app - if (mDragState != null) { - mDragState.mDragResult = false; - mDragState.endDragLw(); - } - } - break; - } - + case DRAG_START_TIMEOUT: + case DRAG_END_TIMEOUT: case TEAR_DOWN_DRAG_AND_DROP_INPUT: { - if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ending; tearing down input channel"); - DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj; - if (interceptor != null) { - synchronized (mWindowMap) { - interceptor.tearDown(); - } - } + mDragDropController.handleMessage(WindowManagerService.this, msg); + break; } - break; case REPORT_HARD_KEYBOARD_STATUS_CHANGE: { notifyHardKeyboardStatusChange(); |