blob: aace5e7136ca033f196f0b29759f01e4e83e4147 [file] [log] [blame]
Dianne Hackborn6e1eb762011-02-17 16:07:28 -08001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080019import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
20import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
21import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
22import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080024
25import android.content.ClipData;
26import android.content.ClipDescription;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080027import android.content.Context;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080028import android.graphics.Matrix;
Craig Mautner39834192012-09-02 07:47:24 -070029import android.graphics.Point;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -080030import android.hardware.input.InputManager;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080031import android.os.IBinder;
32import android.os.Message;
33import android.os.Process;
34import android.os.RemoteException;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080035import android.os.ServiceManager;
36import android.os.UserHandle;
37import android.os.UserManager;
38import android.os.IUserManager;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080039import android.util.Slog;
Craig Mautner39834192012-09-02 07:47:24 -070040import android.view.Display;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080041import android.view.DragEvent;
42import android.view.InputChannel;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -080043import android.view.InputDevice;
44import android.view.PointerIcon;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080045import android.view.SurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080046import android.view.View;
47import android.view.WindowManager;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080048import android.view.animation.AlphaAnimation;
49import android.view.animation.Animation;
50import android.view.animation.AnimationSet;
51import android.view.animation.DecelerateInterpolator;
52import android.view.animation.Interpolator;
53import android.view.animation.ScaleAnimation;
54import android.view.animation.Transformation;
55import android.view.animation.TranslateAnimation;
56
57import com.android.server.input.InputApplicationHandle;
58import com.android.server.input.InputWindowHandle;
59import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
60import com.android.server.wm.WindowManagerService.H;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080061
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080062import com.android.internal.view.IDropPermissions;
63
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080064import java.util.ArrayList;
65
66/**
67 * Drag/drop state
68 */
69class DragState {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080070 private static final long ANIMATION_DURATION_MS = 500;
71
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -080072 private static final int DRAG_FLAGS_URI_ACCESS = View.DRAG_FLAG_GLOBAL_URI_READ |
73 View.DRAG_FLAG_GLOBAL_URI_WRITE;
74
75 private static final int DRAG_FLAGS_URI_PERMISSIONS = DRAG_FLAGS_URI_ACCESS |
76 View.DRAG_FLAG_GLOBAL_PERSISTABLE_URI_PERMISSION |
77 View.DRAG_FLAG_GLOBAL_PREFIX_URI_PERMISSION;
78
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080079 final WindowManagerService mService;
80 IBinder mToken;
Mathias Agopian29479eb2013-02-14 14:36:04 -080081 SurfaceControl mSurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080082 int mFlags;
83 IBinder mLocalWin;
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -080084 int mPid;
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -070085 int mUid;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080086 int mSourceUserId;
87 boolean mCrossProfileCopyAllowed;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080088 ClipData mData;
89 ClipDescription mDataDescription;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -080090 int mTouchSource;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080091 boolean mDragResult;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080092 float mOriginalAlpha;
93 float mOriginalX, mOriginalY;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080094 float mCurrentX, mCurrentY;
95 float mThumbOffsetX, mThumbOffsetY;
96 InputChannel mServerChannel, mClientChannel;
Jeff Brown32cbc38552011-12-01 14:01:49 -080097 DragInputEventReceiver mInputEventReceiver;
Jeff Brownea426552011-07-18 16:53:48 -070098 InputApplicationHandle mDragApplicationHandle;
99 InputWindowHandle mDragWindowHandle;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800100 WindowState mTargetWindow;
101 ArrayList<WindowState> mNotifiedWindows;
102 boolean mDragInProgress;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800103 DisplayContent mDisplayContent;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800104
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800105 private Animation mAnimation;
106 final Transformation mTransformation = new Transformation();
107 private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
108
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800109 DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800110 int flags, IBinder localWin) {
111 mService = service;
112 mToken = token;
Mathias Agopian29479eb2013-02-14 14:36:04 -0800113 mSurfaceControl = surface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800114 mFlags = flags;
115 mLocalWin = localWin;
116 mNotifiedWindows = new ArrayList<WindowState>();
117 }
118
119 void reset() {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800120 if (mSurfaceControl != null) {
121 mSurfaceControl.destroy();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800122 }
Mathias Agopian29479eb2013-02-14 14:36:04 -0800123 mSurfaceControl = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800124 mFlags = 0;
125 mLocalWin = null;
126 mToken = null;
127 mData = null;
128 mThumbOffsetX = mThumbOffsetY = 0;
129 mNotifiedWindows = null;
130 }
131
Craig Mautner3486b962012-08-27 11:31:24 -0700132 /**
Craig Mautner39834192012-09-02 07:47:24 -0700133 * @param display The Display that the window being dragged is on.
Craig Mautner3486b962012-08-27 11:31:24 -0700134 */
Craig Mautner39834192012-09-02 07:47:24 -0700135 void register(Display display) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800136 if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800137 if (mClientChannel != null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800138 Slog.e(TAG_WM, "Duplicate register of drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800139 } else {
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800140 mDisplayContent = mService.getDisplayContentLocked(display.getDisplayId());
141
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800142 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
143 mServerChannel = channels[0];
144 mClientChannel = channels[1];
145 mService.mInputManager.registerInputChannel(mServerChannel, null);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800146 mInputEventReceiver = mService.new DragInputEventReceiver(mClientChannel,
147 mService.mH.getLooper());
Jeff Brownea426552011-07-18 16:53:48 -0700148
149 mDragApplicationHandle = new InputApplicationHandle(null);
150 mDragApplicationHandle.name = "drag";
151 mDragApplicationHandle.dispatchingTimeoutNanos =
152 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
153
Craig Mautner59c00972012-07-30 12:10:24 -0700154 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null,
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800155 display.getDisplayId());
Jeff Brownea426552011-07-18 16:53:48 -0700156 mDragWindowHandle.name = "drag";
157 mDragWindowHandle.inputChannel = mServerChannel;
158 mDragWindowHandle.layer = getDragLayerLw();
159 mDragWindowHandle.layoutParamsFlags = 0;
160 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
161 mDragWindowHandle.dispatchingTimeoutNanos =
162 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
163 mDragWindowHandle.visible = true;
164 mDragWindowHandle.canReceiveKeys = false;
165 mDragWindowHandle.hasFocus = true;
166 mDragWindowHandle.hasWallpaper = false;
167 mDragWindowHandle.paused = false;
168 mDragWindowHandle.ownerPid = Process.myPid();
169 mDragWindowHandle.ownerUid = Process.myUid();
170 mDragWindowHandle.inputFeatures = 0;
171 mDragWindowHandle.scaleFactor = 1.0f;
172
173 // The drag window cannot receive new touches.
174 mDragWindowHandle.touchableRegion.setEmpty();
175
176 // The drag window covers the entire display
177 mDragWindowHandle.frameLeft = 0;
178 mDragWindowHandle.frameTop = 0;
Craig Mautner39834192012-09-02 07:47:24 -0700179 Point p = new Point();
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800180 display.getRealSize(p);
Craig Mautner39834192012-09-02 07:47:24 -0700181 mDragWindowHandle.frameRight = p.x;
182 mDragWindowHandle.frameBottom = p.y;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700183
184 // Pause rotations before a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800185 if (DEBUG_ORIENTATION) {
186 Slog.d(TAG_WM, "Pausing rotation during drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700187 }
188 mService.pauseRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800189 }
190 }
191
192 void unregister() {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800193 if (DEBUG_DRAG) Slog.d(TAG_WM, "unregistering drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800194 if (mClientChannel == null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800195 Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800196 } else {
197 mService.mInputManager.unregisterInputChannel(mServerChannel);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800198 mInputEventReceiver.dispose();
199 mInputEventReceiver = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800200 mClientChannel.dispose();
201 mServerChannel.dispose();
202 mClientChannel = null;
203 mServerChannel = null;
Jeff Browncc4f7db2011-08-30 20:34:48 -0700204
205 mDragWindowHandle = null;
206 mDragApplicationHandle = null;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700207
208 // Resume rotations after a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800209 if (DEBUG_ORIENTATION) {
210 Slog.d(TAG_WM, "Resuming rotation after drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700211 }
212 mService.resumeRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800213 }
214 }
215
216 int getDragLayerLw() {
217 return mService.mPolicy.windowTypeToLayerLw(WindowManager.LayoutParams.TYPE_DRAG)
218 * WindowManagerService.TYPE_LAYER_MULTIPLIER
219 + WindowManagerService.TYPE_LAYER_OFFSET;
220 }
221
222 /* call out to each visible window/session informing it about the drag
223 */
224 void broadcastDragStartedLw(final float touchX, final float touchY) {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800225 mOriginalX = mCurrentX = touchX;
226 mOriginalY = mCurrentY = touchY;
227
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800228 // Cache a base-class instance of the clip metadata so that parceling
229 // works correctly in calling out to the apps.
230 mDataDescription = (mData != null) ? mData.getDescription() : null;
231 mNotifiedWindows.clear();
232 mDragInProgress = true;
233
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800234 mSourceUserId = UserHandle.getUserId(mUid);
235
236 final IUserManager userManager =
237 (IUserManager) ServiceManager.getService(Context.USER_SERVICE);
238 try {
239 mCrossProfileCopyAllowed = !userManager.getUserRestrictions(mSourceUserId).getBoolean(
240 UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
241 } catch (RemoteException e) {
242 Slog.e(TAG_WM, "Remote Exception calling UserManager: " + e);
243 mCrossProfileCopyAllowed = false;
244 }
245
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800246 if (DEBUG_DRAG) {
247 Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800248 }
249
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800250 final WindowList windows = mDisplayContent.getWindowList();
251 final int N = windows.size();
252 for (int i = 0; i < N; i++) {
253 sendDragStartedLw(windows.get(i), touchX, touchY, mDataDescription);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800254 }
255 }
256
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800257 /* helper - send a ACTION_DRAG_STARTED event, if the
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800258 * designated window is potentially a drop recipient. There are race situations
259 * around DRAG_ENDED broadcast, so we make sure that once we've declared that
260 * the drag has ended, we never send out another DRAG_STARTED for this drag action.
261 *
262 * This method clones the 'event' parameter if it's being delivered to the same
263 * process, so it's safe for the caller to call recycle() on the event afterwards.
264 */
265 private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
266 ClipDescription desc) {
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800267 if (mDragInProgress && isValidDropTarget(newWin)) {
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700268 DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700269 touchX, touchY, null, desc, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800270 try {
271 newWin.mClient.dispatchDragEvent(event);
272 // track each window that we've notified that the drag is starting
273 mNotifiedWindows.add(newWin);
274 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800275 Slog.w(TAG_WM, "Unable to drag-start window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800276 } finally {
277 // if the callee was local, the dispatch has already recycled the event
278 if (Process.myPid() != newWin.mSession.mPid) {
279 event.recycle();
280 }
281 }
282 }
283 }
284
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800285 private boolean isValidDropTarget(WindowState targetWin) {
286 if (targetWin == null) {
287 return false;
288 }
289 if (!targetWin.isPotentialDragTarget()) {
290 return false;
291 }
292 if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0) {
293 // Drag is limited to the current window.
294 if (mLocalWin != targetWin.mClient.asBinder()) {
295 return false;
296 }
297 }
298
299 return mCrossProfileCopyAllowed ||
300 mSourceUserId == UserHandle.getUserId(targetWin.getOwningUid());
301 }
302
303 /* helper - send a ACTION_DRAG_STARTED event only if the window has not
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800304 * previously been notified, i.e. it became visible after the drag operation
305 * was begun. This is a rare case.
306 */
307 void sendDragStartedIfNeededLw(WindowState newWin) {
308 if (mDragInProgress) {
309 // If we have sent the drag-started, we needn't do so again
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800310 if (isWindowNotified(newWin)) {
311 return;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800312 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800313 if (DEBUG_DRAG) {
314 Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800315 }
316 sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
317 }
318 }
319
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800320 private boolean isWindowNotified(WindowState newWin) {
321 for (WindowState ws : mNotifiedWindows) {
322 if (ws == newWin) {
323 return true;
324 }
325 }
326 return false;
327 }
328
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800329 private void broadcastDragEndedLw() {
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700330 final int myPid = Process.myPid();
331
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800332 if (DEBUG_DRAG) {
333 Slog.d(TAG_WM, "broadcasting DRAG_ENDED");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800334 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700335 for (WindowState ws : mNotifiedWindows) {
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -0800336 float x = 0;
337 float y = 0;
338 if (!mDragResult && (ws.mSession.mPid == mPid)) {
339 // Report unconsumed drop location back to the app that started the drag.
340 x = mCurrentX;
341 y = mCurrentY;
342 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700343 DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -0800344 x, y, null, null, null, null, mDragResult);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800345 try {
346 ws.mClient.dispatchDragEvent(evt);
347 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800348 Slog.w(TAG_WM, "Unable to drag-end window " + ws);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800349 }
Vladislav Kaznacheev68dd2e82015-10-22 17:06:40 -0700350 // if the current window is in the same process,
351 // the dispatch has already recycled the event
352 if (myPid != ws.mSession.mPid) {
353 evt.recycle();
354 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800355 }
356 mNotifiedWindows.clear();
357 mDragInProgress = false;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800358 }
359
360 void endDragLw() {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800361 if (mAnimation != null) {
362 return;
363 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800364 if (!mDragResult) {
365 mAnimation = createReturnAnimationLocked();
366 mService.scheduleAnimationLocked();
367 return; // Will call cleanUpDragLw when the animation is done.
368 }
369 cleanUpDragLw();
370 }
371
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800372 void cancelDragLw() {
373 if (mAnimation != null) {
374 return;
375 }
376 mAnimation = createCancelAnimationLocked();
377 mService.scheduleAnimationLocked();
378 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800379
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800380 private void cleanUpDragLw() {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800381 broadcastDragEndedLw();
Vladislav Kaznacheev989b58a2016-02-10 12:19:33 -0800382 if (isFromSource(InputDevice.SOURCE_MOUSE)) {
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800383 mService.restorePointerIconLocked(mDisplayContent, mCurrentX, mCurrentY);
Vladislav Kaznacheev989b58a2016-02-10 12:19:33 -0800384 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800385
386 // stop intercepting input
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800387 unregister();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800388
389 // free our resources and drop all the object references
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800390 reset();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800391 mService.mDragState = null;
Chong Zhang8e89b312015-09-09 15:09:30 -0700392
393 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800394 }
395
396 void notifyMoveLw(float x, float y) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800397 if (mAnimation != null) {
398 return;
399 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800400 mCurrentX = x;
401 mCurrentY = y;
402
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403 // Move the surface to the given touch
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800404 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
405 TAG_WM, ">>> OPEN TRANSACTION notifyMoveLw");
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800406 SurfaceControl.openTransaction();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800407 try {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800408 mSurfaceControl.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800409 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
Mathias Agopian29479eb2013-02-14 14:36:04 -0800410 + mSurfaceControl + ": pos=(" +
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800411 (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
412 } finally {
Mathias Agopian3866f0d2013-02-11 22:08:48 -0800413 SurfaceControl.closeTransaction();
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800414 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
415 TAG_WM, "<<< CLOSE TRANSACTION notifyMoveLw");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800416 }
Vladislav Kaznacheevd0ed8932016-01-15 15:37:05 -0800417 notifyLocationLw(x, y);
418 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800419
Vladislav Kaznacheevd0ed8932016-01-15 15:37:05 -0800420 void notifyLocationLw(float x, float y) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800421 // Tell the affected window
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800422 WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800423 if (touchedWin == null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800424 if (DEBUG_DRAG) Slog.d(TAG_WM, "No touched win at x=" + x + " y=" + y);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800425 return;
426 }
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800427
428 if (!isWindowNotified(touchedWin)) {
429 // The drag point is over a window which was not notified about a drag start.
430 // Pretend it's over empty space.
431 touchedWin = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800432 }
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800433
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800434 try {
Vladislav Kaznacheevd0ed8932016-01-15 15:37:05 -0800435 final int myPid = Process.myPid();
436
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800437 // have we dragged over a new window?
438 if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800439 if (DEBUG_DRAG) {
440 Slog.d(TAG_WM, "sending DRAG_EXITED to " + mTargetWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800441 }
442 // force DRAG_EXITED_EVENT if appropriate
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700443 DragEvent evt = obtainDragEvent(mTargetWindow, DragEvent.ACTION_DRAG_EXITED,
Vladislav Kaznacheevcc010b22016-01-21 16:24:40 -0800444 0, 0, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800445 mTargetWindow.mClient.dispatchDragEvent(evt);
446 if (myPid != mTargetWindow.mSession.mPid) {
447 evt.recycle();
448 }
449 }
450 if (touchedWin != null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800451 if (false && DEBUG_DRAG) {
452 Slog.d(TAG_WM, "sending DRAG_LOCATION to " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800453 }
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700454 DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DRAG_LOCATION,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700455 x, y, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800456 touchedWin.mClient.dispatchDragEvent(evt);
457 if (myPid != touchedWin.mSession.mPid) {
458 evt.recycle();
459 }
460 }
461 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800462 Slog.w(TAG_WM, "can't send drag notification to windows");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800463 }
464 mTargetWindow = touchedWin;
465 }
466
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800467 // Find the drop target and tell it about the data. Returns 'true' if we can immediately
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800468 // dispatch the global drag-ended message, 'false' if we need to wait for a
469 // result from the recipient.
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800470 boolean notifyDropLw(float x, float y) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800471 if (mAnimation != null) {
472 return false;
473 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800474 mCurrentX = x;
475 mCurrentY = y;
476
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800477 WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
478
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800479 if (!isWindowNotified(touchedWin)) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800480 // "drop" outside a valid window -- no recipient to apply a
481 // timeout to, and we can send the drag-ended message immediately.
482 mDragResult = false;
483 return true;
484 }
485
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800486 if (DEBUG_DRAG) {
487 Slog.d(TAG_WM, "sending DROP to " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800488 }
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800489
490 final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
491
492 DropPermissionsHandler dropPermissions = null;
493 if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 &&
494 (mFlags & DRAG_FLAGS_URI_ACCESS) != 0) {
495 dropPermissions = new DropPermissionsHandler(
496 mData,
497 mUid,
498 touchedWin.getOwningPackage(),
499 mFlags & DRAG_FLAGS_URI_PERMISSIONS,
500 mSourceUserId,
501 targetUserId);
502 }
503 if (mSourceUserId != targetUserId){
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800504 mData.fixUris(mSourceUserId);
505 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800506 final int myPid = Process.myPid();
507 final IBinder token = touchedWin.mClient.asBinder();
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700508 DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800509 null, null, mData, dropPermissions, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800510 try {
511 touchedWin.mClient.dispatchDragEvent(evt);
512
513 // 5 second timeout for this window to respond to the drop
514 mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
515 Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
516 mService.mH.sendMessageDelayed(msg, 5000);
517 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800518 Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800519 return true;
520 } finally {
521 if (myPid != touchedWin.mSession.mPid) {
522 evt.recycle();
523 }
524 }
525 mToken = token;
526 return false;
527 }
528
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700529 private static DragEvent obtainDragEvent(WindowState win, int action,
530 float x, float y, Object localState,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700531 ClipDescription description, ClipData data,
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800532 IDropPermissions dropPermissions,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700533 boolean result) {
Vladislav Kaznacheev989b58a2016-02-10 12:19:33 -0800534 final float winX = win.translateToWindowX(x);
535 final float winY = win.translateToWindowY(y);
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700536 return DragEvent.obtain(action, winX, winY, localState, description, data,
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -0800537 dropPermissions, result);
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700538 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800539
540 boolean stepAnimationLocked(long currentTimeMs) {
541 if (mAnimation == null) {
542 return false;
543 }
544
545 mTransformation.clear();
546 if (!mAnimation.getTransformation(currentTimeMs, mTransformation)) {
547 cleanUpDragLw();
548 return false;
549 }
550
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800551 mTransformation.getMatrix().postTranslate(
552 mCurrentX - mThumbOffsetX, mCurrentY - mThumbOffsetY);
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800553 final float tmpFloats[] = mService.mTmpFloats;
554 mTransformation.getMatrix().getValues(tmpFloats);
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800555 mSurfaceControl.setPosition(tmpFloats[Matrix.MTRANS_X], tmpFloats[Matrix.MTRANS_Y]);
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800556 mSurfaceControl.setAlpha(mTransformation.getAlpha());
557 mSurfaceControl.setMatrix(tmpFloats[Matrix.MSCALE_X], tmpFloats[Matrix.MSKEW_Y],
558 tmpFloats[Matrix.MSKEW_X], tmpFloats[Matrix.MSCALE_Y]);
559 return true;
560 }
561
562 private Animation createReturnAnimationLocked() {
563 final AnimationSet set = new AnimationSet(false);
564 set.addAnimation(new TranslateAnimation(
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800565 0, mOriginalX - mCurrentX, 0, mOriginalY - mCurrentY));
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800566 set.addAnimation(new AlphaAnimation(mOriginalAlpha, mOriginalAlpha / 2));
567 set.setDuration(ANIMATION_DURATION_MS);
568 set.setInterpolator(mCubicEaseOutInterpolator);
569 set.initialize(0, 0, 0, 0);
570 set.start(); // Will start on the first call to getTransformation.
571 return set;
572 }
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800573
574 private Animation createCancelAnimationLocked() {
575 final AnimationSet set = new AnimationSet(false);
576 set.addAnimation(new ScaleAnimation(1, 0, 1, 0, mThumbOffsetX, mThumbOffsetY));
577 set.addAnimation(new AlphaAnimation(mOriginalAlpha, 0));
578 set.setDuration(ANIMATION_DURATION_MS);
579 set.setInterpolator(mCubicEaseOutInterpolator);
580 set.initialize(0, 0, 0, 0);
581 set.start(); // Will start on the first call to getTransformation.
582 return set;
583 }
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800584
585 private boolean isFromSource(int source) {
586 return (mTouchSource & source) == source;
587 }
588
589 void overridePointerIconLw(int touchSource) {
590 mTouchSource = touchSource;
591 if (isFromSource(InputDevice.SOURCE_MOUSE)) {
Vladislav Kaznacheevacaa4a22016-03-31 13:18:02 -0700592 InputManager.getInstance().setPointerIconShape(PointerIcon.STYLE_GRABBING);
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800593 }
594 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800595}