Loading core/java/android/view/IWindowSession.aidl +20 −12 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.IWindowId; import android.view.MotionEvent; import android.view.WindowManager; import android.view.Surface; import android.view.SurfaceControl; /** * System private per-application interface to the window manager. Loading Loading @@ -149,18 +150,25 @@ interface IWindowSession { boolean performHapticFeedback(IWindow window, int effectId, boolean always); /** * Allocate the drag's thumbnail surface. Also assigns a token that identifies * the drag to the OS and passes that as the return value. A return value of * null indicates failure. */ IBinder prepareDrag(IWindow window, int flags, int thumbnailWidth, int thumbnailHeight, out Surface outSurface); /** * Initiate the drag operation itself */ boolean performDrag(IWindow window, IBinder dragToken, int touchSource, * * @param window Window which initiates drag operation. * @param flags See {@code View#startDragAndDrop} * @param surface Surface containing drag shadow image * @param touchSource See {@code InputDevice#getSource()} * @param touchX TODO (b/72072998): Fix the issue that the system server misuse the arguments as * initial touch point while the framework passes drag shadow size. * @param touchY TODO (b/72072998): Fix the issue that the system server misuse the arguments as * initial touch point while the framework passes drag shadow size. * @param thumbCenterX X coordinate for the position within the shadow image that should be * underneath the touch point during the drag and drop operation. * @param thumbCenterY Y coordinate for the position within the shadow image that should be * underneath the touch point during the drag and drop operation. * @param data Data transferred by drag and drop * @return Token of drag operation which will be passed to cancelDragAndDrop. */ IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data); /** Loading core/java/android/view/SurfaceControl.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * 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 android.view; parcelable SurfaceControl; core/java/android/view/View.java +39 −31 Original line number Diff line number Diff line Loading @@ -23562,15 +23562,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0); } boolean okay = false; Point shadowSize = new Point(); Point shadowTouchPoint = new Point(); shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); if ((shadowSize.x < 0) || (shadowSize.y < 0) || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { throw new IllegalStateException("Drag shadow dimensions must not be negative"); if ((shadowSize.x <= 0) || (shadowSize.y <= 0) || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { throw new IllegalStateException("Drag shadow dimensions must be positive"); } if (ViewDebug.DEBUG_DRAG) { Loading @@ -23581,13 +23579,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo.mDragSurface.release(); } mAttachInfo.mDragSurface = new Surface(); mAttachInfo.mDragToken = null; final ViewRootImpl root = mAttachInfo.mViewRootImpl; final SurfaceSession session = new SurfaceSession(root.mSurface); final SurfaceControl surface = new SurfaceControl.Builder(session) .setName("drag surface") .setSize(shadowSize.x, shadowSize.y) .setFormat(PixelFormat.TRANSLUCENT) .build(); try { mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface); if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface); if (mAttachInfo.mDragToken != null) { Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); mAttachInfo.mDragSurface.copyFrom(surface); final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); try { canvas.drawColor(0, PorterDuff.Mode.CLEAR); shadowBuilder.onDrawShadow(canvas); Loading @@ -23595,26 +23598,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); } final ViewRootImpl root = getViewRootImpl(); // Cache the local state object for delivery with DragEvents root.setLocalDragState(myLocalState); // repurpose 'shadowSize' for the last touch point root.getLastTouchPoint(shadowSize); okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken, root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag( mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); if (ViewDebug.DEBUG_DRAG) { Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken); } return mAttachInfo.mDragToken != null; } catch (Exception e) { Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); return false; } finally { if (mAttachInfo.mDragToken == null) { mAttachInfo.mDragSurface.destroy(); mAttachInfo.mDragSurface = null; root.setLocalDragState(null); } session.kill(); } return okay; } /** services/core/java/com/android/server/wm/DisplayContent.java +7 −0 Original line number Diff line number Diff line Loading @@ -3697,6 +3697,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .setParent(mOverlayLayer); } /** * Reparents the given surface to mOverlayLayer. */ void reparentToOverlay(Transaction transaction, SurfaceControl surface) { transaction.reparent(surface, mOverlayLayer.getHandle()); } void applyMagnificationSpec(MagnificationSpec spec) { applyMagnificationSpec(getPendingTransaction(), spec); getPendingTransaction().apply(); Loading services/core/java/com/android/server/wm/DragDropController.java +48 −102 Original line number Diff line number Diff line Loading @@ -18,12 +18,10 @@ package com.android.server.wm; 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.annotation.NonNull; import android.content.ClipData; import android.graphics.PixelFormat; import android.os.Binder; import android.os.Handler; import android.os.IBinder; Loading @@ -32,8 +30,8 @@ import android.os.Message; import android.util.Slog; import android.view.Display; import android.view.IWindow; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.View; Loading @@ -50,10 +48,9 @@ class DragDropController { private static final long DRAG_TIMEOUT_MS = 5000; // Messages for Handler. private static final int MSG_DRAG_START_TIMEOUT = 0; static final int MSG_DRAG_END_TIMEOUT = 1; static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2; static final int MSG_ANIMATION_END = 3; static final int MSG_DRAG_END_TIMEOUT = 0; static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1; static final int MSG_ANIMATION_END = 2; /** * Drag state per operation. Loading Loading @@ -95,87 +92,35 @@ class DragDropController { mDragState.sendDragStartedIfNeededLocked(window); } IBinder prepareDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) { IBinder performDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window, int flags, SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) { if (DEBUG_DRAG) { Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height + " flags=" + Integer.toHexString(flags) + " win=" + window + " asbinder=" + window.asBinder()); } if (width <= 0 || height <= 0) { Slog.w(TAG_WM, "width and height of drag shadow must be positive"); return null; } synchronized (mService.mWindowMap) { if (dragDropActiveLocked()) { Slog.w(TAG_WM, "Drag already in progress"); return null; } // TODO(multi-display): support other displays final DisplayContent displayContent = mService.getDefaultDisplayContentLocked(); final Display display = displayContent.getDisplay(); final SurfaceControl surface = new SurfaceControl.Builder(session) .setName("drag surface") .setSize(width, height) .setFormat(PixelFormat.TRANSLUCENT) .build(); 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(); IBinder token = new Binder(); mDragState = new DragState(mService, 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 sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder); return token; } } 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); Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" + Integer.toHexString(flags) + " data=" + data); } final IBinder dragToken = new Binder(); final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data); try { synchronized (mService.mWindowMap) { mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder()); try { if (!callbackResult) { return false; Slog.w(TAG_WM, "IDragDropCallback rejects the performDrag request"); return null; } Preconditions.checkState( mDragState != null, "performDrag() without prepareDrag()"); Preconditions.checkState( mDragState.mToken == dragToken, "performDrag() does not match prepareDrag()"); if (dragDropActiveLocked()) { Slog.w(TAG_WM, "Drag already in progress"); return null; } final WindowState callingWin = mService.windowForClientLocked( null, window, false); if (callingWin == null) { Slog.w(TAG_WM, "Bad requesting window " + window); return false; // !!! TODO: throw here? return null; // !!! TODO: throw here? } // !!! TODO: if input is not still focused on the initiating window, fail Loading @@ -188,18 +133,31 @@ class DragDropController { // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as // the actual drag event dispatch stuff in the dragstate // !!! TODO(multi-display): support other displays final DisplayContent displayContent = callingWin.getDisplayContent(); if (displayContent == null) { Slog.w(TAG_WM, "display content is null"); return false; return null; } final float alpha = (flags & View.DRAG_FLAG_OPAQUE) == 0 ? DRAG_SHADOW_ALPHA_TRANSPARENT : 1; final IBinder winBinder = window.asBinder(); IBinder token = new Binder(); mDragState = new DragState(mService, this, token, surface, flags, winBinder); surface = null; mDragState.mPid = callerPid; mDragState.mUid = callerUid; mDragState.mOriginalAlpha = alpha; mDragState.mToken = dragToken; final Display display = displayContent.getDisplay(); mDragState.register(display); if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, mDragState.getInputChannel())) { Slog.e(TAG_WM, "Unable to transfer touch focus"); return false; return null; } mDragState.mDisplayContent = displayContent; Loading @@ -213,28 +171,31 @@ class DragDropController { // Make the surface visible at the proper location final SurfaceControl surfaceControl = mDragState.mSurfaceControl; if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag"); mService.openSurfaceTransaction(); try { surfaceControl.setPosition(touchX - thumbCenterX, touchY - thumbCenterY); surfaceControl.setLayer(mDragState.getDragLayerLocked()); surfaceControl.setLayerStack(display.getLayerStack()); surfaceControl.show(); } finally { mService.closeSurfaceTransaction("performDrag"); final SurfaceControl.Transaction transaction = callingWin.getPendingTransaction(); transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha); transaction.setPosition( surfaceControl, touchX - thumbCenterX, touchY - thumbCenterY); transaction.show(surfaceControl); displayContent.reparentToOverlay(transaction, surfaceControl); callingWin.scheduleAnimation(); if (SHOW_LIGHT_TRANSACTIONS) { Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag"); } } mDragState.notifyLocationLocked(touchX, touchY); } finally { if (surface != null) { surface.release(); } if (mDragState != null && !mDragState.isInProgress()) { mDragState.closeLocked(); } } } return true; // success! return dragToken; // success! } finally { mCallback.get().postPerformDrag(); } Loading Loading @@ -385,21 +346,6 @@ class DragDropController { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_DRAG_START_TIMEOUT: { IBinder win = (IBinder) msg.obj; if (DEBUG_DRAG) { Slog.w(TAG_WM, "Timeout starting drag by win " + win); } synchronized (mService.mWindowMap) { // !!! TODO: ANR the app that has failed to start the drag in time if (mDragState != null) { mDragState.closeLocked(); } } break; } case MSG_DRAG_END_TIMEOUT: { final IBinder win = (IBinder) msg.obj; if (DEBUG_DRAG) { Loading Loading
core/java/android/view/IWindowSession.aidl +20 −12 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.IWindowId; import android.view.MotionEvent; import android.view.WindowManager; import android.view.Surface; import android.view.SurfaceControl; /** * System private per-application interface to the window manager. Loading Loading @@ -149,18 +150,25 @@ interface IWindowSession { boolean performHapticFeedback(IWindow window, int effectId, boolean always); /** * Allocate the drag's thumbnail surface. Also assigns a token that identifies * the drag to the OS and passes that as the return value. A return value of * null indicates failure. */ IBinder prepareDrag(IWindow window, int flags, int thumbnailWidth, int thumbnailHeight, out Surface outSurface); /** * Initiate the drag operation itself */ boolean performDrag(IWindow window, IBinder dragToken, int touchSource, * * @param window Window which initiates drag operation. * @param flags See {@code View#startDragAndDrop} * @param surface Surface containing drag shadow image * @param touchSource See {@code InputDevice#getSource()} * @param touchX TODO (b/72072998): Fix the issue that the system server misuse the arguments as * initial touch point while the framework passes drag shadow size. * @param touchY TODO (b/72072998): Fix the issue that the system server misuse the arguments as * initial touch point while the framework passes drag shadow size. * @param thumbCenterX X coordinate for the position within the shadow image that should be * underneath the touch point during the drag and drop operation. * @param thumbCenterY Y coordinate for the position within the shadow image that should be * underneath the touch point during the drag and drop operation. * @param data Data transferred by drag and drop * @return Token of drag operation which will be passed to cancelDragAndDrop. */ IBinder performDrag(IWindow window, int flags, in SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, in ClipData data); /** Loading
core/java/android/view/SurfaceControl.aidl 0 → 100644 +19 −0 Original line number Diff line number Diff line /* * 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 android.view; parcelable SurfaceControl;
core/java/android/view/View.java +39 −31 Original line number Diff line number Diff line Loading @@ -23562,15 +23562,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, data.prepareToLeaveProcess((flags & View.DRAG_FLAG_GLOBAL) != 0); } boolean okay = false; Point shadowSize = new Point(); Point shadowTouchPoint = new Point(); shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint); if ((shadowSize.x < 0) || (shadowSize.y < 0) || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { throw new IllegalStateException("Drag shadow dimensions must not be negative"); if ((shadowSize.x <= 0) || (shadowSize.y <= 0) || (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) { throw new IllegalStateException("Drag shadow dimensions must be positive"); } if (ViewDebug.DEBUG_DRAG) { Loading @@ -23581,13 +23579,18 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo.mDragSurface.release(); } mAttachInfo.mDragSurface = new Surface(); mAttachInfo.mDragToken = null; final ViewRootImpl root = mAttachInfo.mViewRootImpl; final SurfaceSession session = new SurfaceSession(root.mSurface); final SurfaceControl surface = new SurfaceControl.Builder(session) .setName("drag surface") .setSize(shadowSize.x, shadowSize.y) .setFormat(PixelFormat.TRANSLUCENT) .build(); try { mAttachInfo.mDragToken = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow, flags, shadowSize.x, shadowSize.y, mAttachInfo.mDragSurface); if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + mAttachInfo.mDragToken + " surface=" + mAttachInfo.mDragSurface); if (mAttachInfo.mDragToken != null) { Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); mAttachInfo.mDragSurface.copyFrom(surface); final Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null); try { canvas.drawColor(0, PorterDuff.Mode.CLEAR); shadowBuilder.onDrawShadow(canvas); Loading @@ -23595,26 +23598,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mAttachInfo.mDragSurface.unlockCanvasAndPost(canvas); } final ViewRootImpl root = getViewRootImpl(); // Cache the local state object for delivery with DragEvents root.setLocalDragState(myLocalState); // repurpose 'shadowSize' for the last touch point root.getLastTouchPoint(shadowSize); okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, mAttachInfo.mDragToken, root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay); mAttachInfo.mDragToken = mAttachInfo.mSession.performDrag( mAttachInfo.mWindow, flags, surface, root.getLastTouchSource(), shadowSize.x, shadowSize.y, shadowTouchPoint.x, shadowTouchPoint.y, data); if (ViewDebug.DEBUG_DRAG) { Log.d(VIEW_LOG_TAG, "performDrag returned " + mAttachInfo.mDragToken); } return mAttachInfo.mDragToken != null; } catch (Exception e) { Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e); return false; } finally { if (mAttachInfo.mDragToken == null) { mAttachInfo.mDragSurface.destroy(); mAttachInfo.mDragSurface = null; root.setLocalDragState(null); } session.kill(); } return okay; } /**
services/core/java/com/android/server/wm/DisplayContent.java +7 −0 Original line number Diff line number Diff line Loading @@ -3697,6 +3697,13 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo .setParent(mOverlayLayer); } /** * Reparents the given surface to mOverlayLayer. */ void reparentToOverlay(Transaction transaction, SurfaceControl surface) { transaction.reparent(surface, mOverlayLayer.getHandle()); } void applyMagnificationSpec(MagnificationSpec spec) { applyMagnificationSpec(getPendingTransaction(), spec); getPendingTransaction().apply(); Loading
services/core/java/com/android/server/wm/DragDropController.java +48 −102 Original line number Diff line number Diff line Loading @@ -18,12 +18,10 @@ package com.android.server.wm; 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.annotation.NonNull; import android.content.ClipData; import android.graphics.PixelFormat; import android.os.Binder; import android.os.Handler; import android.os.IBinder; Loading @@ -32,8 +30,8 @@ import android.os.Message; import android.util.Slog; import android.view.Display; import android.view.IWindow; import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; import android.view.View; Loading @@ -50,10 +48,9 @@ class DragDropController { private static final long DRAG_TIMEOUT_MS = 5000; // Messages for Handler. private static final int MSG_DRAG_START_TIMEOUT = 0; static final int MSG_DRAG_END_TIMEOUT = 1; static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2; static final int MSG_ANIMATION_END = 3; static final int MSG_DRAG_END_TIMEOUT = 0; static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 1; static final int MSG_ANIMATION_END = 2; /** * Drag state per operation. Loading Loading @@ -95,87 +92,35 @@ class DragDropController { mDragState.sendDragStartedIfNeededLocked(window); } IBinder prepareDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) { IBinder performDrag(SurfaceSession session, int callerPid, int callerUid, IWindow window, int flags, SurfaceControl surface, int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY, ClipData data) { if (DEBUG_DRAG) { Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height + " flags=" + Integer.toHexString(flags) + " win=" + window + " asbinder=" + window.asBinder()); } if (width <= 0 || height <= 0) { Slog.w(TAG_WM, "width and height of drag shadow must be positive"); return null; } synchronized (mService.mWindowMap) { if (dragDropActiveLocked()) { Slog.w(TAG_WM, "Drag already in progress"); return null; } // TODO(multi-display): support other displays final DisplayContent displayContent = mService.getDefaultDisplayContentLocked(); final Display display = displayContent.getDisplay(); final SurfaceControl surface = new SurfaceControl.Builder(session) .setName("drag surface") .setSize(width, height) .setFormat(PixelFormat.TRANSLUCENT) .build(); 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(); IBinder token = new Binder(); mDragState = new DragState(mService, 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 sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder); return token; } } 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); Slog.d(TAG_WM, "perform drag: win=" + window + " surface=" + surface + " flags=" + Integer.toHexString(flags) + " data=" + data); } final IBinder dragToken = new Binder(); final boolean callbackResult = mCallback.get().prePerformDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX, thumbCenterY, data); try { synchronized (mService.mWindowMap) { mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder()); try { if (!callbackResult) { return false; Slog.w(TAG_WM, "IDragDropCallback rejects the performDrag request"); return null; } Preconditions.checkState( mDragState != null, "performDrag() without prepareDrag()"); Preconditions.checkState( mDragState.mToken == dragToken, "performDrag() does not match prepareDrag()"); if (dragDropActiveLocked()) { Slog.w(TAG_WM, "Drag already in progress"); return null; } final WindowState callingWin = mService.windowForClientLocked( null, window, false); if (callingWin == null) { Slog.w(TAG_WM, "Bad requesting window " + window); return false; // !!! TODO: throw here? return null; // !!! TODO: throw here? } // !!! TODO: if input is not still focused on the initiating window, fail Loading @@ -188,18 +133,31 @@ class DragDropController { // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as // the actual drag event dispatch stuff in the dragstate // !!! TODO(multi-display): support other displays final DisplayContent displayContent = callingWin.getDisplayContent(); if (displayContent == null) { Slog.w(TAG_WM, "display content is null"); return false; return null; } final float alpha = (flags & View.DRAG_FLAG_OPAQUE) == 0 ? DRAG_SHADOW_ALPHA_TRANSPARENT : 1; final IBinder winBinder = window.asBinder(); IBinder token = new Binder(); mDragState = new DragState(mService, this, token, surface, flags, winBinder); surface = null; mDragState.mPid = callerPid; mDragState.mUid = callerUid; mDragState.mOriginalAlpha = alpha; mDragState.mToken = dragToken; final Display display = displayContent.getDisplay(); mDragState.register(display); if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel, mDragState.getInputChannel())) { Slog.e(TAG_WM, "Unable to transfer touch focus"); return false; return null; } mDragState.mDisplayContent = displayContent; Loading @@ -213,28 +171,31 @@ class DragDropController { // Make the surface visible at the proper location final SurfaceControl surfaceControl = mDragState.mSurfaceControl; if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG_WM, ">>> OPEN TRANSACTION performDrag"); mService.openSurfaceTransaction(); try { surfaceControl.setPosition(touchX - thumbCenterX, touchY - thumbCenterY); surfaceControl.setLayer(mDragState.getDragLayerLocked()); surfaceControl.setLayerStack(display.getLayerStack()); surfaceControl.show(); } finally { mService.closeSurfaceTransaction("performDrag"); final SurfaceControl.Transaction transaction = callingWin.getPendingTransaction(); transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha); transaction.setPosition( surfaceControl, touchX - thumbCenterX, touchY - thumbCenterY); transaction.show(surfaceControl); displayContent.reparentToOverlay(transaction, surfaceControl); callingWin.scheduleAnimation(); if (SHOW_LIGHT_TRANSACTIONS) { Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag"); } } mDragState.notifyLocationLocked(touchX, touchY); } finally { if (surface != null) { surface.release(); } if (mDragState != null && !mDragState.isInProgress()) { mDragState.closeLocked(); } } } return true; // success! return dragToken; // success! } finally { mCallback.get().postPerformDrag(); } Loading Loading @@ -385,21 +346,6 @@ class DragDropController { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_DRAG_START_TIMEOUT: { IBinder win = (IBinder) msg.obj; if (DEBUG_DRAG) { Slog.w(TAG_WM, "Timeout starting drag by win " + win); } synchronized (mService.mWindowMap) { // !!! TODO: ANR the app that has failed to start the drag in time if (mDragState != null) { mDragState.closeLocked(); } } break; } case MSG_DRAG_END_TIMEOUT: { final IBinder win = (IBinder) msg.obj; if (DEBUG_DRAG) { Loading