Merge "Move drag and drop related lines to DragDropController"
This commit is contained in:
committed by
Android (Google) Code Review
commit
fe0c2c4506
306
services/core/java/com/android/server/wm/DragDropController.java
Normal file
306
services/core/java/com/android/server/wm/DragDropController.java
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user