blob: d3790d4406875efa7896abd293f02046dd9a44ba [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.MotionEvent;
36import android.view.View;
37import android.view.ViewConfiguration;
Matthew Nga8f24262017-12-19 11:54:24 -080038import android.view.WindowManagerGlobal;
39import android.view.animation.DecelerateInterpolator;
40import android.view.animation.Interpolator;
41import android.support.annotation.DimenRes;
42import com.android.systemui.Dependency;
43import com.android.systemui.OverviewProxyService;
44import com.android.systemui.R;
45import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
46import com.android.systemui.shared.recents.IOverviewProxy;
47import com.android.systemui.shared.recents.utilities.Utilities;
48
49import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
50import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
Matthew Ngbd824572018-01-17 16:25:56 -080051import static com.android.systemui.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
52import static com.android.systemui.OverviewProxyService.TAG_OPS;
Winson Chungc4e06202018-02-13 10:37:35 -080053import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
Matthew Ng9a223632018-03-30 16:47:22 -070054import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_SCRUB_DRAG_SLOP_PX;
55import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_SCRUB_TOUCH_SLOP_PX;
56import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_DRAG_SLOP_PX;
57import static com.android.systemui.shared.system.NavigationBarCompat.QUICK_STEP_TOUCH_SLOP_PX;
Matthew Nga8f24262017-12-19 11:54:24 -080058
59/**
Matthew Ngfba39692018-03-13 18:08:34 -070060 * Class to detect gestures on the navigation bar and implement quick scrub.
Matthew Nga8f24262017-12-19 11:54:24 -080061 */
Matthew Ngfba39692018-03-13 18:08:34 -070062public class QuickStepController implements GestureHelper {
Matthew Nga8f24262017-12-19 11:54:24 -080063
Matthew Ng2ea93b72018-03-14 19:43:18 +000064 private static final String TAG = "QuickStepController";
Matthew Nga8f24262017-12-19 11:54:24 -080065 private static final int ANIM_DURATION_MS = 200;
Matthew Nga8f24262017-12-19 11:54:24 -080066
67 private NavigationBarView mNavigationBarView;
Matthew Nga8f24262017-12-19 11:54:24 -080068
Matthew Nga8f24262017-12-19 11:54:24 -080069 private boolean mQuickScrubActive;
Matthew Ng2ea93b72018-03-14 19:43:18 +000070 private boolean mAllowGestureDetection;
71 private boolean mQuickStepStarted;
Matthew Nga8f24262017-12-19 11:54:24 -080072 private float mDownOffset;
73 private float mTranslation;
74 private int mTouchDownX;
75 private int mTouchDownY;
Matthew Ng9a223632018-03-30 16:47:22 -070076 private boolean mDragScrubActive;
Matthew Nga8f24262017-12-19 11:54:24 -080077 private boolean mDragPositive;
78 private boolean mIsVertical;
79 private boolean mIsRTL;
Matthew Ng7090a802018-01-19 13:36:22 -080080 private float mTrackAlpha;
81 private int mLightTrackColor;
82 private int mDarkTrackColor;
83 private float mDarkIntensity;
Winson Chungd10ca302018-02-14 10:13:41 -080084 private View mHomeButtonView;
Matthew Nga8f24262017-12-19 11:54:24 -080085
86 private final Handler mHandler = new Handler();
87 private final Interpolator mQuickScrubEndInterpolator = new DecelerateInterpolator();
88 private final Rect mTrackRect = new Rect();
Matthew Nga8f24262017-12-19 11:54:24 -080089 private final Paint mTrackPaint = new Paint();
Matthew Nga8f24262017-12-19 11:54:24 -080090 private final OverviewProxyService mOverviewEventSender;
Matthew Nga8f24262017-12-19 11:54:24 -080091 private final int mTrackThickness;
92 private final int mTrackPadding;
93 private final ValueAnimator mTrackAnimator;
94 private final ValueAnimator mButtonAnimator;
95 private final AnimatorSet mQuickScrubEndAnimator;
96 private final Context mContext;
Matthew Ng2ea93b72018-03-14 19:43:18 +000097 private final Matrix mTransformGlobalMatrix = new Matrix();
98 private final Matrix mTransformLocalMatrix = new Matrix();
Matthew Ng7090a802018-01-19 13:36:22 -080099 private final ArgbEvaluator mTrackColorEvaluator = new ArgbEvaluator();
Matthew Nga8f24262017-12-19 11:54:24 -0800100
101 private final AnimatorUpdateListener mTrackAnimatorListener = valueAnimator -> {
Matthew Ng7090a802018-01-19 13:36:22 -0800102 mTrackAlpha = (float) valueAnimator.getAnimatedValue();
Matthew Nga8f24262017-12-19 11:54:24 -0800103 mNavigationBarView.invalidate();
104 };
105
106 private final AnimatorUpdateListener mButtonTranslationListener = animator -> {
107 int pos = (int) animator.getAnimatedValue();
108 if (!mQuickScrubActive) {
109 pos = mDragPositive ? Math.min((int) mTranslation, pos) : Math.max((int) mTranslation, pos);
110 }
Matthew Nga8f24262017-12-19 11:54:24 -0800111 if (mIsVertical) {
Winson Chungd10ca302018-02-14 10:13:41 -0800112 mHomeButtonView.setTranslationY(pos);
Matthew Nga8f24262017-12-19 11:54:24 -0800113 } else {
Winson Chungd10ca302018-02-14 10:13:41 -0800114 mHomeButtonView.setTranslationX(pos);
Matthew Nga8f24262017-12-19 11:54:24 -0800115 }
116 };
117
118 private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
119 @Override
120 public void onAnimationEnd(Animator animation) {
Matthew Nga8f24262017-12-19 11:54:24 -0800121 mQuickScrubActive = false;
Matthew Ng9a223632018-03-30 16:47:22 -0700122 mDragScrubActive = false;
Matthew Nga8f24262017-12-19 11:54:24 -0800123 mTranslation = 0;
Matthew Nged166f92018-02-20 16:22:09 -0800124 mQuickScrubEndAnimator.setCurrentPlayTime(mQuickScrubEndAnimator.getDuration());
125 mHomeButtonView = null;
Matthew Nga8f24262017-12-19 11:54:24 -0800126 }
127 };
128
Matthew Ng2ea93b72018-03-14 19:43:18 +0000129 public QuickStepController(Context context) {
Matthew Nga8f24262017-12-19 11:54:24 -0800130 mContext = context;
Matthew Nga8f24262017-12-19 11:54:24 -0800131 mOverviewEventSender = Dependency.get(OverviewProxyService.class);
Matthew Nga8f24262017-12-19 11:54:24 -0800132 mTrackThickness = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_thickness);
133 mTrackPadding = getDimensionPixelSize(mContext, R.dimen.nav_quick_scrub_track_edge_padding);
Matthew Ng7090a802018-01-19 13:36:22 -0800134 mTrackPaint.setAlpha(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800135
136 mTrackAnimator = ObjectAnimator.ofFloat();
137 mTrackAnimator.addUpdateListener(mTrackAnimatorListener);
Matthew Ng55437a92018-02-23 15:02:07 -0800138 mTrackAnimator.setFloatValues(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800139 mButtonAnimator = ObjectAnimator.ofInt();
140 mButtonAnimator.addUpdateListener(mButtonTranslationListener);
Matthew Ng55437a92018-02-23 15:02:07 -0800141 mButtonAnimator.setIntValues(0);
Matthew Nga8f24262017-12-19 11:54:24 -0800142 mQuickScrubEndAnimator = new AnimatorSet();
143 mQuickScrubEndAnimator.playTogether(mTrackAnimator, mButtonAnimator);
144 mQuickScrubEndAnimator.setDuration(ANIM_DURATION_MS);
145 mQuickScrubEndAnimator.addListener(mQuickScrubEndListener);
146 mQuickScrubEndAnimator.setInterpolator(mQuickScrubEndInterpolator);
147 }
148
149 public void setComponents(NavigationBarView navigationBarView) {
150 mNavigationBarView = navigationBarView;
151 }
152
Winson Chung4faf38a2018-02-06 08:53:37 -0800153 /**
Matthew Ngfba39692018-03-13 18:08:34 -0700154 * @return true if we want to intercept touch events for quick scrub and prevent proxying the
155 * event to the overview service.
Winson Chung4faf38a2018-02-06 08:53:37 -0800156 */
Matthew Nga8f24262017-12-19 11:54:24 -0800157 @Override
158 public boolean onInterceptTouchEvent(MotionEvent event) {
Winson Chungde2a1242018-02-07 15:59:43 -0800159 return handleTouchEvent(event);
160 }
161
162 /**
Matthew Ngfba39692018-03-13 18:08:34 -0700163 * @return true if we want to handle touch events for quick scrub or if down event (that will
164 * get consumed and ignored). No events will be proxied to the overview service.
Winson Chungde2a1242018-02-07 15:59:43 -0800165 */
166 @Override
167 public boolean onTouchEvent(MotionEvent event) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000168 // The same down event was just sent on intercept and therefore can be ignored here
169 final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
170 && mOverviewEventSender.getProxy() != null;
171 return ignoreProxyDownEvent || handleTouchEvent(event);
Winson Chungde2a1242018-02-07 15:59:43 -0800172 }
173
174 private boolean handleTouchEvent(MotionEvent event) {
Matthew Ng8a7c97a2018-03-27 15:25:28 -0700175 if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
176 && !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
Matthew Ng22cf5142018-03-14 12:26:14 -0700177 mNavigationBarView.getHomeButton().setDelayTouchFeedback(false /* delay */);
178 return false;
179 }
180 mNavigationBarView.requestUnbufferedDispatch(event);
181
Winson Chungde2a1242018-02-07 15:59:43 -0800182 final ButtonDispatcher homeButton = mNavigationBarView.getHomeButton();
Matthew Ng2ea93b72018-03-14 19:43:18 +0000183 final boolean homePressed = mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME;
Matthew Ng9a223632018-03-30 16:47:22 -0700184 int action = event.getActionMasked();
185 switch (action) {
Matthew Nga8f24262017-12-19 11:54:24 -0800186 case MotionEvent.ACTION_DOWN: {
187 int x = (int) event.getX();
188 int y = (int) event.getY();
Winson Chung0be8f082018-02-15 15:52:49 -0800189 // End any existing quickscrub animations before starting the new transition
Matthew Nged166f92018-02-20 16:22:09 -0800190 if (mHomeButtonView != null) {
Winson Chung0be8f082018-02-15 15:52:49 -0800191 mQuickScrubEndAnimator.end();
192 }
Winson Chungd10ca302018-02-14 10:13:41 -0800193 mHomeButtonView = homeButton.getCurrentView();
Matthew Ng2ea93b72018-03-14 19:43:18 +0000194 homeButton.setDelayTouchFeedback(true /* delay */);
195 mTouchDownX = x;
196 mTouchDownY = y;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000197 mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
198 mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
199 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
200 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
201 mQuickStepStarted = false;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000202 mAllowGestureDetection = true;
Matthew Nga8f24262017-12-19 11:54:24 -0800203 break;
204 }
205 case MotionEvent.ACTION_MOVE: {
Matthew Ng603b3292018-03-30 17:15:39 -0700206 if (mQuickStepStarted || !mAllowGestureDetection || mHomeButtonView == null){
Matthew Ng2ea93b72018-03-14 19:43:18 +0000207 break;
208 }
209 int x = (int) event.getX();
210 int y = (int) event.getY();
211 int xDiff = Math.abs(x - mTouchDownX);
212 int yDiff = Math.abs(y - mTouchDownY);
Matthew Ng9a223632018-03-30 16:47:22 -0700213
214 boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop, exceededScrubDragSlop;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000215 int pos, touchDown, offset, trackSize;
Matthew Nge0903c92018-01-17 15:32:41 -0800216
Matthew Ng2ea93b72018-03-14 19:43:18 +0000217 if (mIsVertical) {
Matthew Ng9a223632018-03-30 16:47:22 -0700218 exceededScrubTouchSlop = yDiff > QUICK_STEP_TOUCH_SLOP_PX && yDiff > xDiff;
219 exceededSwipeUpTouchSlop = xDiff > QUICK_STEP_DRAG_SLOP_PX && xDiff > yDiff;
220 exceededScrubDragSlop = yDiff > QUICK_SCRUB_DRAG_SLOP_PX && yDiff > xDiff;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000221 pos = y;
222 touchDown = mTouchDownY;
223 offset = pos - mTrackRect.top;
224 trackSize = mTrackRect.height();
225 } else {
Matthew Ng9a223632018-03-30 16:47:22 -0700226 exceededScrubTouchSlop = xDiff > QUICK_STEP_TOUCH_SLOP_PX && xDiff > yDiff;
227 exceededSwipeUpTouchSlop = yDiff > QUICK_SCRUB_TOUCH_SLOP_PX && yDiff > xDiff;
228 exceededScrubDragSlop = xDiff > QUICK_SCRUB_DRAG_SLOP_PX && xDiff > yDiff;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000229 pos = x;
230 touchDown = mTouchDownX;
231 offset = pos - mTrackRect.left;
232 trackSize = mTrackRect.width();
233 }
234 // Decide to start quickstep if dragging away from the navigation bar, otherwise in
235 // the parallel direction, decide to start quickscrub. Only one may run.
Matthew Ng9a223632018-03-30 16:47:22 -0700236 if (!mQuickScrubActive && exceededSwipeUpTouchSlop) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000237 if (mNavigationBarView.isQuickStepSwipeUpEnabled()) {
238 startQuickStep(event);
Winson Chung0e490d922018-03-14 16:08:43 +0000239 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000240 break;
241 }
Winson Chung0e490d922018-03-14 16:08:43 +0000242
Matthew Ngfba39692018-03-13 18:08:34 -0700243 // Do not handle quick scrub if disabled or hit target is not home button
Matthew Ng2ea93b72018-03-14 19:43:18 +0000244 if (!homePressed || !mNavigationBarView.isQuickScrubEnabled()) {
245 break;
246 }
247
248 if (!mDragPositive) {
249 offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
250 }
251
Matthew Ng9a223632018-03-30 16:47:22 -0700252 final boolean allowDrag = !mDragPositive
253 ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
254 if (allowDrag) {
255 // Passing the drag slop is for visual feedback and will not initiate anything
256 if (!mDragScrubActive && exceededScrubDragSlop) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000257 mDownOffset = offset;
Matthew Ng9a223632018-03-30 16:47:22 -0700258 mDragScrubActive = true;
259 }
260
261 // Passing the drag slop then touch slop will start quick step
262 if (!mQuickScrubActive && exceededScrubTouchSlop) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000263 homeButton.abortCurrentGesture();
Matthew Ngfba39692018-03-13 18:08:34 -0700264 startQuickScrub();
Winson Chung0e490d922018-03-14 16:08:43 +0000265 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000266 }
Matthew Ng9a223632018-03-30 16:47:22 -0700267
268 if ((mQuickScrubActive || mDragScrubActive) && (mDragPositive && offset >= 0
Matthew Ng2ea93b72018-03-14 19:43:18 +0000269 || !mDragPositive && offset <= 0)) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000270 mTranslation = !mDragPositive
Matthew Ng9a223632018-03-30 16:47:22 -0700271 ? Utilities.clamp(offset - mDownOffset, -trackSize, 0)
272 : Utilities.clamp(offset - mDownOffset, 0, trackSize);
273 if (mQuickScrubActive) {
274 float scrubFraction =
275 Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
276 try {
277 mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
278 if (DEBUG_OVERVIEW_PROXY) {
279 Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
280 }
281 } catch (RemoteException e) {
282 Log.e(TAG, "Failed to send progress of quick scrub.", e);
Winson Chung0e490d922018-03-14 16:08:43 +0000283 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000284 }
285 if (mIsVertical) {
286 mHomeButtonView.setTranslationY(mTranslation);
287 } else {
288 mHomeButtonView.setTranslationX(mTranslation);
Matthew Nga8f24262017-12-19 11:54:24 -0800289 }
290 }
291 break;
292 }
293 case MotionEvent.ACTION_CANCEL:
294 case MotionEvent.ACTION_UP:
Winson Chungd10ca302018-02-14 10:13:41 -0800295 endQuickScrub(true /* animate */);
Matthew Nga8f24262017-12-19 11:54:24 -0800296 break;
297 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000298
Matthew Ngfba39692018-03-13 18:08:34 -0700299 // Proxy motion events to launcher if not handled by quick scrub
Matthew Ng9a223632018-03-30 16:47:22 -0700300 // Proxy motion events up/cancel that would be sent after long press on any nav button
301 if (!mQuickScrubActive && (mAllowGestureDetection || action == MotionEvent.ACTION_CANCEL
302 || action == MotionEvent.ACTION_UP)) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000303 proxyMotionEvents(event);
304 }
Matthew Ngfba39692018-03-13 18:08:34 -0700305 return mQuickScrubActive || mQuickStepStarted;
Matthew Nga8f24262017-12-19 11:54:24 -0800306 }
307
308 @Override
309 public void onDraw(Canvas canvas) {
Matthew Ngf781bbd2018-03-21 14:58:55 -0700310 if (!mNavigationBarView.isQuickScrubEnabled()) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000311 return;
312 }
Matthew Ng7090a802018-01-19 13:36:22 -0800313 int color = (int) mTrackColorEvaluator.evaluate(mDarkIntensity, mLightTrackColor,
314 mDarkTrackColor);
315 mTrackPaint.setColor(color);
316 mTrackPaint.setAlpha((int) (mTrackPaint.getAlpha() * mTrackAlpha));
Matthew Nga8f24262017-12-19 11:54:24 -0800317 canvas.drawRect(mTrackRect, mTrackPaint);
318 }
319
320 @Override
321 public void onLayout(boolean changed, int left, int top, int right, int bottom) {
Matthew Ng5bcd3472018-03-22 11:33:16 -0700322 final int width = (right - left) - mNavigationBarView.getPaddingEnd()
323 - mNavigationBarView.getPaddingStart();
324 final int height = (bottom - top) - mNavigationBarView.getPaddingBottom()
325 - mNavigationBarView.getPaddingTop();
Matthew Nga8f24262017-12-19 11:54:24 -0800326 final int x1, x2, y1, y2;
327 if (mIsVertical) {
Matthew Ng5bcd3472018-03-22 11:33:16 -0700328 x1 = (width - mTrackThickness) / 2 + mNavigationBarView.getPaddingStart();
Matthew Nga8f24262017-12-19 11:54:24 -0800329 x2 = x1 + mTrackThickness;
330 y1 = mDragPositive ? height / 2 : mTrackPadding;
331 y2 = y1 + height / 2 - mTrackPadding;
332 } else {
Matthew Ng5bcd3472018-03-22 11:33:16 -0700333 y1 = (height - mTrackThickness) / 2 + mNavigationBarView.getPaddingTop();
Matthew Nga8f24262017-12-19 11:54:24 -0800334 y2 = y1 + mTrackThickness;
335 x1 = mDragPositive ? width / 2 : mTrackPadding;
336 x2 = x1 + width / 2 - mTrackPadding;
337 }
338 mTrackRect.set(x1, y1, x2, y2);
Matthew Nga8f24262017-12-19 11:54:24 -0800339 }
340
341 @Override
342 public void onDarkIntensityChange(float intensity) {
Matthew Ng7090a802018-01-19 13:36:22 -0800343 mDarkIntensity = intensity;
344 mNavigationBarView.invalidate();
Matthew Nga8f24262017-12-19 11:54:24 -0800345 }
346
347 @Override
Matthew Nga8f24262017-12-19 11:54:24 -0800348 public void setBarState(boolean isVertical, boolean isRTL) {
Winson Chungd10ca302018-02-14 10:13:41 -0800349 final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
350 if (changed) {
351 // End quickscrub if the state changes mid-transition
352 endQuickScrub(false /* animate */);
353 }
Matthew Nga8f24262017-12-19 11:54:24 -0800354 mIsVertical = isVertical;
355 mIsRTL = isRTL;
356 try {
357 int navbarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
358 mDragPositive = navbarPos == NAV_BAR_LEFT || navbarPos == NAV_BAR_BOTTOM;
359 if (isRTL) {
360 mDragPositive = !mDragPositive;
361 }
362 } catch (RemoteException e) {
363 Slog.e(TAG, "Failed to get nav bar position.", e);
364 }
365 }
366
Matthew Ng2ea93b72018-03-14 19:43:18 +0000367 @Override
368 public void onNavigationButtonLongPress(View v) {
369 mAllowGestureDetection = false;
370 mHandler.removeCallbacksAndMessages(null);
371 }
372
373 private void startQuickStep(MotionEvent event) {
374 mQuickStepStarted = true;
375 event.transform(mTransformGlobalMatrix);
376 try {
377 mOverviewEventSender.getProxy().onQuickStep(event);
378 if (DEBUG_OVERVIEW_PROXY) {
379 Log.d(TAG_OPS, "Quick Step Start");
380 }
381 } catch (RemoteException e) {
382 Log.e(TAG, "Failed to send quick step started.", e);
383 } finally {
384 event.transform(mTransformLocalMatrix);
385 }
386 mOverviewEventSender.notifyQuickStepStarted();
387 mNavigationBarView.getHomeButton().abortCurrentGesture();
Matthew Ng2ea93b72018-03-14 19:43:18 +0000388 mHandler.removeCallbacksAndMessages(null);
Matthew Ng9a223632018-03-30 16:47:22 -0700389
390 if (mDragScrubActive) {
391 animateEnd();
392 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000393 }
394
Matthew Nga8f24262017-12-19 11:54:24 -0800395 private void startQuickScrub() {
Matthew Ng9a223632018-03-30 16:47:22 -0700396 if (!mQuickScrubActive && mDragScrubActive) {
Matthew Nga8f24262017-12-19 11:54:24 -0800397 mQuickScrubActive = true;
Matthew Ng7090a802018-01-19 13:36:22 -0800398 mLightTrackColor = mContext.getColor(R.color.quick_step_track_background_light);
399 mDarkTrackColor = mContext.getColor(R.color.quick_step_track_background_dark);
400 mTrackAnimator.setFloatValues(0, 1);
Matthew Nga8f24262017-12-19 11:54:24 -0800401 mTrackAnimator.start();
402 try {
403 mOverviewEventSender.getProxy().onQuickScrubStart();
Matthew Ngbd824572018-01-17 16:25:56 -0800404 if (DEBUG_OVERVIEW_PROXY) {
405 Log.d(TAG_OPS, "Quick Scrub Start");
406 }
Matthew Nga8f24262017-12-19 11:54:24 -0800407 } catch (RemoteException e) {
408 Log.e(TAG, "Failed to send start of quick scrub.", e);
409 }
410 }
411 }
412
Winson Chungd10ca302018-02-14 10:13:41 -0800413 private void endQuickScrub(boolean animate) {
Matthew Ng9a223632018-03-30 16:47:22 -0700414 if (mQuickScrubActive || mDragScrubActive) {
Matthew Nged166f92018-02-20 16:22:09 -0800415 animateEnd();
Matthew Ng9a223632018-03-30 16:47:22 -0700416 if (mQuickScrubActive) {
417 try {
418 mOverviewEventSender.getProxy().onQuickScrubEnd();
419 if (DEBUG_OVERVIEW_PROXY) {
420 Log.d(TAG_OPS, "Quick Scrub End");
421 }
422 } catch (RemoteException e) {
423 Log.e(TAG, "Failed to send end of quick scrub.", e);
Matthew Ngbd824572018-01-17 16:25:56 -0800424 }
Matthew Nga8f24262017-12-19 11:54:24 -0800425 }
Matthew Nged166f92018-02-20 16:22:09 -0800426 }
427 if (mHomeButtonView != null && !animate) {
428 mQuickScrubEndAnimator.end();
Matthew Nga8f24262017-12-19 11:54:24 -0800429 }
Matthew Nga8f24262017-12-19 11:54:24 -0800430 }
431
Matthew Ng2ea93b72018-03-14 19:43:18 +0000432 private boolean proxyMotionEvents(MotionEvent event) {
433 final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
434 event.transform(mTransformGlobalMatrix);
435 try {
436 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
437 overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
438 }
439 overviewProxy.onMotionEvent(event);
440 if (DEBUG_OVERVIEW_PROXY) {
441 Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
442 }
443 return true;
444 } catch (RemoteException e) {
445 Log.e(TAG, "Callback failed", e);
446 } finally {
447 event.transform(mTransformLocalMatrix);
Matthew Ngdb2734c2018-02-16 16:02:20 -0800448 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000449 return false;
Matthew Ngdb2734c2018-02-16 16:02:20 -0800450 }
451
Matthew Nged166f92018-02-20 16:22:09 -0800452 private void animateEnd() {
453 mButtonAnimator.setIntValues((int) mTranslation, 0);
454 mTrackAnimator.setFloatValues(mTrackAlpha, 0);
Matthew Ng55437a92018-02-23 15:02:07 -0800455 mQuickScrubEndAnimator.setCurrentPlayTime(0);
Matthew Nged166f92018-02-20 16:22:09 -0800456 mQuickScrubEndAnimator.start();
457 }
458
Matthew Nga8f24262017-12-19 11:54:24 -0800459 private int getDimensionPixelSize(Context context, @DimenRes int resId) {
460 return context.getResources().getDimensionPixelSize(resId);
461 }
462}