From df5cf6259c9e23e573edb2ecf019beef6396d369 Mon Sep 17 00:00:00 2001 From: Daichi Hirono Date: Mon, 11 Sep 2017 14:59:26 +0900 Subject: [PATCH] Move drag and drop related lines to DragDropController The CL creates new DragDropController class where we can get together everything related with drag and drop, and moves the following methods to DragDropController. * WindowManagerService#preapreDragSurface * WindowManagerService.H#handleMessage for DRAG_START_TIMEOUT, DRAG_END_TIMEOUT, and TEAR_DOWN_DRAG_AND_DROP_INPUT * Session#preapreDrag * Session#performDrag * Session#reportDropResult * Session#cancelDragAndDrop * Session#dragRecipientEntered * Session#dragRecipientExited Note that the CL does not remove the binder interface methods in Session e.g. Session#prepareDrag. These methods start delegating drag and drop work to DragDropController. Bug: 65564090 Test: Manually drag and drop files between apps, CTS CrossAppDragAndDropTests Change-Id: I50f6f022f2ecd0ab160b5187ae39f0f533f05969 --- .../android/server/wm/DragDropController.java | 306 ++++++++++++++++++ .../java/com/android/server/wm/Session.java | 204 +++--------- .../server/wm/WindowManagerService.java | 114 +------ 3 files changed, 354 insertions(+), 270 deletions(-) create mode 100644 services/core/java/com/android/server/wm/DragDropController.java 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 0000000000000..36871b1d8c5be --- /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 2bb0235576474..717c5774f9f31 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 mAppOverlaySurfaces = new HashSet<>(); // Set of visible alert window surfaces connected to this session. private final Set 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,94 +306,56 @@ 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); + return mDragDropController.performDrag(mService, window, dragToken, touchSource, + touchX, touchY, thumbCenterX, thumbCenterY, data); + } + + @Override + public void reportDropResult(IWindow window, boolean consumed) { + final long ident = Binder.clearCallingIdentity(); + try { + mDragDropController.reportDropResult(mService, window, consumed); + } finally { + Binder.restoreCallingIdentity(ident); } + } - 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); + @Override + public void cancelDragAndDrop(IBinder dragToken) { + final long ident = Binder.clearCallingIdentity(); + try { + mDragDropController.cancelDragAndDrop(mService, dragToken); + } finally { + Binder.restoreCallingIdentity(ident); } + } - return true; // success! + @Override + public void dragRecipientEntered(IWindow window) { + mDragDropController.dragRecipientEntered(window); + } + + @Override + public void dragRecipientExited(IWindow window) { + mDragDropController.dragRecipientExited(window); } @Override @@ -407,90 +371,6 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { } } - @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); - } - } - } - - @Override - public void dragRecipientEntered(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "Drag into new candidate view @ " + window.asBinder()); - } - } - - @Override - public void dragRecipientExited(IWindow window) { - if (DEBUG_DRAG) { - Slog.d(TAG_WM, "Drag from old candidate view @ " + window.asBinder()); - } - } - @Override public void setWallpaperPosition(IBinder window, float x, float y, float xStep, float yStep) { synchronized(mService.mWindowMap) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index f0da4742efa0e..3d60475684e50 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. @@ -4636,73 +4635,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();