blob: 1ac9b88749a7895b61fd9d1deb025d9e4a7acbb7 [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
Daichi Hirono58e25e12017-10-25 15:48:08 +090019import static com.android.server.wm.DragDropController.MSG_ANIMATION_END;
20import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT;
21import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080022import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
23import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
24import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
25import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
26import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080027
Daichi Hirono4a700b12017-10-04 15:49:35 +090028import android.animation.Animator;
29import android.animation.PropertyValuesHolder;
30import android.animation.ValueAnimator;
31import android.annotation.Nullable;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080032import android.content.ClipData;
33import android.content.ClipDescription;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080034import android.content.Context;
Craig Mautner39834192012-09-02 07:47:24 -070035import android.graphics.Point;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -080036import android.hardware.input.InputManager;
Yorke Lee0e852472016-06-15 10:03:18 -070037import android.os.Build;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080038import android.os.IBinder;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080039import android.os.Process;
40import android.os.RemoteException;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080041import android.os.ServiceManager;
42import android.os.UserHandle;
43import android.os.UserManager;
44import android.os.IUserManager;
Daichi Hirono01b64502017-12-15 09:49:18 +090045import android.os.UserManagerInternal;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080046import android.util.Slog;
Craig Mautner39834192012-09-02 07:47:24 -070047import android.view.Display;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080048import android.view.DragEvent;
49import android.view.InputChannel;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -080050import android.view.InputDevice;
51import android.view.PointerIcon;
Mathias Agopian3866f0d2013-02-11 22:08:48 -080052import android.view.SurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080053import android.view.View;
54import android.view.WindowManager;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080055import android.view.animation.DecelerateInterpolator;
56import android.view.animation.Interpolator;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080057
Daichi Hirono58e25e12017-10-25 15:48:08 +090058import com.android.internal.view.IDragAndDropPermissions;
Daichi Hirono01b64502017-12-15 09:49:18 +090059import com.android.server.LocalServices;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080060import com.android.server.input.InputApplicationHandle;
61import com.android.server.input.InputWindowHandle;
Vladislav Kaznacheev9149d2b2015-12-15 12:16:28 -080062
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080063import java.util.ArrayList;
64
65/**
66 * Drag/drop state
67 */
68class DragState {
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -080069 private static final long MIN_ANIMATION_DURATION_MS = 195;
70 private static final long MAX_ANIMATION_DURATION_MS = 375;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -080071
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
Daichi Hirono4a700b12017-10-04 15:49:35 +090079 // Property names for animations
80 private static final String ANIMATED_PROPERTY_X = "x";
81 private static final String ANIMATED_PROPERTY_Y = "y";
82 private static final String ANIMATED_PROPERTY_ALPHA = "alpha";
83 private static final String ANIMATED_PROPERTY_SCALE = "scale";
84
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080085 final WindowManagerService mService;
Daichi Hirono58e25e12017-10-25 15:48:08 +090086 final DragDropController mDragDropController;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080087 IBinder mToken;
Daichi Hirono4a700b12017-10-04 15:49:35 +090088 /**
89 * Do not use the variable from the out of animation thread while mAnimator is not null.
90 */
Mathias Agopian29479eb2013-02-14 14:36:04 -080091 SurfaceControl mSurfaceControl;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080092 int mFlags;
93 IBinder mLocalWin;
Vladislav Kaznacheevc7482412015-11-05 14:03:07 -080094 int mPid;
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -070095 int mUid;
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -080096 int mSourceUserId;
97 boolean mCrossProfileCopyAllowed;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -080098 ClipData mData;
99 ClipDescription mDataDescription;
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800100 int mTouchSource;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800101 boolean mDragResult;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800102 float mOriginalAlpha;
103 float mOriginalX, mOriginalY;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800104 float mCurrentX, mCurrentY;
105 float mThumbOffsetX, mThumbOffsetY;
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700106 InputInterceptor mInputInterceptor;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800107 WindowState mTargetWindow;
108 ArrayList<WindowState> mNotifiedWindows;
109 boolean mDragInProgress;
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900110 /**
111 * Whether if animation is completed. Needs to be volatile to update from the animation thread
112 * without having a WM lock.
113 */
114 volatile boolean mAnimationCompleted = false;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800115 DisplayContent mDisplayContent;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800116
Daichi Hirono4a700b12017-10-04 15:49:35 +0900117 @Nullable private ValueAnimator mAnimator;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800118 private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -0800119 private Point mDisplaySize = new Point();
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800120
Daichi Hironoda0748d2017-12-13 12:48:59 +0900121 DragState(WindowManagerService service, DragDropController controller, IBinder token,
122 SurfaceControl surface, int flags, IBinder localWin) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800123 mService = service;
Daichi Hironoda0748d2017-12-13 12:48:59 +0900124 mDragDropController = controller;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800125 mToken = token;
Mathias Agopian29479eb2013-02-14 14:36:04 -0800126 mSurfaceControl = surface;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800127 mFlags = flags;
128 mLocalWin = localWin;
129 mNotifiedWindows = new ArrayList<WindowState>();
130 }
131
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900132 /**
133 * After calling this, DragDropController#onDragStateClosedLocked is invoked, which causes
134 * DragDropController#mDragState becomes null.
135 */
136 void closeLocked() {
137 // Unregister the input interceptor.
138 if (mInputInterceptor != null) {
139 if (DEBUG_DRAG)
140 Slog.d(TAG_WM, "unregistering drag input channel");
141
142 // Input channel should be disposed on the thread where the input is being handled.
143 mDragDropController.sendHandlerMessage(
144 MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor);
145 mInputInterceptor = null;
146 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
147 }
148
149 // Send drag end broadcast if drag start has been sent.
150 if (mDragInProgress) {
151 final int myPid = Process.myPid();
152
153 if (DEBUG_DRAG) {
154 Slog.d(TAG_WM, "broadcasting DRAG_ENDED");
155 }
156 for (WindowState ws : mNotifiedWindows) {
157 float x = 0;
158 float y = 0;
159 if (!mDragResult && (ws.mSession.mPid == mPid)) {
160 // Report unconsumed drop location back to the app that started the drag.
161 x = mCurrentX;
162 y = mCurrentY;
163 }
164 DragEvent evt = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED,
165 x, y, null, null, null, null, mDragResult);
166 try {
167 ws.mClient.dispatchDragEvent(evt);
168 } catch (RemoteException e) {
169 Slog.w(TAG_WM, "Unable to drag-end window " + ws);
170 }
171 // if the current window is in the same process,
172 // the dispatch has already recycled the event
173 if (myPid != ws.mSession.mPid) {
174 evt.recycle();
175 }
176 }
177 mNotifiedWindows.clear();
178 mDragInProgress = false;
179 }
180
181 // Take the cursor back if it has been changed.
182 if (isFromSource(InputDevice.SOURCE_MOUSE)) {
183 mService.restorePointerIconLocked(mDisplayContent, mCurrentX, mCurrentY);
184 mTouchSource = 0;
185 }
186
187 // Clear the internal variables.
188 if (mSurfaceControl != null) {
189 mSurfaceControl.destroy();
190 mSurfaceControl = null;
191 }
192 if (mAnimator != null && !mAnimationCompleted) {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900193 Slog.wtf(TAG_WM,
194 "Unexpectedly destroying mSurfaceControl while animation is running");
195 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800196 mFlags = 0;
197 mLocalWin = null;
198 mToken = null;
199 mData = null;
200 mThumbOffsetX = mThumbOffsetY = 0;
201 mNotifiedWindows = null;
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900202
203 // Notifies the controller that the drag state is closed.
204 mDragDropController.onDragStateClosedLocked(this);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800205 }
206
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700207 class InputInterceptor {
208 InputChannel mServerChannel, mClientChannel;
209 DragInputEventReceiver mInputEventReceiver;
210 InputApplicationHandle mDragApplicationHandle;
211 InputWindowHandle mDragWindowHandle;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800212
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700213 InputInterceptor(Display display) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800214 InputChannel[] channels = InputChannel.openInputChannelPair("drag");
215 mServerChannel = channels[0];
216 mClientChannel = channels[1];
217 mService.mInputManager.registerInputChannel(mServerChannel, null);
Daichi Hirono52cb2152017-09-11 15:29:42 +0900218 mInputEventReceiver = new DragInputEventReceiver(mClientChannel,
Daichi Hirono768012e2017-10-30 10:05:37 +0900219 mService.mH.getLooper(), mDragDropController);
Jeff Brownea426552011-07-18 16:53:48 -0700220
221 mDragApplicationHandle = new InputApplicationHandle(null);
222 mDragApplicationHandle.name = "drag";
223 mDragApplicationHandle.dispatchingTimeoutNanos =
224 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
225
Vladislav Kaznacheev3787de12016-12-21 10:36:35 -0800226 mDragWindowHandle = new InputWindowHandle(mDragApplicationHandle, null, null,
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800227 display.getDisplayId());
Jeff Brownea426552011-07-18 16:53:48 -0700228 mDragWindowHandle.name = "drag";
229 mDragWindowHandle.inputChannel = mServerChannel;
Daichi Hirono58e25e12017-10-25 15:48:08 +0900230 mDragWindowHandle.layer = getDragLayerLocked();
Jeff Brownea426552011-07-18 16:53:48 -0700231 mDragWindowHandle.layoutParamsFlags = 0;
232 mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
233 mDragWindowHandle.dispatchingTimeoutNanos =
234 WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
235 mDragWindowHandle.visible = true;
236 mDragWindowHandle.canReceiveKeys = false;
237 mDragWindowHandle.hasFocus = true;
238 mDragWindowHandle.hasWallpaper = false;
239 mDragWindowHandle.paused = false;
240 mDragWindowHandle.ownerPid = Process.myPid();
241 mDragWindowHandle.ownerUid = Process.myUid();
242 mDragWindowHandle.inputFeatures = 0;
243 mDragWindowHandle.scaleFactor = 1.0f;
244
245 // The drag window cannot receive new touches.
246 mDragWindowHandle.touchableRegion.setEmpty();
247
248 // The drag window covers the entire display
249 mDragWindowHandle.frameLeft = 0;
250 mDragWindowHandle.frameTop = 0;
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -0800251 mDragWindowHandle.frameRight = mDisplaySize.x;
252 mDragWindowHandle.frameBottom = mDisplaySize.y;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700253
254 // Pause rotations before a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800255 if (DEBUG_ORIENTATION) {
256 Slog.d(TAG_WM, "Pausing rotation during drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700257 }
258 mService.pauseRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800259 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800260
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700261 void tearDown() {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800262 mService.mInputManager.unregisterInputChannel(mServerChannel);
Jeff Brown32cbc38552011-12-01 14:01:49 -0800263 mInputEventReceiver.dispose();
264 mInputEventReceiver = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800265 mClientChannel.dispose();
266 mServerChannel.dispose();
267 mClientChannel = null;
268 mServerChannel = null;
Jeff Browncc4f7db2011-08-30 20:34:48 -0700269
270 mDragWindowHandle = null;
271 mDragApplicationHandle = null;
Jeff Brown01a98dd2011-09-20 15:08:29 -0700272
273 // Resume rotations after a drag.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800274 if (DEBUG_ORIENTATION) {
275 Slog.d(TAG_WM, "Resuming rotation after drag");
Jeff Brown01a98dd2011-09-20 15:08:29 -0700276 }
277 mService.resumeRotationLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800278 }
279 }
280
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700281 InputChannel getInputChannel() {
282 return mInputInterceptor == null ? null : mInputInterceptor.mServerChannel;
283 }
284
285 InputWindowHandle getInputWindowHandle() {
286 return mInputInterceptor == null ? null : mInputInterceptor.mDragWindowHandle;
287 }
288
289 /**
290 * @param display The Display that the window being dragged is on.
291 */
292 void register(Display display) {
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -0800293 display.getRealSize(mDisplaySize);
Vladislav Kaznacheev64b103a2016-08-10 11:49:08 -0700294 if (DEBUG_DRAG) Slog.d(TAG_WM, "registering drag input channel");
295 if (mInputInterceptor != null) {
296 Slog.e(TAG_WM, "Duplicate register of drag input channel");
297 } else {
298 mInputInterceptor = new InputInterceptor(display);
299 mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
300 }
301 }
302
Daichi Hirono58e25e12017-10-25 15:48:08 +0900303 int getDragLayerLocked() {
Wale Ogunwale5cd907d2017-01-26 14:14:08 -0800304 return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800305 * WindowManagerService.TYPE_LAYER_MULTIPLIER
306 + WindowManagerService.TYPE_LAYER_OFFSET;
307 }
308
309 /* call out to each visible window/session informing it about the drag
310 */
Daichi Hirono58e25e12017-10-25 15:48:08 +0900311 void broadcastDragStartedLocked(final float touchX, final float touchY) {
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800312 mOriginalX = mCurrentX = touchX;
313 mOriginalY = mCurrentY = touchY;
314
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800315 // Cache a base-class instance of the clip metadata so that parceling
316 // works correctly in calling out to the apps.
317 mDataDescription = (mData != null) ? mData.getDescription() : null;
318 mNotifiedWindows.clear();
319 mDragInProgress = true;
320
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800321 mSourceUserId = UserHandle.getUserId(mUid);
322
Daichi Hirono01b64502017-12-15 09:49:18 +0900323 final UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
324 mCrossProfileCopyAllowed = !userManager.getUserRestriction(
325 mSourceUserId, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE);
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800326
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800327 if (DEBUG_DRAG) {
328 Slog.d(TAG_WM, "broadcasting DRAG_STARTED at (" + touchX + ", " + touchY + ")");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800329 }
330
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800331 mDisplayContent.forAllWindows(w -> {
Daichi Hirono58e25e12017-10-25 15:48:08 +0900332 sendDragStartedLocked(w, touchX, touchY, mDataDescription);
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800333 }, false /* traverseTopToBottom */ );
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800334 }
335
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800336 /* helper - send a ACTION_DRAG_STARTED event, if the
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800337 * designated window is potentially a drop recipient. There are race situations
338 * around DRAG_ENDED broadcast, so we make sure that once we've declared that
339 * the drag has ended, we never send out another DRAG_STARTED for this drag action.
340 *
341 * This method clones the 'event' parameter if it's being delivered to the same
342 * process, so it's safe for the caller to call recycle() on the event afterwards.
343 */
Daichi Hirono58e25e12017-10-25 15:48:08 +0900344 private void sendDragStartedLocked(WindowState newWin, float touchX, float touchY,
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800345 ClipDescription desc) {
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800346 if (mDragInProgress && isValidDropTarget(newWin)) {
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700347 DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700348 touchX, touchY, null, desc, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800349 try {
350 newWin.mClient.dispatchDragEvent(event);
351 // track each window that we've notified that the drag is starting
352 mNotifiedWindows.add(newWin);
353 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800354 Slog.w(TAG_WM, "Unable to drag-start window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800355 } finally {
356 // if the callee was local, the dispatch has already recycled the event
357 if (Process.myPid() != newWin.mSession.mPid) {
358 event.recycle();
359 }
360 }
361 }
362 }
363
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800364 private boolean isValidDropTarget(WindowState targetWin) {
365 if (targetWin == null) {
366 return false;
367 }
368 if (!targetWin.isPotentialDragTarget()) {
369 return false;
370 }
Yorke Lee0e852472016-06-15 10:03:18 -0700371 if ((mFlags & View.DRAG_FLAG_GLOBAL) == 0 || !targetWindowSupportsGlobalDrag(targetWin)) {
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800372 // Drag is limited to the current window.
373 if (mLocalWin != targetWin.mClient.asBinder()) {
374 return false;
375 }
376 }
377
378 return mCrossProfileCopyAllowed ||
379 mSourceUserId == UserHandle.getUserId(targetWin.getOwningUid());
380 }
381
Yorke Lee0e852472016-06-15 10:03:18 -0700382 private boolean targetWindowSupportsGlobalDrag(WindowState targetWin) {
383 // Global drags are limited to system windows, and windows for apps that are targeting N and
384 // above.
385 return targetWin.mAppToken == null
Wale Ogunwale72919d22016-12-08 18:58:50 -0800386 || targetWin.mAppToken.mTargetSdk >= Build.VERSION_CODES.N;
Yorke Lee0e852472016-06-15 10:03:18 -0700387 }
388
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800389 /* helper - send a ACTION_DRAG_STARTED event only if the window has not
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800390 * previously been notified, i.e. it became visible after the drag operation
391 * was begun. This is a rare case.
392 */
Daichi Hirono58e25e12017-10-25 15:48:08 +0900393 void sendDragStartedIfNeededLocked(WindowState newWin) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800394 if (mDragInProgress) {
395 // If we have sent the drag-started, we needn't do so again
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800396 if (isWindowNotified(newWin)) {
397 return;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800398 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800399 if (DEBUG_DRAG) {
400 Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800401 }
Daichi Hirono58e25e12017-10-25 15:48:08 +0900402 sendDragStartedLocked(newWin, mCurrentX, mCurrentY, mDataDescription);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800403 }
404 }
405
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800406 private boolean isWindowNotified(WindowState newWin) {
407 for (WindowState ws : mNotifiedWindows) {
408 if (ws == newWin) {
409 return true;
410 }
411 }
412 return false;
413 }
414
Daichi Hirono58e25e12017-10-25 15:48:08 +0900415 void endDragLocked() {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900416 if (mAnimator != null) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800417 return;
418 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800419 if (!mDragResult) {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900420 mAnimator = createReturnAnimationLocked();
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900421 return; // Will call closeLocked() when the animation is done.
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800422 }
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900423 closeLocked();
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800424 }
425
Daichi Hirono58e25e12017-10-25 15:48:08 +0900426 void cancelDragLocked() {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900427 if (mAnimator != null) {
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800428 return;
429 }
Daichi Hirono4a700b12017-10-04 15:49:35 +0900430 if (!mDragInProgress) {
431 // This can happen if an app invokes Session#cancelDragAndDrop before
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900432 // Session#performDrag. Reset the drag state without playing the cancel animation
433 // because H.DRAG_START_TIMEOUT may be sent to WindowManagerService, which will cause
434 // DragState#reset() while playing the cancel animation.
435 closeLocked();
Daichi Hirono4a700b12017-10-04 15:49:35 +0900436 return;
437 }
438 mAnimator = createCancelAnimationLocked();
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800439 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800440
Daichi Hirono58e25e12017-10-25 15:48:08 +0900441 void notifyMoveLocked(float x, float y) {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900442 if (mAnimator != null) {
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800443 return;
444 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800445 mCurrentX = x;
446 mCurrentY = y;
447
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800448 // Move the surface to the given touch
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800449 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
Daichi Hirono58e25e12017-10-25 15:48:08 +0900450 TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
Robert Carr68e5c9e2016-09-14 10:50:09 -0700451 mService.openSurfaceTransaction();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800452 try {
Mathias Agopian29479eb2013-02-14 14:36:04 -0800453 mSurfaceControl.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800454 if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, " DRAG "
Mathias Agopian29479eb2013-02-14 14:36:04 -0800455 + mSurfaceControl + ": pos=(" +
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800456 (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
457 } finally {
Adrian Roos111aff92017-09-27 18:11:46 +0200458 mService.closeSurfaceTransaction("notifyMoveLw");
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800459 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
Daichi Hirono58e25e12017-10-25 15:48:08 +0900460 TAG_WM, "<<< CLOSE TRANSACTION notifyMoveLocked");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800461 }
Daichi Hirono58e25e12017-10-25 15:48:08 +0900462 notifyLocationLocked(x, y);
Vladislav Kaznacheevd0ed8932016-01-15 15:37:05 -0800463 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800464
Daichi Hirono58e25e12017-10-25 15:48:08 +0900465 void notifyLocationLocked(float x, float y) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800466 // Tell the affected window
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800467 WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
Vladislav Kaznacheev598d40d2016-04-19 15:24:52 -0700468 if (touchedWin != null && !isWindowNotified(touchedWin)) {
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800469 // The drag point is over a window which was not notified about a drag start.
470 // Pretend it's over empty space.
471 touchedWin = null;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800472 }
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800473
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800474 try {
Vladislav Kaznacheevd0ed8932016-01-15 15:37:05 -0800475 final int myPid = Process.myPid();
476
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800477 // have we dragged over a new window?
478 if ((touchedWin != mTargetWindow) && (mTargetWindow != null)) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800479 if (DEBUG_DRAG) {
480 Slog.d(TAG_WM, "sending DRAG_EXITED to " + mTargetWindow);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800481 }
482 // force DRAG_EXITED_EVENT if appropriate
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700483 DragEvent evt = obtainDragEvent(mTargetWindow, DragEvent.ACTION_DRAG_EXITED,
Vladislav Kaznacheevcc010b22016-01-21 16:24:40 -0800484 0, 0, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800485 mTargetWindow.mClient.dispatchDragEvent(evt);
486 if (myPid != mTargetWindow.mSession.mPid) {
487 evt.recycle();
488 }
489 }
490 if (touchedWin != null) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800491 if (false && DEBUG_DRAG) {
492 Slog.d(TAG_WM, "sending DRAG_LOCATION to " + touchedWin);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800493 }
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700494 DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DRAG_LOCATION,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700495 x, y, null, null, null, null, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800496 touchedWin.mClient.dispatchDragEvent(evt);
497 if (myPid != touchedWin.mSession.mPid) {
498 evt.recycle();
499 }
500 }
501 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800502 Slog.w(TAG_WM, "can't send drag notification to windows");
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800503 }
504 mTargetWindow = touchedWin;
505 }
506
Daichi Hirono768012e2017-10-30 10:05:37 +0900507 /**
508 * Finds the drop target and tells it about the data. If the drop event is not sent to the
509 * target, invokes {@code endDragLocked} immediately.
510 */
511 void notifyDropLocked(float x, float y) {
Daichi Hirono4a700b12017-10-04 15:49:35 +0900512 if (mAnimator != null) {
Daichi Hirono768012e2017-10-30 10:05:37 +0900513 return;
Vladislav Kaznacheeva56b2b92015-11-20 18:30:21 -0800514 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800515 mCurrentX = x;
516 mCurrentY = y;
517
Daichi Hirono768012e2017-10-30 10:05:37 +0900518 final WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800519
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800520 if (!isWindowNotified(touchedWin)) {
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800521 // "drop" outside a valid window -- no recipient to apply a
522 // timeout to, and we can send the drag-ended message immediately.
523 mDragResult = false;
Daichi Hirono768012e2017-10-30 10:05:37 +0900524 endDragLocked();
525 return;
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800526 }
527
Daichi Hirono768012e2017-10-30 10:05:37 +0900528 if (DEBUG_DRAG) Slog.d(TAG_WM, "sending DROP to " + touchedWin);
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800529
530 final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
531
Daichi Hirono768012e2017-10-30 10:05:37 +0900532 final DragAndDropPermissionsHandler dragAndDropPermissions;
Daichi Hironoda0748d2017-12-13 12:48:59 +0900533 if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
534 && mData != null) {
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -0700535 dragAndDropPermissions = new DragAndDropPermissionsHandler(
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800536 mData,
537 mUid,
538 touchedWin.getOwningPackage(),
539 mFlags & DRAG_FLAGS_URI_PERMISSIONS,
540 mSourceUserId,
541 targetUserId);
Daichi Hirono768012e2017-10-30 10:05:37 +0900542 } else {
543 dragAndDropPermissions = null;
Vladislav Kaznacheev5d6bdeb2016-02-12 17:07:20 -0800544 }
545 if (mSourceUserId != targetUserId){
Daichi Hironoda0748d2017-12-13 12:48:59 +0900546 if (mData != null) {
547 mData.fixUris(mSourceUserId);
548 }
Vladislav Kaznacheevda2f1942016-02-11 18:58:41 -0800549 }
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800550 final int myPid = Process.myPid();
551 final IBinder token = touchedWin.mClient.asBinder();
Daichi Hirono768012e2017-10-30 10:05:37 +0900552 final DragEvent evt = obtainDragEvent(touchedWin, DragEvent.ACTION_DROP, x, y,
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -0700553 null, null, mData, dragAndDropPermissions, false);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800554 try {
555 touchedWin.mClient.dispatchDragEvent(evt);
556
557 // 5 second timeout for this window to respond to the drop
Daichi Hirono58e25e12017-10-25 15:48:08 +0900558 mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, token);
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800559 } catch (RemoteException e) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800560 Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
Daichi Hirono768012e2017-10-30 10:05:37 +0900561 endDragLocked();
Dianne Hackborn6e1eb762011-02-17 16:07:28 -0800562 } finally {
563 if (myPid != touchedWin.mSession.mPid) {
564 evt.recycle();
565 }
566 }
567 mToken = token;
Daichi Hirono58e25e12017-10-25 15:48:08 +0900568 }
569
Daichi Hirono663e9a72017-11-10 13:51:02 +0900570 /**
571 * Returns true if it has sent DRAG_STARTED broadcast out but has not been sent DRAG_END
572 * broadcast.
573 */
574 boolean isInProgress() {
575 return mDragInProgress;
576 }
577
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700578 private static DragEvent obtainDragEvent(WindowState win, int action,
579 float x, float y, Object localState,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700580 ClipDescription description, ClipData data,
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -0700581 IDragAndDropPermissions dragAndDropPermissions,
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700582 boolean result) {
Vladislav Kaznacheev989b58a2016-02-10 12:19:33 -0800583 final float winX = win.translateToWindowX(x);
584 final float winY = win.translateToWindowY(y);
Vladislav Kaznacheevede5f542015-07-15 18:04:04 -0700585 return DragEvent.obtain(action, winX, winY, localState, description, data,
Vladislav Kaznacheev377c3282016-04-20 14:22:23 -0700586 dragAndDropPermissions, result);
Dianne Hackbornffb3d932011-05-17 17:44:51 -0700587 }
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800588
Daichi Hirono4a700b12017-10-04 15:49:35 +0900589 private ValueAnimator createReturnAnimationLocked() {
590 final ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(
591 PropertyValuesHolder.ofFloat(
592 ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX,
593 mOriginalX - mThumbOffsetX),
594 PropertyValuesHolder.ofFloat(
595 ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY,
596 mOriginalY - mThumbOffsetY),
597 PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, 1, 1),
598 PropertyValuesHolder.ofFloat(
599 ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, mOriginalAlpha / 2));
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800600
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -0800601 final float translateX = mOriginalX - mCurrentX;
602 final float translateY = mOriginalY - mCurrentY;
Vladislav Kaznacheevb3665f12016-11-18 15:06:08 -0800603 // Adjust the duration to the travel distance.
604 final double travelDistance = Math.sqrt(translateX * translateX + translateY * translateY);
605 final double displayDiagonal =
606 Math.sqrt(mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
607 final long duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal
608 * (MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
Daichi Hirono4a700b12017-10-04 15:49:35 +0900609 final AnimationListener listener = new AnimationListener();
610 animator.setDuration(duration);
611 animator.setInterpolator(mCubicEaseOutInterpolator);
612 animator.addListener(listener);
613 animator.addUpdateListener(listener);
614
615 mService.mAnimationHandler.post(() -> animator.start());
616 return animator;
Vladislav Kaznacheev8b6f38c2015-11-19 16:00:28 -0800617 }
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800618
Daichi Hirono4a700b12017-10-04 15:49:35 +0900619 private ValueAnimator createCancelAnimationLocked() {
620 final ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(
621 PropertyValuesHolder.ofFloat(
622 ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX, mCurrentX),
623 PropertyValuesHolder.ofFloat(
624 ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY, mCurrentY),
625 PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, 1, 0),
626 PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0));
627 final AnimationListener listener = new AnimationListener();
628 animator.setDuration(MIN_ANIMATION_DURATION_MS);
629 animator.setInterpolator(mCubicEaseOutInterpolator);
630 animator.addListener(listener);
631 animator.addUpdateListener(listener);
632
633 mService.mAnimationHandler.post(() -> animator.start());
634 return animator;
Vladislav Kaznacheevce2aef92015-11-20 18:49:59 -0800635 }
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800636
637 private boolean isFromSource(int source) {
638 return (mTouchSource & source) == source;
639 }
640
Daichi Hirono58e25e12017-10-25 15:48:08 +0900641 void overridePointerIconLocked(int touchSource) {
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800642 mTouchSource = touchSource;
643 if (isFromSource(InputDevice.SOURCE_MOUSE)) {
Michael Wrightf9d9ce772016-05-13 17:44:16 +0100644 InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_GRABBING);
Vladislav Kaznacheevba761122016-01-22 12:09:45 -0800645 }
646 }
Daichi Hirono4a700b12017-10-04 15:49:35 +0900647
Daichi Hirono4a700b12017-10-04 15:49:35 +0900648 private class AnimationListener
649 implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
650 @Override
651 public void onAnimationUpdate(ValueAnimator animation) {
652 try (final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) {
653 transaction.setPosition(
654 mSurfaceControl,
Daichi Hirono971fe912017-11-21 13:10:42 +0900655 (float) animation.getAnimatedValue(ANIMATED_PROPERTY_X),
656 (float) animation.getAnimatedValue(ANIMATED_PROPERTY_Y));
Daichi Hirono4a700b12017-10-04 15:49:35 +0900657 transaction.setAlpha(
658 mSurfaceControl,
Daichi Hirono971fe912017-11-21 13:10:42 +0900659 (float) animation.getAnimatedValue(ANIMATED_PROPERTY_ALPHA));
Daichi Hirono4a700b12017-10-04 15:49:35 +0900660 transaction.setMatrix(
661 mSurfaceControl,
Daichi Hirono971fe912017-11-21 13:10:42 +0900662 (float) animation.getAnimatedValue(ANIMATED_PROPERTY_SCALE), 0,
663 0, (float) animation.getAnimatedValue(ANIMATED_PROPERTY_SCALE));
Daichi Hirono4a700b12017-10-04 15:49:35 +0900664 transaction.apply();
665 }
666 }
667
668 @Override
669 public void onAnimationStart(Animator animator) {}
670
671 @Override
672 public void onAnimationCancel(Animator animator) {}
673
674 @Override
675 public void onAnimationRepeat(Animator animator) {}
676
677 @Override
678 public void onAnimationEnd(Animator animator) {
Daichi Hirono3bae0b02017-10-27 13:05:13 +0900679 mAnimationCompleted = true;
Daichi Hirono4a700b12017-10-04 15:49:35 +0900680 // Updating mDragState requires the WM lock so continues it on the out of
681 // AnimationThread.
Daichi Hirono58e25e12017-10-25 15:48:08 +0900682 mDragDropController.sendHandlerMessage(MSG_ANIMATION_END, null);
Daichi Hirono4a700b12017-10-04 15:49:35 +0900683 }
684 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800685}