blob: 854696ee313d9bf2847b9505ffd24f705af2fad9 [file] [log] [blame]
Winson73bc1592016-10-18 18:47:43 -07001/*
2 * Copyright (C) 2016 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.systemui.pip.phone;
18
Mady Mellor637cd482017-03-21 10:39:42 -070019import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_NONE;
20import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_CLOSE;
21import static com.android.systemui.pip.phone.PipMenuActivityController.MENU_STATE_FULL;
22
Winson Chung87e5d552017-04-05 11:49:38 -070023import android.animation.Animator;
24import android.animation.AnimatorListenerAdapter;
Mady Mellor81d40612017-03-10 15:14:10 -080025import android.animation.ValueAnimator;
26import android.animation.ValueAnimator.AnimatorUpdateListener;
Winson73bc1592016-10-18 18:47:43 -070027import android.app.IActivityManager;
28import android.content.Context;
Mady Mellora7f69742017-02-03 11:00:20 -080029import android.graphics.Point;
Winson73bc1592016-10-18 18:47:43 -070030import android.graphics.PointF;
31import android.graphics.Rect;
Mady Mellord4e40fb2017-01-26 10:43:16 -080032import android.os.Handler;
Winson73bc1592016-10-18 18:47:43 -070033import android.os.RemoteException;
34import android.util.Log;
Mady Mellora7f69742017-02-03 11:00:20 -080035import android.util.Size;
Winson Chung655332c2016-10-31 13:14:28 -070036import android.view.IPinnedStackController;
Winson73bc1592016-10-18 18:47:43 -070037import android.view.MotionEvent;
Winson73bc1592016-10-18 18:47:43 -070038import android.view.ViewConfiguration;
Phil Weaverf00cd142017-03-03 13:44:00 -080039import android.view.accessibility.AccessibilityEvent;
40import android.view.accessibility.AccessibilityManager;
41import android.view.accessibility.AccessibilityNodeInfo;
Winson73bc1592016-10-18 18:47:43 -070042
Winson Chung14fbe142016-12-19 16:18:24 -080043import com.android.internal.logging.MetricsLogger;
44import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Winson Chungcd1ff642016-10-26 09:44:43 -070045import com.android.internal.policy.PipSnapAlgorithm;
Mady Mellor2e138782017-03-27 11:09:50 -070046import com.android.systemui.Dependency;
Mady Mellora7f69742017-02-03 11:00:20 -080047import com.android.systemui.R;
Winson73bc1592016-10-18 18:47:43 -070048import com.android.systemui.statusbar.FlingAnimationUtils;
Mady Mellor2e138782017-03-27 11:09:50 -070049import com.android.systemui.tuner.TunerService;
Winson73bc1592016-10-18 18:47:43 -070050
Winson Chung29a78652017-02-09 18:35:26 -080051import java.io.PrintWriter;
52
Winson73bc1592016-10-18 18:47:43 -070053/**
54 * Manages all the touch handling for PIP on the Phone, including moving, dismissing and expanding
55 * the PIP.
56 */
Mady Mellor8c7dc422017-05-10 12:55:06 -070057public class PipTouchHandler {
Winson73bc1592016-10-18 18:47:43 -070058 private static final String TAG = "PipTouchHandler";
Winson73bc1592016-10-18 18:47:43 -070059
Mady Mellor8c7dc422017-05-10 12:55:06 -070060 // Allow the PIP to be dragged to the edge of the screen to be minimized.
61 private static final boolean ENABLE_MINIMIZE = false;
62 // Allow the PIP to be flung from anywhere on the screen to the bottom to be dismissed.
63 private static final boolean ENABLE_FLING_DISMISS = false;
Mady Mellor2e138782017-03-27 11:09:50 -070064
Winson Chung14fbe142016-12-19 16:18:24 -080065 // These values are used for metrics and should never change
66 private static final int METRIC_VALUE_DISMISSED_BY_TAP = 0;
67 private static final int METRIC_VALUE_DISMISSED_BY_DRAG = 1;
68
Mady Mellor5d58d252017-04-18 12:48:04 -070069 private static final int SHOW_DISMISS_AFFORDANCE_DELAY = 225;
Winson Chungfa7053782016-11-08 15:45:10 -080070
Winson Chung6e35ee1f2017-02-14 12:06:44 -080071 // Allow dragging the PIP to a location to close it
Mady Mellor81d40612017-03-10 15:14:10 -080072 private static final boolean ENABLE_DISMISS_DRAG_TO_EDGE = true;
Winson Chung6e35ee1f2017-02-14 12:06:44 -080073
Winson73bc1592016-10-18 18:47:43 -070074 private final Context mContext;
75 private final IActivityManager mActivityManager;
76 private final ViewConfiguration mViewConfig;
Winson Chung15504af2016-11-02 18:11:36 -070077 private final PipMenuListener mMenuListener = new PipMenuListener();
Winson Chung655332c2016-10-31 13:14:28 -070078 private IPinnedStackController mPinnedStackController;
Winson73bc1592016-10-18 18:47:43 -070079
Winson Chung2a82fe52017-02-02 14:43:34 -080080 private final PipMenuActivityController mMenuController;
81 private final PipDismissViewController mDismissViewController;
Winson Chung14fefc22016-11-02 10:02:29 -070082 private final PipSnapAlgorithm mSnapAlgorithm;
Phil Weaverf00cd142017-03-03 13:44:00 -080083 private final AccessibilityManager mAccessibilityManager;
Wale Ogunwale6455e502017-04-17 14:16:43 -070084 private boolean mShowPipMenuOnAnimationEnd = false;
Winson73bc1592016-10-18 18:47:43 -070085
Winson Chung2a82fe52017-02-02 14:43:34 -080086 // The current movement bounds
87 private Rect mMovementBounds = new Rect();
88
89 // The reference bounds used to calculate the normal/expanded target bounds
90 private Rect mNormalBounds = new Rect();
91 private Rect mNormalMovementBounds = new Rect();
92 private Rect mExpandedBounds = new Rect();
93 private Rect mExpandedMovementBounds = new Rect();
Mady Mellora7f69742017-02-03 11:00:20 -080094 private int mExpandedShortestEdgeSize;
Winson73bc1592016-10-18 18:47:43 -070095
Winson Chungef4dc812017-04-11 13:31:44 -070096 // Used to workaround an issue where the WM rotation happens before we are notified, allowing
97 // us to send stale bounds
98 private int mDeferResizeToNormalBoundsUntilRotation = -1;
99 private int mDisplayRotation;
100
Mady Mellord4e40fb2017-01-26 10:43:16 -0800101 private Handler mHandler = new Handler();
102 private Runnable mShowDismissAffordance = new Runnable() {
103 @Override
104 public void run() {
Mady Mellor60421c92017-03-29 15:27:37 -0700105 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
106 mDismissViewController.showDismissTarget();
Mady Mellord4e40fb2017-01-26 10:43:16 -0800107 }
108 }
109 };
Mady Mellor81d40612017-03-10 15:14:10 -0800110 private ValueAnimator.AnimatorUpdateListener mUpdateScrimListener =
111 new AnimatorUpdateListener() {
112 @Override
113 public void onAnimationUpdate(ValueAnimator animation) {
114 updateDismissFraction();
115 }
116 };
Mady Mellord4e40fb2017-01-26 10:43:16 -0800117
Winson Chungfa7053782016-11-08 15:45:10 -0800118 // Behaviour states
Mady Mellor637cd482017-03-21 10:39:42 -0700119 private int mMenuState;
Winson Chungd2d90972017-02-28 11:40:41 -0800120 private boolean mIsMinimized;
Winson Chung2a82fe52017-02-02 14:43:34 -0800121 private boolean mIsImeShowing;
122 private int mImeHeight;
123 private float mSavedSnapFraction = -1f;
Phil Weaverf00cd142017-03-03 13:44:00 -0800124 private boolean mSendingHoverAccessibilityEvents;
Mady Mellor2fbdd3b2017-03-21 17:45:00 -0700125 private boolean mMovementWithinMinimize;
126 private boolean mMovementWithinDismiss;
Winson73bc1592016-10-18 18:47:43 -0700127
Winson Chungfa7053782016-11-08 15:45:10 -0800128 // Touch state
129 private final PipTouchState mTouchState;
Winson73bc1592016-10-18 18:47:43 -0700130 private final FlingAnimationUtils mFlingAnimationUtils;
Winson Chungfa7053782016-11-08 15:45:10 -0800131 private final PipTouchGesture[] mGestures;
Winson Chung2a82fe52017-02-02 14:43:34 -0800132 private final PipMotionHelper mMotionHelper;
Winson73bc1592016-10-18 18:47:43 -0700133
Winson Chung2a82fe52017-02-02 14:43:34 -0800134 // Temp vars
Winson Chung655332c2016-10-31 13:14:28 -0700135 private final Rect mTmpBounds = new Rect();
136
Winson73bc1592016-10-18 18:47:43 -0700137 /**
Winson Chung15504af2016-11-02 18:11:36 -0700138 * A listener for the PIP menu activity.
139 */
140 private class PipMenuListener implements PipMenuActivityController.Listener {
141 @Override
Mady Mellor637cd482017-03-21 10:39:42 -0700142 public void onPipMenuStateChanged(int menuState, boolean resize) {
143 setMenuState(menuState, resize);
Winson Chung15504af2016-11-02 18:11:36 -0700144 }
Winson Chunga29eb982016-12-14 12:01:27 -0800145
146 @Override
147 public void onPipExpand() {
148 if (!mIsMinimized) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800149 mMotionHelper.expandPip();
Winson Chunga29eb982016-12-14 12:01:27 -0800150 }
151 }
152
153 @Override
154 public void onPipMinimize() {
Winson Chung2a82fe52017-02-02 14:43:34 -0800155 setMinimizedStateInternal(true);
Mady Mellor81d40612017-03-10 15:14:10 -0800156 mMotionHelper.animateToClosestMinimizedState(mMovementBounds, null /* updateListener */);
Winson Chunga29eb982016-12-14 12:01:27 -0800157 }
158
159 @Override
160 public void onPipDismiss() {
Winson Chung2a82fe52017-02-02 14:43:34 -0800161 mMotionHelper.dismissPip();
Winson Chung14fbe142016-12-19 16:18:24 -0800162 MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
163 METRIC_VALUE_DISMISSED_BY_TAP);
Winson Chunga29eb982016-12-14 12:01:27 -0800164 }
Mady Mellor637cd482017-03-21 10:39:42 -0700165
166 @Override
167 public void onPipShowMenu() {
168 mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
169 mMovementBounds, true /* allowMenuTimeout */);
170 }
Winson Chung15504af2016-11-02 18:11:36 -0700171 }
172
Winson Chungd2d90972017-02-28 11:40:41 -0800173 public PipTouchHandler(Context context, IActivityManager activityManager,
174 PipMenuActivityController menuController,
175 InputConsumerController inputConsumerController) {
Winson73bc1592016-10-18 18:47:43 -0700176
177 // Initialize the Pip input consumer
Winson73bc1592016-10-18 18:47:43 -0700178 mContext = context;
179 mActivityManager = activityManager;
Phil Weaverf00cd142017-03-03 13:44:00 -0800180 mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
Winson73bc1592016-10-18 18:47:43 -0700181 mViewConfig = ViewConfiguration.get(context);
Winson Chung15504af2016-11-02 18:11:36 -0700182 mMenuController = menuController;
183 mMenuController.addListener(mMenuListener);
184 mDismissViewController = new PipDismissViewController(context);
Winson Chung14fefc22016-11-02 10:02:29 -0700185 mSnapAlgorithm = new PipSnapAlgorithm(mContext);
Winson Chungfa7053782016-11-08 15:45:10 -0800186 mTouchState = new PipTouchState(mViewConfig);
Winson73bc1592016-10-18 18:47:43 -0700187 mFlingAnimationUtils = new FlingAnimationUtils(context, 2f);
Winson Chunga5acf182017-01-05 16:02:27 -0800188 mGestures = new PipTouchGesture[] {
Mady Mellord4e40fb2017-01-26 10:43:16 -0800189 mDefaultMovementGesture
Winson Chungfa7053782016-11-08 15:45:10 -0800190 };
Winson Chung79f852e2017-05-04 15:06:18 -0700191 mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mMenuController,
192 mSnapAlgorithm, mFlingAnimationUtils);
Mady Mellora7f69742017-02-03 11:00:20 -0800193 mExpandedShortestEdgeSize = context.getResources().getDimensionPixelSize(
194 R.dimen.pip_expanded_shortest_edge_size);
Winson Chungd2d90972017-02-28 11:40:41 -0800195
196 // Register the listener for input consumer touch events
197 inputConsumerController.setTouchListener(this::handleTouchEvent);
Phil Weaverf00cd142017-03-03 13:44:00 -0800198 inputConsumerController.setRegistrationListener(this::onRegistrationChanged);
199 onRegistrationChanged(inputConsumerController.isRegistered());
Winson73bc1592016-10-18 18:47:43 -0700200 }
201
Winson Chung85d39982017-02-24 15:21:25 -0800202 public void setTouchEnabled(boolean enabled) {
203 mTouchState.setAllowTouches(enabled);
204 }
205
Winson Chungac52f282017-03-30 14:44:52 -0700206 public void showPictureInPictureMenu() {
207 // Only show the menu if the user isn't currently interacting with the PiP
208 if (!mTouchState.isUserInteracting()) {
Mady Mellor637cd482017-03-21 10:39:42 -0700209 mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
210 mMovementBounds, false /* allowMenuTimeout */);
Winson Chungac52f282017-03-30 14:44:52 -0700211 }
212 }
213
Winson Chung929d4f72017-01-13 10:21:33 -0800214 public void onActivityPinned() {
215 // Reset some states once we are pinned
Mady Mellor637cd482017-03-21 10:39:42 -0700216 mMenuState = MENU_STATE_NONE;
217
Winson Chung929d4f72017-01-13 10:21:33 -0800218 if (mIsMinimized) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800219 setMinimizedStateInternal(false);
Winson Chung929d4f72017-01-13 10:21:33 -0800220 }
Winson Chungb54b65b2017-04-26 14:02:13 -0700221 cleanUpDismissTarget();
Wale Ogunwale6455e502017-04-17 14:16:43 -0700222 mShowPipMenuOnAnimationEnd = true;
Winson Chung929d4f72017-01-13 10:21:33 -0800223 }
224
Winson Chungac52f282017-03-30 14:44:52 -0700225 public void onPinnedStackAnimationEnded() {
226 // Always synchronize the motion helper bounds once PiP animations finish
227 mMotionHelper.synchronizePinnedStackBounds();
Wale Ogunwale6455e502017-04-17 14:16:43 -0700228
229 if (mShowPipMenuOnAnimationEnd) {
230 mMenuController.showMenu(MENU_STATE_CLOSE, mMotionHelper.getBounds(),
231 mMovementBounds, true /* allowMenuTimeout */);
232 mShowPipMenuOnAnimationEnd = false;
233 }
Winson Chungac52f282017-03-30 14:44:52 -0700234 }
235
Winson Chung303c6b72016-10-24 17:12:49 -0700236 public void onConfigurationChanged() {
Winson Chung2a82fe52017-02-02 14:43:34 -0800237 mMotionHelper.onConfigurationChanged();
238 mMotionHelper.synchronizePinnedStackBounds();
Winson Chung303c6b72016-10-24 17:12:49 -0700239 }
240
Winson Chung2a82fe52017-02-02 14:43:34 -0800241 public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
242 mIsImeShowing = imeVisible;
243 mImeHeight = imeHeight;
244 }
245
Winson Chungbaa7b722017-03-03 21:33:44 -0800246 public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds, Rect animatingBounds,
Winson Chungef4dc812017-04-11 13:31:44 -0700247 boolean fromImeAdjustement, int displayRotation) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800248 // Re-calculate the expanded bounds
249 mNormalBounds = normalBounds;
250 Rect normalMovementBounds = new Rect();
251 mSnapAlgorithm.getMovementBounds(mNormalBounds, insetBounds, normalMovementBounds,
252 mIsImeShowing ? mImeHeight : 0);
Mady Mellora7f69742017-02-03 11:00:20 -0800253
254 // Calculate the expanded size
255 float aspectRatio = (float) normalBounds.width() / normalBounds.height();
256 Point displaySize = new Point();
257 mContext.getDisplay().getRealSize(displaySize);
258 Size expandedSize = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio,
259 mExpandedShortestEdgeSize, displaySize.x, displaySize.y);
260 mExpandedBounds.set(0, 0, expandedSize.getWidth(), expandedSize.getHeight());
Winson Chung2a82fe52017-02-02 14:43:34 -0800261 Rect expandedMovementBounds = new Rect();
262 mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
263 mIsImeShowing ? mImeHeight : 0);
264
265
266 // If this is from an IME adjustment, then we should move the PiP so that it is not occluded
267 // by the IME
268 if (fromImeAdjustement) {
269 if (mTouchState.isUserInteracting()) {
270 // Defer the update of the current movement bounds until after the user finishes
271 // touching the screen
272 } else {
Winson Chungbaa7b722017-03-03 21:33:44 -0800273 final Rect bounds = new Rect(animatingBounds);
Mady Mellor637cd482017-03-21 10:39:42 -0700274 final Rect toMovementBounds = mMenuState == MENU_STATE_FULL
Winson Chung2a82fe52017-02-02 14:43:34 -0800275 ? expandedMovementBounds
276 : normalMovementBounds;
277 if (mIsImeShowing) {
278 // IME visible
279 if (bounds.top == mMovementBounds.bottom) {
280 // If the PIP is currently resting on top of the IME, then adjust it with
281 // the hiding IME
282 bounds.offsetTo(bounds.left, toMovementBounds.bottom);
283 } else {
284 bounds.offset(0, Math.min(0, toMovementBounds.bottom - bounds.top));
285 }
286 } else {
287 // IME hidden
288 if (bounds.top == mMovementBounds.bottom) {
289 // If the PIP is resting on top of the IME, then adjust it with the hiding IME
290 bounds.offsetTo(bounds.left, toMovementBounds.bottom);
291 }
292 }
Winson Chungbaa7b722017-03-03 21:33:44 -0800293 mMotionHelper.animateToIMEOffset(bounds);
Winson Chung2a82fe52017-02-02 14:43:34 -0800294 }
Winson Chung14fbe142016-12-19 16:18:24 -0800295 }
Winson Chunga29eb982016-12-14 12:01:27 -0800296
Winson Chung2a82fe52017-02-02 14:43:34 -0800297 // Update the movement bounds after doing the calculations based on the old movement bounds
298 // above
299 mNormalMovementBounds = normalMovementBounds;
300 mExpandedMovementBounds = expandedMovementBounds;
Winson Chungef4dc812017-04-11 13:31:44 -0700301 mDisplayRotation = displayRotation;
Mady Mellor637cd482017-03-21 10:39:42 -0700302 updateMovementBounds(mMenuState);
Winson Chungef4dc812017-04-11 13:31:44 -0700303
304 // If we have a deferred resize, apply it now
305 if (mDeferResizeToNormalBoundsUntilRotation == displayRotation) {
306 mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
307 mNormalMovementBounds, mMovementBounds, mIsMinimized,
308 true /* immediate */);
309 mSavedSnapFraction = -1f;
310 mDeferResizeToNormalBoundsUntilRotation = -1;
311 }
Winson Chunga29eb982016-12-14 12:01:27 -0800312 }
313
Phil Weaverf00cd142017-03-03 13:44:00 -0800314 private void onRegistrationChanged(boolean isRegistered) {
315 mAccessibilityManager.setPictureInPictureActionReplacingConnection(isRegistered
Winson Chungfe1fa642017-03-13 10:51:22 -0700316 ? new PipAccessibilityInteractionConnection(mMotionHelper,
317 this::onAccessibilityShowMenu, mHandler) : null);
Winson Chungb54b65b2017-04-26 14:02:13 -0700318
319 if (!isRegistered && mTouchState.isUserInteracting()) {
320 // If the input consumer is unregistered while the user is interacting, then we may not
321 // get the final TOUCH_UP event, so clean up the dismiss target as well
322 cleanUpDismissTarget();
323 }
Winson Chungfe1fa642017-03-13 10:51:22 -0700324 }
325
326 private void onAccessibilityShowMenu() {
Mady Mellor637cd482017-03-21 10:39:42 -0700327 mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
328 mMovementBounds, false /* allowMenuTimeout */);
Phil Weaverf00cd142017-03-03 13:44:00 -0800329 }
330
Winson Chung15504af2016-11-02 18:11:36 -0700331 private boolean handleTouchEvent(MotionEvent ev) {
Winson Chung655332c2016-10-31 13:14:28 -0700332 // Skip touch handling until we are bound to the controller
333 if (mPinnedStackController == null) {
Winson Chung15504af2016-11-02 18:11:36 -0700334 return true;
Winson Chung655332c2016-10-31 13:14:28 -0700335 }
336
Winson Chungfa7053782016-11-08 15:45:10 -0800337 // Update the touch state
338 mTouchState.onTouchEvent(ev);
339
Winson73bc1592016-10-18 18:47:43 -0700340 switch (ev.getAction()) {
341 case MotionEvent.ACTION_DOWN: {
Winson Chung2a82fe52017-02-02 14:43:34 -0800342 mMotionHelper.synchronizePinnedStackBounds();
Winson73bc1592016-10-18 18:47:43 -0700343
Winson Chungfa7053782016-11-08 15:45:10 -0800344 for (PipTouchGesture gesture : mGestures) {
345 gesture.onDown(mTouchState);
346 }
Winson73bc1592016-10-18 18:47:43 -0700347 break;
348 }
349 case MotionEvent.ACTION_MOVE: {
Winson Chungfa7053782016-11-08 15:45:10 -0800350 for (PipTouchGesture gesture : mGestures) {
351 if (gesture.onMove(mTouchState)) {
352 break;
Winson73bc1592016-10-18 18:47:43 -0700353 }
354 }
Winson73bc1592016-10-18 18:47:43 -0700355 break;
356 }
357 case MotionEvent.ACTION_UP: {
Winson Chung14fefc22016-11-02 10:02:29 -0700358 // Update the movement bounds again if the state has changed since the user started
359 // dragging (ie. when the IME shows)
Mady Mellor637cd482017-03-21 10:39:42 -0700360 updateMovementBounds(mMenuState);
Winson Chung14fefc22016-11-02 10:02:29 -0700361
Winson Chungfa7053782016-11-08 15:45:10 -0800362 for (PipTouchGesture gesture : mGestures) {
363 if (gesture.onUp(mTouchState)) {
364 break;
Winson Chung5cd26ff2016-10-24 11:50:44 -0700365 }
Winson Chung5cd26ff2016-10-24 11:50:44 -0700366 }
Winson73bc1592016-10-18 18:47:43 -0700367
368 // Fall through to clean up
369 }
370 case MotionEvent.ACTION_CANCEL: {
Winson Chung85d39982017-02-24 15:21:25 -0800371 mTouchState.reset();
Winson73bc1592016-10-18 18:47:43 -0700372 break;
373 }
Phil Weaverf00cd142017-03-03 13:44:00 -0800374 case MotionEvent.ACTION_HOVER_ENTER:
375 case MotionEvent.ACTION_HOVER_MOVE: {
376 if (!mSendingHoverAccessibilityEvents) {
377 AccessibilityEvent event = AccessibilityEvent.obtain(
378 AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
Winson Chungfe1fa642017-03-13 10:51:22 -0700379 AccessibilityNodeInfo info =
380 PipAccessibilityInteractionConnection.obtainRootAccessibilityNodeInfo();
Phil Weaverf00cd142017-03-03 13:44:00 -0800381 event.setSource(info);
382 info.recycle();
383 mAccessibilityManager.sendAccessibilityEvent(event);
384 mSendingHoverAccessibilityEvents = true;
385 }
386 break;
387 }
388 case MotionEvent.ACTION_HOVER_EXIT: {
389 if (mSendingHoverAccessibilityEvents) {
390 AccessibilityEvent event = AccessibilityEvent.obtain(
391 AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
Winson Chungfe1fa642017-03-13 10:51:22 -0700392 AccessibilityNodeInfo info =
393 PipAccessibilityInteractionConnection.obtainRootAccessibilityNodeInfo();
Phil Weaverf00cd142017-03-03 13:44:00 -0800394 event.setSource(info);
395 info.recycle();
396 mAccessibilityManager.sendAccessibilityEvent(event);
397 mSendingHoverAccessibilityEvents = false;
398 }
399 break;
400 }
Winson73bc1592016-10-18 18:47:43 -0700401 }
Mady Mellor637cd482017-03-21 10:39:42 -0700402 return mMenuState == MENU_STATE_NONE;
Winson Chung15504af2016-11-02 18:11:36 -0700403 }
404
405 /**
Mady Mellor81d40612017-03-10 15:14:10 -0800406 * Updates the appearance of the menu and scrim on top of the PiP while dismissing.
407 */
408 void updateDismissFraction() {
409 if (mMenuController != null) {
410 Rect bounds = mMotionHelper.getBounds();
411 final float target = mMovementBounds.bottom + bounds.height();
412 float fraction = 0f;
413 if (bounds.bottom > target) {
414 final float distance = bounds.bottom - target;
415 fraction = Math.min(distance / bounds.height(), 1f);
416 }
Mady Mellor637cd482017-03-21 10:39:42 -0700417 if (Float.compare(fraction, 0f) != 0 || mMenuState != MENU_STATE_NONE) {
Winson Chung87e5d552017-04-05 11:49:38 -0700418 // Update if the fraction > 0, or if fraction == 0 and the menu was already visible
419 mMenuController.setDismissFraction(fraction);
420 }
Mady Mellor81d40612017-03-10 15:14:10 -0800421 }
422 }
423
424 /**
Winson Chunga29eb982016-12-14 12:01:27 -0800425 * Sets the controller to update the system of changes from user interaction.
426 */
427 void setPinnedStackController(IPinnedStackController controller) {
428 mPinnedStackController = controller;
429 }
430
431 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800432 * Sets the minimized state.
Winson Chungdff5c082016-11-02 17:28:03 -0700433 */
Winson Chung2a82fe52017-02-02 14:43:34 -0800434 void setMinimizedStateInternal(boolean isMinimized) {
Mady Mellor8c7dc422017-05-10 12:55:06 -0700435 if (!ENABLE_MINIMIZE) {
Mady Mellor2e138782017-03-27 11:09:50 -0700436 return;
437 }
Winson Chung2a82fe52017-02-02 14:43:34 -0800438 setMinimizedState(isMinimized, false /* fromController */);
Winson Chungdff5c082016-11-02 17:28:03 -0700439 }
440
441 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800442 * Sets the minimized state.
Winson Chungfa7053782016-11-08 15:45:10 -0800443 */
Winson Chung2a82fe52017-02-02 14:43:34 -0800444 void setMinimizedState(boolean isMinimized, boolean fromController) {
Mady Mellor8c7dc422017-05-10 12:55:06 -0700445 if (!ENABLE_MINIMIZE) {
Mady Mellor2e138782017-03-27 11:09:50 -0700446 return;
447 }
Winson Chung2a82fe52017-02-02 14:43:34 -0800448 if (mIsMinimized != isMinimized) {
449 MetricsLogger.action(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MINIMIZED,
450 isMinimized);
451 }
452 mIsMinimized = isMinimized;
453 mSnapAlgorithm.setMinimized(isMinimized);
Winson Chung54f0c652016-12-06 14:46:31 -0800454
Winson Chung2a82fe52017-02-02 14:43:34 -0800455 if (fromController) {
456 if (isMinimized) {
457 // Move the PiP to the new bounds immediately if minimized
458 mMotionHelper.movePip(mMotionHelper.getClosestMinimizedBounds(mNormalBounds,
459 mMovementBounds));
460 }
461 } else if (mPinnedStackController != null) {
Winson Chung54f0c652016-12-06 14:46:31 -0800462 try {
463 mPinnedStackController.setIsMinimized(isMinimized);
464 } catch (RemoteException e) {
465 Log.e(TAG, "Could not set minimized state", e);
466 }
Winson Chungfa7053782016-11-08 15:45:10 -0800467 }
468 }
469
470 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800471 * Sets the menu visibility.
Winson Chungfa7053782016-11-08 15:45:10 -0800472 */
Mady Mellor637cd482017-03-21 10:39:42 -0700473 void setMenuState(int menuState, boolean resize) {
474 if (menuState == MENU_STATE_FULL) {
Winson Chungd2d90972017-02-28 11:40:41 -0800475 // Save the current snap fraction and if we do not drag or move the PiP, then
476 // we store back to this snap fraction. Otherwise, we'll reset the snap
477 // fraction and snap to the closest edge
478 Rect expandedBounds = new Rect(mExpandedBounds);
479 if (resize) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800480 mSavedSnapFraction = mMotionHelper.animateToExpandedState(expandedBounds,
481 mMovementBounds, mExpandedMovementBounds);
Winson Chungd2d90972017-02-28 11:40:41 -0800482 }
Mady Mellor637cd482017-03-21 10:39:42 -0700483 } else if (menuState == MENU_STATE_NONE) {
Winson Chungd2d90972017-02-28 11:40:41 -0800484 // Try and restore the PiP to the closest edge, using the saved snap fraction
485 // if possible
486 if (resize) {
Winson Chungef4dc812017-04-11 13:31:44 -0700487 if (mDeferResizeToNormalBoundsUntilRotation == -1) {
Winson Chungbb233762017-05-15 14:20:46 -0700488 // This is a very special case: when the menu is expanded and visible,
489 // navigating to another activity can trigger auto-enter PiP, and if the
490 // revealed activity has a forced rotation set, then the controller will get
491 // updated with the new rotation of the display. However, at the same time,
492 // SystemUI will try to hide the menu by creating an animation to the normal
493 // bounds which are now stale. In such a case we defer the animation to the
494 // normal bounds until after the next onMovementBoundsChanged() call to get the
495 // bounds in the new orientation
Winson Chungef4dc812017-04-11 13:31:44 -0700496 try {
497 int displayRotation = mPinnedStackController.getDisplayRotation();
498 if (mDisplayRotation != displayRotation) {
499 mDeferResizeToNormalBoundsUntilRotation = displayRotation;
500 }
501 } catch (RemoteException e) {
502 Log.e(TAG, "Could not get display rotation from controller");
503 }
504 }
505
506 if (mDeferResizeToNormalBoundsUntilRotation == -1) {
507 Rect normalBounds = new Rect(mNormalBounds);
508 mMotionHelper.animateToUnexpandedState(normalBounds, mSavedSnapFraction,
509 mNormalMovementBounds, mMovementBounds, mIsMinimized,
510 false /* immediate */);
511 mSavedSnapFraction = -1f;
512 }
513 } else {
Winson Chungbb233762017-05-15 14:20:46 -0700514 // If resizing is not allowed, then the PiP should be frozen until the transition
515 // ends as well
516 setTouchEnabled(false);
Winson Chungef4dc812017-04-11 13:31:44 -0700517 mSavedSnapFraction = -1f;
Winson Chunga29eb982016-12-14 12:01:27 -0800518 }
Winson Chungfa7053782016-11-08 15:45:10 -0800519 }
Mady Mellor637cd482017-03-21 10:39:42 -0700520 mMenuState = menuState;
521 updateMovementBounds(menuState);
522 if (menuState != MENU_STATE_CLOSE) {
523 MetricsLogger.visibility(mContext, MetricsEvent.ACTION_PICTURE_IN_PICTURE_MENU,
524 menuState == MENU_STATE_FULL);
525 }
Winson Chungfa7053782016-11-08 15:45:10 -0800526 }
527
528 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800529 * @return the motion helper.
Winson Chungfa7053782016-11-08 15:45:10 -0800530 */
Winson Chung2a82fe52017-02-02 14:43:34 -0800531 public PipMotionHelper getMotionHelper() {
532 return mMotionHelper;
Winson73bc1592016-10-18 18:47:43 -0700533 }
Winson Chungfa7053782016-11-08 15:45:10 -0800534
535 /**
Winson Chungfa7053782016-11-08 15:45:10 -0800536 * Gesture controlling normal movement of the PIP.
537 */
538 private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
Mady Mellor2fbdd3b2017-03-21 17:45:00 -0700539 // Whether the PiP was on the left side of the screen at the start of the gesture
540 private boolean mStartedOnLeft;
Mady Mellord4e40fb2017-01-26 10:43:16 -0800541
542 @Override
543 public void onDown(PipTouchState touchState) {
Winson Chung85d39982017-02-24 15:21:25 -0800544 if (!touchState.isUserInteracting()) {
545 return;
546 }
547
Mady Mellor2fbdd3b2017-03-21 17:45:00 -0700548 mStartedOnLeft = mMotionHelper.getBounds().left < mMovementBounds.centerX();
549 mMovementWithinMinimize = true;
550 mMovementWithinDismiss = touchState.getDownTouchPosition().y >= mMovementBounds.bottom;
551
Mady Mellora7f69742017-02-03 11:00:20 -0800552 // If the menu is still visible, and we aren't minimized, then just poke the menu
553 // so that it will timeout after the user stops touching it
Mady Mellor637cd482017-03-21 10:39:42 -0700554 if (mMenuState != MENU_STATE_NONE && !mIsMinimized) {
Mady Mellora7f69742017-02-03 11:00:20 -0800555 mMenuController.pokeMenu();
556 }
557
Mady Mellor60421c92017-03-29 15:27:37 -0700558 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
Mady Mellord4e40fb2017-01-26 10:43:16 -0800559 mDismissViewController.createDismissTarget();
560 mHandler.postDelayed(mShowDismissAffordance, SHOW_DISMISS_AFFORDANCE_DELAY);
561 }
562 }
563
Winson Chungfa7053782016-11-08 15:45:10 -0800564 @Override
565 boolean onMove(PipTouchState touchState) {
Winson Chung85d39982017-02-24 15:21:25 -0800566 if (!touchState.isUserInteracting()) {
567 return false;
568 }
569
Winson Chung2a82fe52017-02-02 14:43:34 -0800570 if (touchState.startedDragging()) {
571 mSavedSnapFraction = -1f;
Winson Chung2a82fe52017-02-02 14:43:34 -0800572
Winson Chungb54b65b2017-04-26 14:02:13 -0700573 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
574 mHandler.removeCallbacks(mShowDismissAffordance);
575 mDismissViewController.showDismissTarget();
576 }
Mady Mellord4e40fb2017-01-26 10:43:16 -0800577 }
578
Winson Chungfa7053782016-11-08 15:45:10 -0800579 if (touchState.isDragging()) {
580 // Move the pinned stack freely
Winson Chung2a82fe52017-02-02 14:43:34 -0800581 mTmpBounds.set(mMotionHelper.getBounds());
582 final PointF lastDelta = touchState.getLastTouchDelta();
583 float left = mTmpBounds.left + lastDelta.x;
584 float top = mTmpBounds.top + lastDelta.y;
Mady Mellor8c7dc422017-05-10 12:55:06 -0700585 if (!touchState.allowDraggingOffscreen() || !ENABLE_MINIMIZE) {
Winson Chung2a82fe52017-02-02 14:43:34 -0800586 left = Math.max(mMovementBounds.left, Math.min(mMovementBounds.right, left));
Winson Chungfa7053782016-11-08 15:45:10 -0800587 }
Mady Mellor57d22552017-03-09 15:37:13 -0800588 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
589 // Allow pip to move past bottom bounds
590 top = Math.max(mMovementBounds.top, top);
591 } else {
592 top = Math.max(mMovementBounds.top, Math.min(mMovementBounds.bottom, top));
593 }
Winson Chungfa7053782016-11-08 15:45:10 -0800594 mTmpBounds.offsetTo((int) left, (int) top);
Winson Chung2a82fe52017-02-02 14:43:34 -0800595 mMotionHelper.movePip(mTmpBounds);
596
Mady Mellor81d40612017-03-10 15:14:10 -0800597 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
598 updateDismissFraction();
599 }
Mady Mellor2fbdd3b2017-03-21 17:45:00 -0700600
601 final PointF curPos = touchState.getLastTouchPosition();
602 if (mMovementWithinMinimize) {
603 // Track if movement remains near starting edge to identify swipes to minimize
604 mMovementWithinMinimize = mStartedOnLeft
605 ? curPos.x <= mMovementBounds.left + mTmpBounds.width()
606 : curPos.x >= mMovementBounds.right;
607 }
608 if (mMovementWithinDismiss) {
609 // Track if movement remains near the bottom edge to identify swipe to dismiss
610 mMovementWithinDismiss = curPos.y >= mMovementBounds.bottom;
611 }
Winson Chungfa7053782016-11-08 15:45:10 -0800612 return true;
613 }
614 return false;
615 }
616
617 @Override
618 public boolean onUp(PipTouchState touchState) {
Winson Chungb54b65b2017-04-26 14:02:13 -0700619 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
620 // Clean up the dismiss target regardless of the touch state in case the touch
621 // enabled state changes while the user is interacting
622 cleanUpDismissTarget();
623 }
624
Winson Chung85d39982017-02-24 15:21:25 -0800625 if (!touchState.isUserInteracting()) {
626 return false;
627 }
628
Mady Mellor60421c92017-03-29 15:27:37 -0700629 final PointF vel = touchState.getVelocity();
630 final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
631 final float velocity = PointF.length(vel.x, vel.y);
632 final boolean isFling = velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond();
Mady Mellor8c7dc422017-05-10 12:55:06 -0700633 final boolean isUpWithinDimiss = ENABLE_FLING_DISMISS
Mady Mellor47ba1402017-04-04 17:25:43 -0700634 && touchState.getLastTouchPosition().y >= mMovementBounds.bottom
635 && mMotionHelper.isGestureToDismissArea(mMotionHelper.getBounds(), vel.x,
636 vel.y, isFling);
637 final boolean isFlingToBot = isFling && vel.y > 0 && !isHorizontal
638 && (mMovementWithinDismiss || isUpWithinDimiss);
Mady Mellor60421c92017-03-29 15:27:37 -0700639 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
Winson Chungb54b65b2017-04-26 14:02:13 -0700640 // Check if the user dragged or flung the PiP offscreen to dismiss it
641 if (mMotionHelper.shouldDismissPip() || isFlingToBot) {
642 mMotionHelper.animateDismiss(mMotionHelper.getBounds(), vel.x,
643 vel.y, mUpdateScrimListener);
644 MetricsLogger.action(mContext,
645 MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
646 METRIC_VALUE_DISMISSED_BY_DRAG);
647 return true;
Mady Mellord4e40fb2017-01-26 10:43:16 -0800648 }
Mady Mellord4e40fb2017-01-26 10:43:16 -0800649 }
Winson Chungd2d90972017-02-28 11:40:41 -0800650
Winson Chungfa7053782016-11-08 15:45:10 -0800651 if (touchState.isDragging()) {
Mady Mellor84a0f892017-03-27 14:10:46 -0700652 final boolean isFlingToEdge = isFling && isHorizontal && mMovementWithinMinimize
653 && (mStartedOnLeft ? vel.x < 0 : vel.x > 0);
Mady Mellor8c7dc422017-05-10 12:55:06 -0700654 if (ENABLE_MINIMIZE &&
Mady Mellor2e138782017-03-27 11:09:50 -0700655 !mIsMinimized && (mMotionHelper.shouldMinimizePip() || isFlingToEdge)) {
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800656 // Pip should be minimized
Winson Chung2a82fe52017-02-02 14:43:34 -0800657 setMinimizedStateInternal(true);
Mady Mellor637cd482017-03-21 10:39:42 -0700658 if (mMenuState == MENU_STATE_FULL) {
Winson Chungd2d90972017-02-28 11:40:41 -0800659 // If the user dragged the expanded PiP to the edge, then hiding the menu
660 // will trigger the PiP to be scaled back to the normal size with the
661 // minimize offset adjusted
662 mMenuController.hideMenu();
663 } else {
Mady Mellor81d40612017-03-10 15:14:10 -0800664 mMotionHelper.animateToClosestMinimizedState(mMovementBounds,
665 mUpdateScrimListener);
Winson Chungd2d90972017-02-28 11:40:41 -0800666 }
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800667 return true;
668 }
669 if (mIsMinimized) {
Winson Chungd2d90972017-02-28 11:40:41 -0800670 // If we're dragging and it wasn't a minimize gesture then we shouldn't be
671 // minimized.
Winson Chung2a82fe52017-02-02 14:43:34 -0800672 setMinimizedStateInternal(false);
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800673 }
674
Winson Chung87e5d552017-04-05 11:49:38 -0700675 AnimatorListenerAdapter postAnimationCallback = null;
Mady Mellor637cd482017-03-21 10:39:42 -0700676 if (mMenuState != MENU_STATE_NONE) {
Winson Chung87e5d552017-04-05 11:49:38 -0700677 // If the menu is still visible, and we aren't minimized, then just poke the
678 // menu so that it will timeout after the user stops touching it
Mady Mellor637cd482017-03-21 10:39:42 -0700679 mMenuController.showMenu(mMenuState, mMotionHelper.getBounds(),
680 mMovementBounds, true /* allowMenuTimeout */);
Winson Chung87e5d552017-04-05 11:49:38 -0700681 } else {
682 // If the menu is not visible, then we can still be showing the activity for the
683 // dismiss overlay, so just finish it after the animation completes
684 postAnimationCallback = new AnimatorListenerAdapter() {
685 @Override
686 public void onAnimationEnd(Animator animation) {
687 mMenuController.hideMenu();
688 }
689 };
Winson Chungd2d90972017-02-28 11:40:41 -0800690 }
691
Mady Mellor2fbdd3b2017-03-21 17:45:00 -0700692 if (isFling) {
Mady Mellor81d40612017-03-10 15:14:10 -0800693 mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds,
Winson Chung87e5d552017-04-05 11:49:38 -0700694 mUpdateScrimListener, postAnimationCallback);
Winson Chungfa7053782016-11-08 15:45:10 -0800695 } else {
Winson Chung87e5d552017-04-05 11:49:38 -0700696 mMotionHelper.animateToClosestSnapTarget(mMovementBounds, mUpdateScrimListener,
697 postAnimationCallback);
Winson Chungfa7053782016-11-08 15:45:10 -0800698 }
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800699 } else if (mIsMinimized) {
700 // This was a tap, so no longer minimized
Winson Chung87e5d552017-04-05 11:49:38 -0700701 mMotionHelper.animateToClosestSnapTarget(mMovementBounds, null /* updateListener */,
702 null /* animatorListener */);
Winson Chung2a82fe52017-02-02 14:43:34 -0800703 setMinimizedStateInternal(false);
Mady Mellor637cd482017-03-21 10:39:42 -0700704 } else if (mMenuState != MENU_STATE_FULL) {
705 mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
706 mMovementBounds, true /* allowMenuTimeout */);
Winson Chungfa7053782016-11-08 15:45:10 -0800707 } else {
Winson Chungbe4a8082017-04-13 13:52:04 -0700708 mMenuController.hideMenu();
Winson Chung2a82fe52017-02-02 14:43:34 -0800709 mMotionHelper.expandPip();
Winson Chungfa7053782016-11-08 15:45:10 -0800710 }
711 return true;
712 }
713 };
Mady Mellor3b10dcd2017-01-23 10:08:35 -0800714
715 /**
Winson Chung2a82fe52017-02-02 14:43:34 -0800716 * Updates the current movement bounds based on whether the menu is currently visible.
717 */
Mady Mellor637cd482017-03-21 10:39:42 -0700718 private void updateMovementBounds(int menuState) {
Winson Chunga71febe2017-05-22 11:14:22 -0700719 boolean isMenuExpanded = menuState == MENU_STATE_FULL;
720 mMovementBounds = isMenuExpanded
Winson Chung2a82fe52017-02-02 14:43:34 -0800721 ? mExpandedMovementBounds
722 : mNormalMovementBounds;
Winson Chunga71febe2017-05-22 11:14:22 -0700723 try {
724 mPinnedStackController.setMinEdgeSize(isMenuExpanded ? mExpandedShortestEdgeSize : 0);
725 } catch (RemoteException e) {
726 Log.e(TAG, "Could not set minimized state", e);
727 }
Winson Chung2a82fe52017-02-02 14:43:34 -0800728 }
Winson Chung29a78652017-02-09 18:35:26 -0800729
Winson Chungb54b65b2017-04-26 14:02:13 -0700730 /**
731 * Removes the dismiss target and cancels any pending callbacks to show it.
732 */
733 private void cleanUpDismissTarget() {
734 mHandler.removeCallbacks(mShowDismissAffordance);
735 mDismissViewController.destroyDismissTarget();
736 }
737
Winson Chung29a78652017-02-09 18:35:26 -0800738 public void dump(PrintWriter pw, String prefix) {
739 final String innerPrefix = prefix + " ";
740 pw.println(prefix + TAG);
741 pw.println(innerPrefix + "mMovementBounds=" + mMovementBounds);
742 pw.println(innerPrefix + "mNormalBounds=" + mNormalBounds);
743 pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds);
744 pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds);
745 pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds);
Mady Mellor637cd482017-03-21 10:39:42 -0700746 pw.println(innerPrefix + "mMenuState=" + mMenuState);
Winson Chungd2d90972017-02-28 11:40:41 -0800747 pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
Winson Chung29a78652017-02-09 18:35:26 -0800748 pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
749 pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
750 pw.println(innerPrefix + "mSavedSnapFraction=" + mSavedSnapFraction);
Mady Mellor60421c92017-03-29 15:27:37 -0700751 pw.println(innerPrefix + "mEnableDragToEdgeDismiss=" + ENABLE_DISMISS_DRAG_TO_EDGE);
Mady Mellor8c7dc422017-05-10 12:55:06 -0700752 pw.println(innerPrefix + "mEnableMinimize=" + ENABLE_MINIMIZE);
Winson Chung29a78652017-02-09 18:35:26 -0800753 mSnapAlgorithm.dump(pw, innerPrefix);
754 mTouchState.dump(pw, innerPrefix);
755 mMotionHelper.dump(pw, innerPrefix);
756 }
Phil Weaverf00cd142017-03-03 13:44:00 -0800757
Winson73bc1592016-10-18 18:47:43 -0700758}