blob: d79f0a1bf758652edeab7ffc0de7c01573b8c783 [file] [log] [blame]
Matthew Nga8f24262017-12-19 11:54:24 -08001/*
2 * Copyright (C) 2018 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.statusbar.phone;
18
19import android.animation.Animator;
20import android.animation.AnimatorListenerAdapter;
21import android.animation.AnimatorSet;
Matthew Ng7090a802018-01-19 13:36:22 -080022import android.animation.ArgbEvaluator;
Matthew Nga8f24262017-12-19 11:54:24 -080023import android.animation.ObjectAnimator;
24import android.animation.ValueAnimator;
25import android.animation.ValueAnimator.AnimatorUpdateListener;
26import android.content.Context;
27import android.graphics.Canvas;
Matthew Ng2ea93b72018-03-14 19:43:18 +000028import android.graphics.Matrix;
Matthew Nga8f24262017-12-19 11:54:24 -080029import android.graphics.Paint;
30import android.graphics.Rect;
31import android.os.Handler;
32import android.os.RemoteException;
33import android.util.Log;
34import android.util.Slog;
Matthew Nga8f24262017-12-19 11:54:24 -080035import android.view.GestureDetector;
36import android.view.MotionEvent;
37import android.view.View;
38import android.view.ViewConfiguration;
Matthew Nga8f24262017-12-19 11:54:24 -080039import android.view.WindowManagerGlobal;
40import android.view.animation.DecelerateInterpolator;
41import android.view.animation.Interpolator;
42import android.support.annotation.DimenRes;
43import com.android.systemui.Dependency;
44import com.android.systemui.OverviewProxyService;
45import com.android.systemui.R;
46import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
47import com.android.systemui.shared.recents.IOverviewProxy;
48import com.android.systemui.shared.recents.utilities.Utilities;
49
50import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
51import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
Matthew Ngbd824572018-01-17 16:25:56 -080052import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
53import static com.android.systemui.OverviewProxyService.TAG_OPS;
Winson Chungc4e06202018-02-13 10:37:35 -080054import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
Matthew Nga8f24262017-12-19 11:54:24 -080055
56/**
57 * Class to detect gestures on the navigation bar and implement quick scrub and switch.
58 */
Matthew Ng2ea93b72018-03-14 19:43:18 +000059public class QuickStepController extends GestureDetector.SimpleOnGestureListener implements
Matthew Nga8f24262017-12-19 11:54:24 -080060 GestureHelper {
61
Matthew Ng2ea93b72018-03-14 19:43:18 +000062 private static final String TAG = "QuickStepController";
Matthew Nga8f24262017-12-19 11:54:24 -080063 private static final int QUICK_SWITCH_FLING_VELOCITY = 0;
64 private static final int ANIM_DURATION_MS = 200;
Winson Chungde2a1242018-02-07 15:59:43 -080065 private static final long LONG_PRESS_DELAY_MS = 225;
Matthew Nga8f24262017-12-19 11:54:24 -080066
67 /**
68 * For quick step, set a damping value to allow the button to stick closer its origin position
69 * when dragging before quick scrub is active.
70 */
71 private static final int SWITCH_STICKINESS = 4;
72
73 private NavigationBarView mNavigationBarView;
74 private GestureDetector mGestureDetector;
75
76 private boolean mDraggingActive;
77 private boolean mQuickScrubActive;
Winson Chung49658842018-02-08 12:52:21 -080078 private boolean mAllowQuickSwitch;
Matthew Ng2ea93b72018-03-14 19:43:18 +000079 private boolean mAllowGestureDetection;
80 private boolean mQuickStepStarted;
Matthew Nga8f24262017-12-19 11:54:24 -080081 private float mDownOffset;
82 private float mTranslation;
83 private int mTouchDownX;
84 private int mTouchDownY;
85 private boolean mDragPositive;
86 private boolean mIsVertical;
87 private boolean mIsRTL;
Matthew Ng7090a802018-01-19 13:36:22 -080088 private float mTrackAlpha;
89 private int mLightTrackColor;
90 private int mDarkTrackColor;
91 private float mDarkIntensity;
Winson Chungd10ca302018-02-14 10:13:41 -080092 private View mHomeButtonView;
Matthew Nga8f24262017-12-19 11:54:24 -080093
94 private final Handler mHandler = new Handler();
95 private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
96 private final Rect mTrackRect = new Rect();
Matthew Nga8f24262017-12-19 11:54:24 -080097 private final Paint mTrackPaint = new Paint();
98 private final int mScrollTouchSlop;
99 private final OverviewProxyService mOverviewEventSender;
Matthew Nga8f24262017-12-19 11:54:24 -0800100 private final int mTrackThickness;
101 private final int mTrackPadding;
102 private final ValueAnimator mTrackAnimator;
103 private final ValueAnimator mButtonAnimator;
104 private final AnimatorSet mQuickScrubEndAnimator;
105 private final Context mContext;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000106 private final Matrix mTransformGlobalMatrix = new Matrix();
107 private final Matrix mTransformLocalMatrix = new Matrix();
Matthew Ng7090a802018-01-19 13:36:22 -0800108 private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
Matthew Nga8f24262017-12-19 11:54:24 -0800109
110 private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
Matthew Ng7090a802018-01-19 13:36:22 -0800111 mTrackAlpha = (float) valueAnimator.getAnimatedValue();
Matthew Nga8f24262017-12-19 11:54:24 -0800112 mNavigationBarView.invalidate();
113 };
114
115 private final AnimatorUpdateListener mButtonTranslationListener = animator -> {
116 int pos = (int) animator.getAnimatedValue();
117 if (!mQuickScrubActive) {
118 pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
119 }
Matthew Nga8f24262017-12-19 11:54:24 -0800120 if (mIsVertical) {
Winson Chungd10ca302018-02-14 10:13:41 -0800121 mHomeButtonView.setTranslationY(pos);
Matthew Nga8f24262017-12-19 11:54:24 -0800122 } else {
Winson Chungd10ca302018-02-14 10:13:41 -0800123 mHomeButtonView.setTranslationX(pos);
Matthew Nga8f24262017-12-19 11:54:24 -0800124 }
125 };
126
127 private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
128 @Override
129 public void onAnimationEnd(Animator animation) {
Matthew Nga8f24262017-12-19 11:54:24 -0800130 mQuickScrubActive = false;
131 mTranslation = 0;
Matthew Nged166f92018-02-20 16:22:09 -0800132 mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
133 mHomeButtonView = null;
Matthew Nga8f24262017-12-19 11:54:24 -0800134 }
135 };
136
137 private Runnable mLongPressRunnable = this::startQuickScrub;
138
139 private final GestureDetector.SimpleOnGestureListener mGestureListener =
140 new GestureDetector.SimpleOnGestureListener() {
141 @Override
142 public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
Matthew Ng8f25fb962018-01-16 17:17:24 -0800143 if (!mNavigationBarView.isQuickScrubEnabled() || mQuickScrubActive
144 || !mAllowQuickSwitch
145 || mNavigationBarView.getDownHitTarget() != HIT_TARGET_HOME) {
Matthew Nga8f24262017-12-19 11:54:24 -0800146 return false;
147 }
148 float velocityX = mIsRTL ? -velX : velX;
149 float absVelY = Math.abs(velY);
150 final boolean isValidFling = velocityX > QUICK_SWITCH_FLING_VELOCITY &&
151 mIsVertical ? (absVelY > velocityX) : (velocityX > absVelY);
152 if (isValidFling) {
153 mDraggingActive = false;
Matthew Nged166f92018-02-20 16:22:09 -0800154 animateEnd();
Matthew Nga8f24262017-12-19 11:54:24 -0800155 mHandler.removeCallbacks(mLongPressRunnable);
156 try {
157 final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
158 overviewProxy.onQuickSwitch();
Matthew Ngbd824572018-01-17 16:25:56 -0800159 if (DEBUG_OVERVIEW_PROXY) {
160 Log.d(TAG_OPS, "Quick Switch");
161 }
Matthew Nga8f24262017-12-19 11:54:24 -0800162 } catch (RemoteException e) {
163 Log.e(TAG, "Failed to send start of quick switch.", e);
164 }
Winson Chung4faf38a2018-02-06 08:53:37 -0800165 return true;
Matthew Nga8f24262017-12-19 11:54:24 -0800166 }
Winson Chung4faf38a2018-02-06 08:53:37 -0800167 return false;
Matthew Nga8f24262017-12-19 11:54:24 -0800168 }
169 };
170
Matthew Ng2ea93b72018-03-14 19:43:18 +0000171 public QuickStepController(Context context) {
Matthew Nga8f24262017-12-19 11:54:24 -0800172 mContext = context;
173 mScrollTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Matthew Nga8f24262017-12-19 11:54:24 -0800174 mOverviewEventSender = Dependency.get(OverviewProxyService.class);
175 mGestureDetector = new GestureDetector(mContext, mGestureListener);
176 mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
177 mTrackPadding = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_edge_padding);
Matthew Ng7090a802018-01-19 13:36:22 -0800178 mTrackPaint.setAlpha(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800179
180 mTrackAnimator = ObjectAnimator.ofFloat();
181 mTrackAnimator.addUpdateListener(mTrackAnimatorListener);
Matthew Ng55437a92018-02-23 15:02:07 -0800182 mTrackAnimator.setFloatValues(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800183 mButtonAnimator = ObjectAnimator.ofInt();
184 mButtonAnimator.addUpdateListener(mButtonTranslationListener);
Matthew Ng55437a92018-02-23 15:02:07 -0800185 mButtonAnimator.setIntValues(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800186 mQuickScrubEndAnimator = new AnimatorSet();
187 mQuickScrubEndAnimator.playTogether(mTrackAnimator, mButtonAnimator);
188 mQuickScrubEndAnimator.setDuration(ANIM_DURATION_MS);
189 mQuickScrubEndAnimator.addListener(mQuickScrubEndListener);
190 mQuickScrubEndAnimator.setInterpolator(mQuickScrubEndInterpolator);
191 }
192
193 public void setComponents(NavigationBarView navigationBarView) {
194 mNavigationBarView = navigationBarView;
195 }
196
Winson Chung4faf38a2018-02-06 08:53:37 -0800197 /**
198 * @return true if we want to intercept touch events for quick scrub/switch and prevent proxying
199 * the event to the overview service.
200 */
Matthew Nga8f24262017-12-19 11:54:24 -0800201 @Override
202 public boolean onInterceptTouchEvent(MotionEvent event) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000203 if (!mNavigationBarView.isQuickScrubEnabled()
204 && !mNavigationBarView.isQuickStepSwipeUpEnabled()) {
205 mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
Matthew Nga8f24262017-12-19 11:54:24 -0800206 return false;
207 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000208 mNavigationBarView.requestUnbufferedDispatch(event);
Winson Chungde2a1242018-02-07 15:59:43 -0800209 return handleTouchEvent(event);
210 }
211
212 /**
Matthew Ng2ea93b72018-03-14 19:43:18 +0000213 * @return true if we want to handle touch events for quick scrub/switch or if down event (that
214 * will get consumed and ignored). No events will be proxied to the overview service.
Winson Chungde2a1242018-02-07 15:59:43 -0800215 */
216 @Override
217 public boolean onTouchEvent(MotionEvent event) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000218 // The same down event was just sent on intercept and therefore can be ignored here
219 final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
220 && mOverviewEventSender.getProxy() != null;
221 return ignoreProxyDownEvent || handleTouchEvent(event);
Winson Chungde2a1242018-02-07 15:59:43 -0800222 }
223
224 private boolean handleTouchEvent(MotionEvent event) {
Winson Chungde2a1242018-02-07 15:59:43 -0800225 final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
Winson Chung4faf38a2018-02-06 08:53:37 -0800226 if (mGestureDetector.onTouchEvent(event)) {
Winson Chungde2a1242018-02-07 15:59:43 -0800227 // If the fling has been handled on UP, then skip proxying the UP
Winson Chung4faf38a2018-02-06 08:53:37 -0800228 return true;
229 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000230 final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
Matthew Nga8f24262017-12-19 11:54:24 -0800231 int action = event.getAction();
232 switch (action & MotionEvent.ACTION_MASK) {
233 case MotionEvent.ACTION_DOWN: {
234 int x = (int) event.getX();
235 int y = (int) event.getY();
Winson Chung0be8f082018-02-15 15:52:49 -0800236 // End any existing quickscrub animations before starting the new transition
Matthew Nged166f92018-02-20 16:22:09 -0800237 if (mHomeButtonView != null) {
Winson Chung0be8f082018-02-15 15:52:49 -0800238 mQuickScrubEndAnimator.end();
239 }
Winson Chungd10ca302018-02-14 10:13:41 -0800240 mHomeButtonView = homeButton.getCurrentView();
Matthew Ng2ea93b72018-03-14 19:43:18 +0000241 homeButton.setDelayTouchFeedback(true /* delay */);
242 mTouchDownX = x;
243 mTouchDownY = y;
244 if (homePressed) {
Matthew Nga8f24262017-12-19 11:54:24 -0800245 mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS);
Matthew Nga8f24262017-12-19 11:54:24 -0800246 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000247 mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
248 mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
249 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
250 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
251 mQuickStepStarted = false;
Winson Chung49658842018-02-08 12:52:21 -0800252 mAllowQuickSwitch = true;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000253 mAllowGestureDetection = true;
Matthew Nga8f24262017-12-19 11:54:24 -0800254 break;
255 }
256 case MotionEvent.ACTION_MOVE: {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000257 if (mQuickStepStarted || !mAllowGestureDetection){
258 break;
259 }
260 int x = (int) event.getX();
261 int y = (int) event.getY();
262 int xDiff = Math.abs(x - mTouchDownX);
263 int yDiff = Math.abs(y - mTouchDownY);
264 boolean exceededTouchSlopX = xDiff > mScrollTouchSlop && xDiff > yDiff;
265 boolean exceededTouchSlopY = yDiff > mScrollTouchSlop && yDiff > xDiff;
266 boolean exceededTouchSlop, exceededPerpendicularTouchSlop;
267 int pos, touchDown, offset, trackSize;
Matthew Nge0903c92018-01-17 15:32:41 -0800268
Matthew Ng2ea93b72018-03-14 19:43:18 +0000269 if (mIsVertical) {
270 exceededTouchSlop = exceededTouchSlopY;
271 exceededPerpendicularTouchSlop = exceededTouchSlopX;
272 pos = y;
273 touchDown = mTouchDownY;
274 offset = pos - mTrackRect.top;
275 trackSize = mTrackRect.height();
276 } else {
277 exceededTouchSlop = exceededTouchSlopX;
278 exceededPerpendicularTouchSlop = exceededTouchSlopY;
279 pos = x;
280 touchDown = mTouchDownX;
281 offset = pos - mTrackRect.left;
282 trackSize = mTrackRect.width();
283 }
284 // Decide to start quickstep if dragging away from the navigation bar, otherwise in
285 // the parallel direction, decide to start quickscrub. Only one may run.
286 if (!mDraggingActive && !mQuickScrubActive && exceededPerpendicularTouchSlop) {
287 if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
288 startQuickStep(event);
Winson Chung0e490d922018-03-14 16:08:43 +0000289 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000290 break;
291 }
Winson Chung0e490d922018-03-14 16:08:43 +0000292
Matthew Ng2ea93b72018-03-14 19:43:18 +0000293 // Do not handle quick scrub/switch if disabled or hit target is not home button
294 if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) {
295 break;
296 }
297
298 if (!mDragPositive) {
299 offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
300 }
301
302 // Control the button movement
303 if (!mDraggingActive && exceededTouchSlop) {
304 boolean allowDrag = !mDragPositive
305 ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
306 if (allowDrag) {
307 mDownOffset = offset;
308 homeButton.abortCurrentGesture();
309 mDraggingActive = true;
Winson Chung0e490d922018-03-14 16:08:43 +0000310 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000311 }
312 if (mDraggingActive && (mDragPositive && offset >= 0
313 || !mDragPositive && offset <= 0)) {
314 float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
315 mTranslation = !mDragPositive
316 ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
317 : Utilities.clamp(offset - mDownOffset, 0, trackSize);
318 if (mQuickScrubActive) {
319 try {
320 mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
321 if (DEBUG_OVERVIEW_PROXY) {
322 Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
Winson Chung0e490d922018-03-14 16:08:43 +0000323 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000324 } catch (RemoteException e) {
325 Log.e(TAG, "Failed to send progress of quick scrub.", e);
Winson Chung0e490d922018-03-14 16:08:43 +0000326 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000327 } else {
328 mTranslation /= SWITCH_STICKINESS;
329 }
330 if (mIsVertical) {
331 mHomeButtonView.setTranslationY(mTranslation);
332 } else {
333 mHomeButtonView.setTranslationX(mTranslation);
Matthew Nga8f24262017-12-19 11:54:24 -0800334 }
335 }
336 break;
337 }
338 case MotionEvent.ACTION_CANCEL:
339 case MotionEvent.ACTION_UP:
Winson Chungd10ca302018-02-14 10:13:41 -0800340 endQuickScrub(true /* animate */);
Matthew Nga8f24262017-12-19 11:54:24 -0800341 break;
342 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000343
344 // Proxy motion events to launcher if not handled by quick scrub/switch
345 boolean handled = mDraggingActive || mQuickScrubActive;
346 if (!handled && mAllowGestureDetection) {
347 proxyMotionEvents(event);
348 }
349 return handled || mQuickStepStarted;
Matthew Nga8f24262017-12-19 11:54:24 -0800350 }
351
352 @Override
353 public void onDraw(Canvas canvas) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000354 if (mNavigationBarView.isQuickScrubEnabled()) {
355 return;
356 }
Matthew Ng7090a802018-01-19 13:36:22 -0800357 int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
358 mDarkTrackColor);
359 mTrackPaint.setColor(color);
360 mTrackPaint.setAlpha((int) (mTrackPaint.getAlpha() * mTrackAlpha));
Matthew Nga8f24262017-12-19 11:54:24 -0800361 canvas.drawRect(mTrackRect, mTrackPaint);
362 }
363
364 @Override
365 public void onLayout(boolean changed, int left, int top, int right, int bottom) {
366 final int width = right - left;
367 final int height = bottom - top;
368 final int x1, x2, y1, y2;
369 if (mIsVertical) {
370 x1 = (width - mTrackThickness) / 2;
371 x2 = x1 + mTrackThickness;
372 y1 = mDragPositive ? height / 2 : mTrackPadding;
373 y2 = y1 + height / 2 - mTrackPadding;
374 } else {
375 y1 = (height - mTrackThickness) / 2;
376 y2 = y1 + mTrackThickness;
377 x1 = mDragPositive ? width / 2 : mTrackPadding;
378 x2 = x1 + width / 2 - mTrackPadding;
379 }
380 mTrackRect.set(x1, y1, x2, y2);
Matthew Nga8f24262017-12-19 11:54:24 -0800381 }
382
383 @Override
384 public void onDarkIntensityChange(float intensity) {
Matthew Ng7090a802018-01-19 13:36:22 -0800385 mDarkIntensity = intensity;
386 mNavigationBarView.invalidate();
Matthew Nga8f24262017-12-19 11:54:24 -0800387 }
388
389 @Override
Matthew Nga8f24262017-12-19 11:54:24 -0800390 public void setBarState(boolean isVertical, boolean isRTL) {
Winson Chungd10ca302018-02-14 10:13:41 -0800391 final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
392 if (changed) {
393 // End quickscrub if the state changes mid-transition
394 endQuickScrub(false /* animate */);
395 }
Matthew Nga8f24262017-12-19 11:54:24 -0800396 mIsVertical = isVertical;
397 mIsRTL = isRTL;
398 try {
399 int navbarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
400 mDragPositive = navbarPos == NAV_BAR_LEFT || navbarPos == NAV_BAR_BOTTOM;
401 if (isRTL) {
402 mDragPositive = !mDragPositive;
403 }
404 } catch (RemoteException e) {
405 Slog.e(TAG, "Failed to get nav bar position.", e);
406 }
407 }
408
Matthew Ng2ea93b72018-03-14 19:43:18 +0000409 @Override
410 public void onNavigationButtonLongPress(View v) {
411 mAllowGestureDetection = false;
412 mHandler.removeCallbacksAndMessages(null);
413 }
414
415 private void startQuickStep(MotionEvent event) {
416 mQuickStepStarted = true;
417 event.transform(mTransformGlobalMatrix);
418 try {
419 mOverviewEventSender.getProxy().onQuickStep(event);
420 if (DEBUG_OVERVIEW_PROXY) {
421 Log.d(TAG_OPS, "Quick Step Start");
422 }
423 } catch (RemoteException e) {
424 Log.e(TAG, "Failed to send quick step started.", e);
425 } finally {
426 event.transform(mTransformLocalMatrix);
427 }
428 mOverviewEventSender.notifyQuickStepStarted();
429 mNavigationBarView.getHomeButton().abortCurrentGesture();
430 cancelQuickSwitch();
431 mHandler.removeCallbacksAndMessages(null);
432 }
433
Matthew Nga8f24262017-12-19 11:54:24 -0800434 private void startQuickScrub() {
Matthew Ngfee0b5b2018-02-21 15:38:21 -0800435 if (!mQuickScrubActive && mDraggingActive) {
Matthew Nga8f24262017-12-19 11:54:24 -0800436 mQuickScrubActive = true;
Matthew Ng7090a802018-01-19 13:36:22 -0800437 mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
438 mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
439 mTrackAnimator.setFloatValues(0, 1);
Matthew Nga8f24262017-12-19 11:54:24 -0800440 mTrackAnimator.start();
441 try {
442 mOverviewEventSender.getProxy().onQuickScrubStart();
Matthew Ngbd824572018-01-17 16:25:56 -0800443 if (DEBUG_OVERVIEW_PROXY) {
444 Log.d(TAG_OPS, "Quick Scrub Start");
445 }
Matthew Nga8f24262017-12-19 11:54:24 -0800446 } catch (RemoteException e) {
447 Log.e(TAG, "Failed to send start of quick scrub.", e);
448 }
449 }
450 }
451
Winson Chungd10ca302018-02-14 10:13:41 -0800452 private void endQuickScrub(boolean animate) {
Matthew Nga8f24262017-12-19 11:54:24 -0800453 mHandler.removeCallbacks(mLongPressRunnable);
454 if (mDraggingActive || mQuickScrubActive) {
Matthew Nged166f92018-02-20 16:22:09 -0800455 animateEnd();
Matthew Nga8f24262017-12-19 11:54:24 -0800456 try {
457 mOverviewEventSender.getProxy().onQuickScrubEnd();
Matthew Ngbd824572018-01-17 16:25:56 -0800458 if (DEBUG_OVERVIEW_PROXY) {
459 Log.d(TAG_OPS, "Quick Scrub End");
460 }
Matthew Nga8f24262017-12-19 11:54:24 -0800461 } catch (RemoteException e) {
462 Log.e(TAG, "Failed to send end of quick scrub.", e);
463 }
Matthew Nged166f92018-02-20 16:22:09 -0800464 }
465 if (mHomeButtonView != null && !animate) {
466 mQuickScrubEndAnimator.end();
Matthew Nga8f24262017-12-19 11:54:24 -0800467 }
468 mDraggingActive = false;
469 }
470
Matthew Ng2ea93b72018-03-14 19:43:18 +0000471 private boolean proxyMotionEvents(MotionEvent event) {
472 final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
473 event.transform(mTransformGlobalMatrix);
474 try {
475 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
476 overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
477 }
478 overviewProxy.onMotionEvent(event);
479 if (DEBUG_OVERVIEW_PROXY) {
480 Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
481 }
482 return true;
483 } catch (RemoteException e) {
484 Log.e(TAG, "Callback failed", e);
485 } finally {
486 event.transform(mTransformLocalMatrix);
Matthew Ngdb2734c2018-02-16 16:02:20 -0800487 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000488 return false;
Matthew Ngdb2734c2018-02-16 16:02:20 -0800489 }
490
Winson Chung49658842018-02-08 12:52:21 -0800491 public void cancelQuickSwitch() {
492 mAllowQuickSwitch = false;
493 mHandler.removeCallbacks(mLongPressRunnable);
494 }
495
Matthew Nged166f92018-02-20 16:22:09 -0800496 private void animateEnd() {
497 mButtonAnimator.setIntValues((int) mTranslation, 0);
498 mTrackAnimator.setFloatValues(mTrackAlpha, 0);
Matthew Ng55437a92018-02-23 15:02:07 -0800499 mQuickScrubEndAnimator.setCurrentPlayTime(0);
Matthew Nged166f92018-02-20 16:22:09 -0800500 mQuickScrubEndAnimator.start();
501 }
502
Matthew Nga8f24262017-12-19 11:54:24 -0800503 private int getDimensionPixelSize(Context context, @DimenRes int resId) {
504 return context.getResources().getDimensionPixelSize(resId);
505 }
506}