blob: 39801260158766fea05626e6eee39fca20f61883 [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
Winson Chung661d5f92018-05-21 18:41:39 -070019import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
20import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
21import static com.android.systemui.Interpolators.ALPHA_IN;
22import static com.android.systemui.Interpolators.ALPHA_OUT;
Winson Chung2dbcf092018-10-24 13:00:41 -070023import static com.android.systemui.recents.OverviewProxyService.DEBUG_OVERVIEW_PROXY;
24import static com.android.systemui.recents.OverviewProxyService.TAG_OPS;
Matthew Ng472d3e42018-06-14 15:16:55 -070025import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
Matthew Ngc83b9892018-08-21 16:31:13 -070026import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
Winson Chung661d5f92018-05-21 18:41:39 -070027
Matthew Nga8f24262017-12-19 11:54:24 -080028import android.animation.Animator;
29import android.animation.AnimatorListenerAdapter;
30import android.animation.AnimatorSet;
31import android.animation.ObjectAnimator;
Winson Chung661d5f92018-05-21 18:41:39 -070032import android.animation.PropertyValuesHolder;
Matthew Nga8f24262017-12-19 11:54:24 -080033import android.content.Context;
Winson Chung661d5f92018-05-21 18:41:39 -070034import android.content.res.Resources;
Matthew Nga8f24262017-12-19 11:54:24 -080035import android.graphics.Canvas;
Matthew Ng2ea93b72018-03-14 19:43:18 +000036import android.graphics.Matrix;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -070037import android.graphics.Paint;
38import android.graphics.RadialGradient;
Matthew Nga8f24262017-12-19 11:54:24 -080039import android.graphics.Rect;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -070040import android.graphics.Shader;
Matthew Ngc83b9892018-08-21 16:31:13 -070041import android.hardware.input.InputManager;
Matthew Nga8f24262017-12-19 11:54:24 -080042import android.os.Handler;
43import android.os.RemoteException;
Matthew Ngc83b9892018-08-21 16:31:13 -070044import android.os.SystemClock;
Matthew Ngb687c8a2018-10-02 11:31:38 -070045import android.provider.Settings;
Winson Chung661d5f92018-05-21 18:41:39 -070046import android.util.FloatProperty;
Matthew Nga8f24262017-12-19 11:54:24 -080047import android.util.Log;
48import android.util.Slog;
Matthew Ngc83b9892018-08-21 16:31:13 -070049import android.view.HapticFeedbackConstants;
50import android.view.InputDevice;
51import android.view.KeyCharacterMap;
52import android.view.KeyEvent;
Matthew Nga8f24262017-12-19 11:54:24 -080053import android.view.MotionEvent;
54import android.view.View;
Matthew Ngc83b9892018-08-21 16:31:13 -070055import android.view.ViewPropertyAnimator;
Matthew Nga8f24262017-12-19 11:54:24 -080056import android.view.WindowManagerGlobal;
Matthew Nga8f24262017-12-19 11:54:24 -080057import com.android.systemui.Dependency;
Matthew Ngc83b9892018-08-21 16:31:13 -070058import com.android.systemui.Interpolators;
Winson Chung2dbcf092018-10-24 13:00:41 -070059import com.android.systemui.recents.OverviewProxyService;
Matthew Nga8f24262017-12-19 11:54:24 -080060import com.android.systemui.R;
Winson Chung0d3815d2018-09-25 18:11:54 -070061import com.android.systemui.SysUiServiceProvider;
Matthew Nga8f24262017-12-19 11:54:24 -080062import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
63import com.android.systemui.shared.recents.IOverviewProxy;
64import com.android.systemui.shared.recents.utilities.Utilities;
Matthew Ngf29ad752018-04-26 11:24:05 -070065import com.android.systemui.shared.system.NavigationBarCompat;
Winson Chung0d3815d2018-09-25 18:11:54 -070066import java.io.PrintWriter;
Matthew Nga8f24262017-12-19 11:54:24 -080067
Matthew Nga8f24262017-12-19 11:54:24 -080068/**
Matthew Ngfba39692018-03-13 18:08:34 -070069 * Class to detect gestures on the navigation bar and implement quick scrub.
Matthew Nga8f24262017-12-19 11:54:24 -080070 */
Matthew Ngfba39692018-03-13 18:08:34 -070071public class QuickStepController implements GestureHelper {
Matthew Nga8f24262017-12-19 11:54:24 -080072
Matthew Ng2ea93b72018-03-14 19:43:18 +000073 private static final String TAG = "QuickStepController";
Winson Chung661d5f92018-05-21 18:41:39 -070074 private static final int ANIM_IN_DURATION_MS = 150;
Winson Chung4baf1242018-05-24 14:21:57 -070075 private static final int ANIM_OUT_DURATION_MS = 134;
76 private static final float TRACK_SCALE = 0.95f;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -070077 private static final float GRADIENT_WIDTH = .75f;
Matthew Nga8f24262017-12-19 11:54:24 -080078
Matthew Ngc83b9892018-08-21 16:31:13 -070079 /** Experiment to swipe home button left to execute a back key press */
Matthew Ngb687c8a2018-10-02 11:31:38 -070080 private static final String PULL_HOME_GO_BACK_PROP = "quickstepcontroller_homegoesback";
81 private static final String HIDE_BACK_BUTTON_PROP = "quickstepcontroller_hideback";
Matthew Ngc414e282018-09-05 15:50:10 -070082 private static final String BACK_AFTER_END_PROP
Matthew Ngb687c8a2018-10-02 11:31:38 -070083 = "quickstepcontroller_homegoesbackwhenend";
84 private static final String NAVBAR_EXPERIMENTS_DISABLED = "navbarexperiments_disabled";
Matthew Ngc83b9892018-08-21 16:31:13 -070085 private static final long BACK_BUTTON_FADE_OUT_ALPHA = 60;
86 private static final long BACK_BUTTON_FADE_IN_ALPHA = 150;
87 private static final long BACK_GESTURE_POLL_TIMEOUT = 1000;
88
89 /** When the home-swipe-back gesture is disallowed, make it harder to pull */
90 private static final float DISALLOW_GESTURE_DAMPING_FACTOR = 0.16f;
91
Matthew Nga8f24262017-12-19 11:54:24 -080092 private NavigationBarView mNavigationBarView;
Matthew Nga8f24262017-12-19 11:54:24 -080093
Matthew Nga8f24262017-12-19 11:54:24 -080094 private boolean mQuickScrubActive;
Matthew Ng2ea93b72018-03-14 19:43:18 +000095 private boolean mAllowGestureDetection;
Matthew Ngc83b9892018-08-21 16:31:13 -070096 private boolean mBackGestureActive;
97 private boolean mCanPerformBack;
Matthew Ng2ea93b72018-03-14 19:43:18 +000098 private boolean mQuickStepStarted;
Matthew Ng90ef0632018-08-15 13:53:15 -070099 private boolean mNotificationsVisibleOnDown;
Matthew Nga8f24262017-12-19 11:54:24 -0800100 private int mTouchDownX;
101 private int mTouchDownY;
102 private boolean mDragPositive;
103 private boolean mIsVertical;
104 private boolean mIsRTL;
Matthew Ng7090a802018-01-19 13:36:22 -0800105 private float mTrackAlpha;
Winson Chung4baf1242018-05-24 14:21:57 -0700106 private float mTrackScale = TRACK_SCALE;
Matthew Ng7090a802018-01-19 13:36:22 -0800107 private float mDarkIntensity;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700108 private RadialGradient mHighlight;
109 private float mHighlightCenter;
Winson Chung661d5f92018-05-21 18:41:39 -0700110 private AnimatorSet mTrackAnimator;
Matthew Ngc83b9892018-08-21 16:31:13 -0700111 private ViewPropertyAnimator mHomeAnimator;
Winson Chung661d5f92018-05-21 18:41:39 -0700112 private ButtonDispatcher mHitTarget;
113 private View mCurrentNavigationBarView;
Matthew Ng20136e62018-05-30 12:20:31 -0700114 private boolean mIsInScreenPinning;
Matthew Nga8f24262017-12-19 11:54:24 -0800115
116 private final Handler mHandler = new Handler();
Matthew Nga8f24262017-12-19 11:54:24 -0800117 private final Rect mTrackRect = new Rect();
Matthew Nga8f24262017-12-19 11:54:24 -0800118 private final OverviewProxyService mOverviewEventSender;
Matthew Nga8f24262017-12-19 11:54:24 -0800119 private final int mTrackThickness;
Winson Chung661d5f92018-05-21 18:41:39 -0700120 private final int mTrackEndPadding;
Matthew Ngc83b9892018-08-21 16:31:13 -0700121 private final int mHomeBackGestureDragLimit;
Matthew Nga8f24262017-12-19 11:54:24 -0800122 private final Context mContext;
Winson Chung0d3815d2018-09-25 18:11:54 -0700123 private final StatusBar mStatusBar;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000124 private final Matrix mTransformGlobalMatrix = new Matrix();
125 private final Matrix mTransformLocalMatrix = new Matrix();
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700126 private final Paint mTrackPaint = new Paint();
Matthew Nga8f24262017-12-19 11:54:24 -0800127
Winson Chung661d5f92018-05-21 18:41:39 -0700128 private final FloatProperty<QuickStepController> mTrackAlphaProperty =
129 new FloatProperty<QuickStepController>("TrackAlpha") {
130 @Override
131 public void setValue(QuickStepController controller, float alpha) {
132 mTrackAlpha = alpha;
133 mNavigationBarView.invalidate();
134 }
135
136 @Override
137 public Float get(QuickStepController controller) {
138 return mTrackAlpha;
139 }
Matthew Nga8f24262017-12-19 11:54:24 -0800140 };
141
Winson Chung4baf1242018-05-24 14:21:57 -0700142 private final FloatProperty<QuickStepController> mTrackScaleProperty =
143 new FloatProperty<QuickStepController>("TrackScale") {
144 @Override
145 public void setValue(QuickStepController controller, float scale) {
146 mTrackScale = scale;
147 mNavigationBarView.invalidate();
148 }
149
150 @Override
151 public Float get(QuickStepController controller) {
152 return mTrackScale;
153 }
154 };
155
Winson Chung661d5f92018-05-21 18:41:39 -0700156 private final FloatProperty<QuickStepController> mNavBarAlphaProperty =
157 new FloatProperty<QuickStepController>("NavBarAlpha") {
158 @Override
159 public void setValue(QuickStepController controller, float alpha) {
160 if (mCurrentNavigationBarView != null) {
161 mCurrentNavigationBarView.setAlpha(alpha);
162 }
Matthew Nga8f24262017-12-19 11:54:24 -0800163 }
Winson Chung661d5f92018-05-21 18:41:39 -0700164
165 @Override
166 public Float get(QuickStepController controller) {
167 if (mCurrentNavigationBarView != null) {
168 return mCurrentNavigationBarView.getAlpha();
169 }
170 return 1f;
Matthew Nga8f24262017-12-19 11:54:24 -0800171 }
172 };
173
174 private AnimatorListenerAdapter mQuickScrubEndListener = new AnimatorListenerAdapter() {
175 @Override
176 public void onAnimationEnd(Animator animation) {
Winson Chung661d5f92018-05-21 18:41:39 -0700177 resetQuickScrub();
Matthew Nga8f24262017-12-19 11:54:24 -0800178 }
179 };
180
Matthew Ngc83b9892018-08-21 16:31:13 -0700181 private final Runnable mExecuteBackRunnable = new Runnable() {
182 @Override
183 public void run() {
184 if (canPerformHomeBackGesture()) {
185 performBack();
186 mHandler.postDelayed(this, BACK_GESTURE_POLL_TIMEOUT);
187 }
188 }
189 };
190
Matthew Ng2ea93b72018-03-14 19:43:18 +0000191 public QuickStepController(Context context) {
Winson Chung661d5f92018-05-21 18:41:39 -0700192 final Resources res = context.getResources();
Matthew Nga8f24262017-12-19 11:54:24 -0800193 mContext = context;
Winson Chung0d3815d2018-09-25 18:11:54 -0700194 mStatusBar = SysUiServiceProvider.getComponent(context, StatusBar.class);
Matthew Nga8f24262017-12-19 11:54:24 -0800195 mOverviewEventSender = Dependency.get(OverviewProxyService.class);
Winson Chung661d5f92018-05-21 18:41:39 -0700196 mTrackThickness = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_thickness);
197 mTrackEndPadding = res.getDimensionPixelSize(R.dimen.nav_quick_scrub_track_edge_padding);
Matthew Ngc83b9892018-08-21 16:31:13 -0700198 mHomeBackGestureDragLimit =
199 res.getDimensionPixelSize(R.dimen.nav_home_back_gesture_drag_limit);
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700200 mTrackPaint.setAntiAlias(true);
201 mTrackPaint.setDither(true);
Matthew Nga8f24262017-12-19 11:54:24 -0800202 }
203
204 public void setComponents(NavigationBarView navigationBarView) {
205 mNavigationBarView = navigationBarView;
Matthew Ngc83b9892018-08-21 16:31:13 -0700206
Matthew Ngb687c8a2018-10-02 11:31:38 -0700207 mNavigationBarView.getBackButton().setVisibility(shouldhideBackButton(mContext)
Matthew Ngc83b9892018-08-21 16:31:13 -0700208 ? View.GONE
209 : View.VISIBLE);
Matthew Nga8f24262017-12-19 11:54:24 -0800210 }
211
Winson Chung4faf38a2018-02-06 08:53:37 -0800212 /**
Matthew Ngfba39692018-03-13 18:08:34 -0700213 * @return true if we want to intercept touch events for quick scrub and prevent proxying the
214 * event to the overview service.
Winson Chung4faf38a2018-02-06 08:53:37 -0800215 */
Matthew Nga8f24262017-12-19 11:54:24 -0800216 @Override
217 public boolean onInterceptTouchEvent(MotionEvent event) {
Winson Chung0d3815d2018-09-25 18:11:54 -0700218 if (mStatusBar.isKeyguardShowing()) {
219 // Disallow any handling when the keyguard is showing
220 return false;
221 }
Winson Chungde2a1242018-02-07 15:59:43 -0800222 return handleTouchEvent(event);
223 }
224
225 /**
Matthew Ngfba39692018-03-13 18:08:34 -0700226 * @return true if we want to handle touch events for quick scrub or if down event (that will
227 * get consumed and ignored). No events will be proxied to the overview service.
Winson Chungde2a1242018-02-07 15:59:43 -0800228 */
229 @Override
230 public boolean onTouchEvent(MotionEvent event) {
Winson Chung0d3815d2018-09-25 18:11:54 -0700231 if (mStatusBar.isKeyguardShowing()) {
232 // Disallow any handling when the keyguard is showing
233 return false;
234 }
235
Matthew Ng2ea93b72018-03-14 19:43:18 +0000236 // The same down event was just sent on intercept and therefore can be ignored here
237 final boolean ignoreProxyDownEvent = event.getAction() == MotionEvent.ACTION_DOWN
238 && mOverviewEventSender.getProxy() != null;
239 return ignoreProxyDownEvent || handleTouchEvent(event);
Winson Chungde2a1242018-02-07 15:59:43 -0800240 }
241
242 private boolean handleTouchEvent(MotionEvent event) {
Matthew Ng472d3e42018-06-14 15:16:55 -0700243 final boolean deadZoneConsumed =
244 mNavigationBarView.getDownHitTarget() == HIT_TARGET_DEAD_ZONE;
Winson Chungd95a2252018-04-04 17:02:29 +0000245 if (mOverviewEventSender.getProxy() == null || (!mNavigationBarView.isQuickScrubEnabled()
246 && !mNavigationBarView.isQuickStepSwipeUpEnabled())) {
Matthew Ng2cbe8cd2018-08-20 11:27:40 -0700247 return deadZoneConsumed;
Matthew Ng22cf5142018-03-14 12:26:14 -0700248 }
249 mNavigationBarView.requestUnbufferedDispatch(event);
250
Matthew Ng9a223632018-03-30 16:47:22 -0700251 int action = event.getActionMasked();
252 switch (action) {
Matthew Nga8f24262017-12-19 11:54:24 -0800253 case MotionEvent.ACTION_DOWN: {
254 int x = (int) event.getX();
255 int y = (int) event.getY();
Matthew Ng20136e62018-05-30 12:20:31 -0700256 mIsInScreenPinning = mNavigationBarView.inScreenPinning();
Winson Chung661d5f92018-05-21 18:41:39 -0700257
Winson Chung0be8f082018-02-15 15:52:49 -0800258 // End any existing quickscrub animations before starting the new transition
Winson Chung661d5f92018-05-21 18:41:39 -0700259 if (mTrackAnimator != null) {
260 mTrackAnimator.end();
261 mTrackAnimator = null;
Winson Chung0be8f082018-02-15 15:52:49 -0800262 }
Winson Chung661d5f92018-05-21 18:41:39 -0700263
264 mCurrentNavigationBarView = mNavigationBarView.getCurrentView();
265 mHitTarget = mNavigationBarView.getButtonAtPosition(x, y);
266 if (mHitTarget != null) {
267 // Pre-emptively delay the touch feedback for the button that we just touched
268 mHitTarget.setDelayTouchFeedback(true);
269 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000270 mTouchDownX = x;
271 mTouchDownY = y;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000272 mTransformGlobalMatrix.set(Matrix.IDENTITY_MATRIX);
273 mTransformLocalMatrix.set(Matrix.IDENTITY_MATRIX);
274 mNavigationBarView.transformMatrixToGlobal(mTransformGlobalMatrix);
275 mNavigationBarView.transformMatrixToLocal(mTransformLocalMatrix);
276 mQuickStepStarted = false;
Matthew Ngc83b9892018-08-21 16:31:13 -0700277 mBackGestureActive = false;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000278 mAllowGestureDetection = true;
Matthew Ng90ef0632018-08-15 13:53:15 -0700279 mNotificationsVisibleOnDown = !mNavigationBarView.isNotificationsFullyCollapsed();
Matthew Ngc83b9892018-08-21 16:31:13 -0700280 mCanPerformBack = canPerformHomeBackGesture();
Matthew Nga8f24262017-12-19 11:54:24 -0800281 break;
282 }
283 case MotionEvent.ACTION_MOVE: {
Winson Chung661d5f92018-05-21 18:41:39 -0700284 if (mQuickStepStarted || !mAllowGestureDetection){
Matthew Ng2ea93b72018-03-14 19:43:18 +0000285 break;
286 }
287 int x = (int) event.getX();
288 int y = (int) event.getY();
289 int xDiff = Math.abs(x - mTouchDownX);
290 int yDiff = Math.abs(y - mTouchDownY);
Matthew Ng9a223632018-03-30 16:47:22 -0700291
Winson Chung661d5f92018-05-21 18:41:39 -0700292 boolean exceededScrubTouchSlop, exceededSwipeUpTouchSlop;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000293 int pos, touchDown, offset, trackSize;
Matthew Nge0903c92018-01-17 15:32:41 -0800294
Matthew Ng2ea93b72018-03-14 19:43:18 +0000295 if (mIsVertical) {
Matthew Ngf29ad752018-04-26 11:24:05 -0700296 exceededScrubTouchSlop =
297 yDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && yDiff > xDiff;
298 exceededSwipeUpTouchSlop =
299 xDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && xDiff > yDiff;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000300 pos = y;
301 touchDown = mTouchDownY;
302 offset = pos - mTrackRect.top;
303 trackSize = mTrackRect.height();
304 } else {
Matthew Ngf29ad752018-04-26 11:24:05 -0700305 exceededScrubTouchSlop =
306 xDiff > NavigationBarCompat.getQuickScrubTouchSlopPx() && xDiff > yDiff;
307 exceededSwipeUpTouchSlop =
308 yDiff > NavigationBarCompat.getQuickStepTouchSlopPx() && yDiff > xDiff;
Matthew Ng2ea93b72018-03-14 19:43:18 +0000309 pos = x;
310 touchDown = mTouchDownX;
311 offset = pos - mTrackRect.left;
312 trackSize = mTrackRect.width();
313 }
314 // Decide to start quickstep if dragging away from the navigation bar, otherwise in
315 // the parallel direction, decide to start quickscrub. Only one may run.
Matthew Ngc83b9892018-08-21 16:31:13 -0700316 if (!mBackGestureActive && !mQuickScrubActive && exceededSwipeUpTouchSlop) {
Matthew Ng90ef0632018-08-15 13:53:15 -0700317 if (mNavigationBarView.isQuickStepSwipeUpEnabled()
318 && !mNotificationsVisibleOnDown) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000319 startQuickStep(event);
Winson Chung0e490d922018-03-14 16:08:43 +0000320 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000321 break;
322 }
Winson Chung0e490d922018-03-14 16:08:43 +0000323
Winson Chung661d5f92018-05-21 18:41:39 -0700324 // Do not handle quick scrub if disabled
325 if (!mNavigationBarView.isQuickScrubEnabled()) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000326 break;
327 }
328
329 if (!mDragPositive) {
330 offset -= mIsVertical ? mTrackRect.height() : mTrackRect.width();
331 }
332
Matthew Ng9a223632018-03-30 16:47:22 -0700333 final boolean allowDrag = !mDragPositive
334 ? offset < 0 && pos < touchDown : offset >= 0 && pos > touchDown;
Winson Chung661d5f92018-05-21 18:41:39 -0700335 float scrubFraction = Utilities.clamp(Math.abs(offset) * 1f / trackSize, 0, 1);
Matthew Ngc83b9892018-08-21 16:31:13 -0700336 if (!mQuickScrubActive && !mBackGestureActive && exceededScrubTouchSlop) {
Matthew Ng9a223632018-03-30 16:47:22 -0700337 // Passing the drag slop then touch slop will start quick step
Matthew Ngc83b9892018-08-21 16:31:13 -0700338 if (allowDrag) {
Matthew Ngfba39692018-03-13 18:08:34 -0700339 startQuickScrub();
Matthew Ngb687c8a2018-10-02 11:31:38 -0700340 } else if (swipeHomeGoBackGestureEnabled(mContext)
Matthew Ngc83b9892018-08-21 16:31:13 -0700341 && mNavigationBarView.getDownHitTarget() == HIT_TARGET_HOME
342 && mDragPositive ? pos < touchDown : pos > touchDown) {
343 startBackGesture();
Winson Chung0e490d922018-03-14 16:08:43 +0000344 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000345 }
Matthew Ng9a223632018-03-30 16:47:22 -0700346
Winson Chung661d5f92018-05-21 18:41:39 -0700347 if (mQuickScrubActive && (mDragPositive && offset >= 0
Matthew Ng2ea93b72018-03-14 19:43:18 +0000348 || !mDragPositive && offset <= 0)) {
Winson Chung661d5f92018-05-21 18:41:39 -0700349 try {
350 mOverviewEventSender.getProxy().onQuickScrubProgress(scrubFraction);
351 if (DEBUG_OVERVIEW_PROXY) {
352 Log.d(TAG_OPS, "Quick Scrub Progress:" + scrubFraction);
Winson Chung0e490d922018-03-14 16:08:43 +0000353 }
Winson Chung661d5f92018-05-21 18:41:39 -0700354 } catch (RemoteException e) {
355 Log.e(TAG, "Failed to send progress of quick scrub.", e);
Matthew Nga8f24262017-12-19 11:54:24 -0800356 }
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700357 mHighlightCenter = x;
358 mNavigationBarView.invalidate();
Matthew Ngc83b9892018-08-21 16:31:13 -0700359 } else if (mBackGestureActive) {
360 int diff = pos - touchDown;
361 // If dragging the incorrect direction after starting back gesture or unable
362 // to execute back functionality, then move home but dampen its distance
363 if (!mCanPerformBack || (mDragPositive ? diff > 0 : diff < 0)) {
364 diff *= DISALLOW_GESTURE_DAMPING_FACTOR;
365 } if (Math.abs(diff) > mHomeBackGestureDragLimit) {
366 // Once the user drags the home button past a certain limit, the distance
367 // will lessen as the home button dampens showing that it was pulled too far
368 float distanceAfterDragLimit = (Math.abs(diff) - mHomeBackGestureDragLimit)
Matthew Ngc414e282018-09-05 15:50:10 -0700369 * DISALLOW_GESTURE_DAMPING_FACTOR;
Matthew Ngc83b9892018-08-21 16:31:13 -0700370 diff = (int)(distanceAfterDragLimit + mHomeBackGestureDragLimit);
371 if (mDragPositive) {
372 diff *= -1;
373 }
374 }
375 moveHomeButton(diff);
Matthew Nga8f24262017-12-19 11:54:24 -0800376 }
377 break;
378 }
379 case MotionEvent.ACTION_CANCEL:
380 case MotionEvent.ACTION_UP:
Winson Chungd10ca302018-02-14 10:13:41 -0800381 endQuickScrub(true /* animate */);
Matthew Ngc83b9892018-08-21 16:31:13 -0700382 endBackGesture();
Matthew Nga8f24262017-12-19 11:54:24 -0800383 break;
384 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000385
Matthew Ng90ef0632018-08-15 13:53:15 -0700386 if (shouldProxyEvents(action)) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000387 proxyMotionEvents(event);
388 }
Matthew Ngc83b9892018-08-21 16:31:13 -0700389 return mBackGestureActive || mQuickScrubActive || mQuickStepStarted || deadZoneConsumed;
Matthew Nga8f24262017-12-19 11:54:24 -0800390 }
391
Matthew Ng90ef0632018-08-15 13:53:15 -0700392 private boolean shouldProxyEvents(int action) {
Matthew Ngc83b9892018-08-21 16:31:13 -0700393 if (!mBackGestureActive && !mQuickScrubActive && !mIsInScreenPinning) {
Matthew Ng90ef0632018-08-15 13:53:15 -0700394 // Allow down, cancel and up events, move and other events are passed if notifications
395 // are not showing and disabled gestures (such as long press) are not executed
396 switch (action) {
397 case MotionEvent.ACTION_DOWN:
398 case MotionEvent.ACTION_CANCEL:
399 case MotionEvent.ACTION_UP:
400 return true;
401 default:
402 return !mNotificationsVisibleOnDown && mAllowGestureDetection;
403 }
404 }
405 return false;
406 }
407
Matthew Nga8f24262017-12-19 11:54:24 -0800408 @Override
409 public void onDraw(Canvas canvas) {
Matthew Ngf781bbd2018-03-21 14:58:55 -0700410 if (!mNavigationBarView.isQuickScrubEnabled()) {
Matthew Ng2ea93b72018-03-14 19:43:18 +0000411 return;
412 }
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700413 mTrackPaint.setAlpha(Math.round(255f * mTrackAlpha));
Winson Chung4baf1242018-05-24 14:21:57 -0700414
415 // Scale the track, but apply the inverse scale from the nav bar
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700416 final float radius = mTrackRect.height() / 2;
Winson Chung4baf1242018-05-24 14:21:57 -0700417 canvas.save();
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700418 float translate = Utilities.clamp(mHighlightCenter, mTrackRect.left, mTrackRect.right);
419 canvas.translate(translate, 0);
Winson Chung4baf1242018-05-24 14:21:57 -0700420 canvas.scale(mTrackScale / mNavigationBarView.getScaleX(),
421 1f / mNavigationBarView.getScaleY(),
422 mTrackRect.centerX(), mTrackRect.centerY());
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700423 canvas.drawRoundRect(mTrackRect.left - translate, mTrackRect.top,
424 mTrackRect.right - translate, mTrackRect.bottom, radius, radius, mTrackPaint);
Winson Chung4baf1242018-05-24 14:21:57 -0700425 canvas.restore();
Matthew Nga8f24262017-12-19 11:54:24 -0800426 }
427
428 @Override
429 public void onLayout(boolean changed, int left, int top, int right, int bottom) {
Winson Chung661d5f92018-05-21 18:41:39 -0700430 final int paddingLeft = mNavigationBarView.getPaddingLeft();
431 final int paddingTop = mNavigationBarView.getPaddingTop();
432 final int paddingRight = mNavigationBarView.getPaddingRight();
433 final int paddingBottom = mNavigationBarView.getPaddingBottom();
434 final int width = (right - left) - paddingRight - paddingLeft;
435 final int height = (bottom - top) - paddingBottom - paddingTop;
Matthew Nga8f24262017-12-19 11:54:24 -0800436 final int x1, x2, y1, y2;
437 if (mIsVertical) {
Winson Chung661d5f92018-05-21 18:41:39 -0700438 x1 = (width - mTrackThickness) / 2 + paddingLeft;
Matthew Nga8f24262017-12-19 11:54:24 -0800439 x2 = x1 + mTrackThickness;
Winson Chung661d5f92018-05-21 18:41:39 -0700440 y1 = paddingTop + mTrackEndPadding;
441 y2 = y1 + height - 2 * mTrackEndPadding;
Matthew Nga8f24262017-12-19 11:54:24 -0800442 } else {
Winson Chung661d5f92018-05-21 18:41:39 -0700443 y1 = (height - mTrackThickness) / 2 + paddingTop;
Matthew Nga8f24262017-12-19 11:54:24 -0800444 y2 = y1 + mTrackThickness;
Winson Chung661d5f92018-05-21 18:41:39 -0700445 x1 = mNavigationBarView.getPaddingStart() + mTrackEndPadding;
446 x2 = x1 + width - 2 * mTrackEndPadding;
Matthew Nga8f24262017-12-19 11:54:24 -0800447 }
448 mTrackRect.set(x1, y1, x2, y2);
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700449 updateHighlight();
Matthew Nga8f24262017-12-19 11:54:24 -0800450 }
451
452 @Override
453 public void onDarkIntensityChange(float intensity) {
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700454 final float oldIntensity = mDarkIntensity;
Matthew Ng7090a802018-01-19 13:36:22 -0800455 mDarkIntensity = intensity;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700456
457 // When in quick scrub, invalidate gradient if changing intensity from black to white and
458 // vice-versa
459 if (mNavigationBarView.isQuickScrubEnabled()
460 && Math.round(intensity) != Math.round(oldIntensity)) {
461 updateHighlight();
462 }
Matthew Ng7090a802018-01-19 13:36:22 -0800463 mNavigationBarView.invalidate();
Matthew Nga8f24262017-12-19 11:54:24 -0800464 }
465
466 @Override
Matthew Nga8f24262017-12-19 11:54:24 -0800467 public void setBarState(boolean isVertical, boolean isRTL) {
Winson Chungd10ca302018-02-14 10:13:41 -0800468 final boolean changed = (mIsVertical != isVertical) || (mIsRTL != isRTL);
469 if (changed) {
470 // End quickscrub if the state changes mid-transition
471 endQuickScrub(false /* animate */);
472 }
Matthew Nga8f24262017-12-19 11:54:24 -0800473 mIsVertical = isVertical;
474 mIsRTL = isRTL;
475 try {
476 int navbarPos = WindowManagerGlobal.getWindowManagerService().getNavBarPosition();
477 mDragPositive = navbarPos == NAV_BAR_LEFT || navbarPos == NAV_BAR_BOTTOM;
478 if (isRTL) {
479 mDragPositive = !mDragPositive;
480 }
481 } catch (RemoteException e) {
482 Slog.e(TAG, "Failed to get nav bar position.", e);
483 }
484 }
485
Matthew Ng2ea93b72018-03-14 19:43:18 +0000486 @Override
487 public void onNavigationButtonLongPress(View v) {
488 mAllowGestureDetection = false;
489 mHandler.removeCallbacksAndMessages(null);
490 }
491
Winson Chung0d3815d2018-09-25 18:11:54 -0700492 @Override
493 public void dump(PrintWriter pw) {
494 pw.println("QuickStepController {");
495 pw.print(" "); pw.println("mQuickScrubActive=" + mQuickScrubActive);
496 pw.print(" "); pw.println("mQuickStepStarted=" + mQuickStepStarted);
497 pw.print(" "); pw.println("mAllowGestureDetection=" + mAllowGestureDetection);
498 pw.print(" "); pw.println("mBackGestureActive=" + mBackGestureActive);
499 pw.print(" "); pw.println("mCanPerformBack=" + mCanPerformBack);
500 pw.print(" "); pw.println("mNotificationsVisibleOnDown=" + mNotificationsVisibleOnDown);
501 pw.print(" "); pw.println("mIsVertical=" + mIsVertical);
502 pw.print(" "); pw.println("mIsRTL=" + mIsRTL);
503 pw.print(" "); pw.println("mIsInScreenPinning=" + mIsInScreenPinning);
504 pw.println("}");
505 }
506
Matthew Ng2ea93b72018-03-14 19:43:18 +0000507 private void startQuickStep(MotionEvent event) {
Matthew Ng20136e62018-05-30 12:20:31 -0700508 if (mIsInScreenPinning) {
509 mNavigationBarView.showPinningEscapeToast();
510 mAllowGestureDetection = false;
511 return;
512 }
513
Matthew Ng2ea93b72018-03-14 19:43:18 +0000514 mQuickStepStarted = true;
515 event.transform(mTransformGlobalMatrix);
516 try {
517 mOverviewEventSender.getProxy().onQuickStep(event);
518 if (DEBUG_OVERVIEW_PROXY) {
519 Log.d(TAG_OPS, "Quick Step Start");
520 }
521 } catch (RemoteException e) {
522 Log.e(TAG, "Failed to send quick step started.", e);
523 } finally {
524 event.transform(mTransformLocalMatrix);
525 }
526 mOverviewEventSender.notifyQuickStepStarted();
Matthew Ng2ea93b72018-03-14 19:43:18 +0000527 mHandler.removeCallbacksAndMessages(null);
Matthew Ng9a223632018-03-30 16:47:22 -0700528
Winson Chung661d5f92018-05-21 18:41:39 -0700529 if (mHitTarget != null) {
530 mHitTarget.abortCurrentGesture();
531 }
532
533 if (mQuickScrubActive) {
Matthew Ng9a223632018-03-30 16:47:22 -0700534 animateEnd();
535 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000536 }
537
Matthew Nga8f24262017-12-19 11:54:24 -0800538 private void startQuickScrub() {
Matthew Ng20136e62018-05-30 12:20:31 -0700539 if (mIsInScreenPinning) {
540 mNavigationBarView.showPinningEscapeToast();
541 mAllowGestureDetection = false;
542 return;
543 }
544
Winson Chung661d5f92018-05-21 18:41:39 -0700545 if (!mQuickScrubActive) {
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700546 updateHighlight();
Matthew Nga8f24262017-12-19 11:54:24 -0800547 mQuickScrubActive = true;
Winson Chung4baf1242018-05-24 14:21:57 -0700548 ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
549 PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 1f),
550 PropertyValuesHolder.ofFloat(mTrackScaleProperty, 1f));
Winson Chung661d5f92018-05-21 18:41:39 -0700551 trackAnimator.setInterpolator(ALPHA_IN);
552 trackAnimator.setDuration(ANIM_IN_DURATION_MS);
553 ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 0f);
554 navBarAnimator.setInterpolator(ALPHA_OUT);
555 navBarAnimator.setDuration(ANIM_OUT_DURATION_MS);
556 mTrackAnimator = new AnimatorSet();
557 mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
558 mTrackAnimator.start();
Matthew Ng6607c3d2018-04-26 15:23:27 -0700559
Matthew Ng472d3e42018-06-14 15:16:55 -0700560 // Disable slippery for quick scrub to not cancel outside the nav bar
561 mNavigationBarView.updateSlippery();
562
Matthew Nga8f24262017-12-19 11:54:24 -0800563 try {
564 mOverviewEventSender.getProxy().onQuickScrubStart();
Matthew Ngbd824572018-01-17 16:25:56 -0800565 if (DEBUG_OVERVIEW_PROXY) {
566 Log.d(TAG_OPS, "Quick Scrub Start");
567 }
Matthew Nga8f24262017-12-19 11:54:24 -0800568 } catch (RemoteException e) {
569 Log.e(TAG, "Failed to send start of quick scrub.", e);
570 }
Tracy Zhou27599052018-04-16 15:47:29 -0700571 mOverviewEventSender.notifyQuickScrubStarted();
Winson Chung661d5f92018-05-21 18:41:39 -0700572
573 if (mHitTarget != null) {
574 mHitTarget.abortCurrentGesture();
575 }
Matthew Nga8f24262017-12-19 11:54:24 -0800576 }
577 }
578
Winson Chungd10ca302018-02-14 10:13:41 -0800579 private void endQuickScrub(boolean animate) {
Winson Chung661d5f92018-05-21 18:41:39 -0700580 if (mQuickScrubActive) {
Matthew Nged166f92018-02-20 16:22:09 -0800581 animateEnd();
Winson Chung661d5f92018-05-21 18:41:39 -0700582 try {
583 mOverviewEventSender.getProxy().onQuickScrubEnd();
584 if (DEBUG_OVERVIEW_PROXY) {
585 Log.d(TAG_OPS, "Quick Scrub End");
Matthew Ngbd824572018-01-17 16:25:56 -0800586 }
Winson Chung661d5f92018-05-21 18:41:39 -0700587 } catch (RemoteException e) {
588 Log.e(TAG, "Failed to send end of quick scrub.", e);
Matthew Nga8f24262017-12-19 11:54:24 -0800589 }
Matthew Nged166f92018-02-20 16:22:09 -0800590 }
Winson Chung661d5f92018-05-21 18:41:39 -0700591 if (!animate) {
592 if (mTrackAnimator != null) {
593 mTrackAnimator.end();
594 mTrackAnimator = null;
595 }
Matthew Nga8f24262017-12-19 11:54:24 -0800596 }
Matthew Nga8f24262017-12-19 11:54:24 -0800597 }
598
Matthew Ngc83b9892018-08-21 16:31:13 -0700599 private void startBackGesture() {
600 if (!mBackGestureActive) {
601 mBackGestureActive = true;
602 mNavigationBarView.getHomeButton().abortCurrentGesture();
Matthew Ngb687c8a2018-10-02 11:31:38 -0700603 final boolean runBackMidGesture = !shouldExecuteBackOnUp(mContext);
Matthew Ngc83b9892018-08-21 16:31:13 -0700604 if (mCanPerformBack) {
Matthew Ngb687c8a2018-10-02 11:31:38 -0700605 if (!shouldhideBackButton(mContext)) {
Matthew Ngc83b9892018-08-21 16:31:13 -0700606 mNavigationBarView.getBackButton().setAlpha(0 /* alpha */, true /* animate */,
607 BACK_BUTTON_FADE_OUT_ALPHA);
608 }
Matthew Ngc414e282018-09-05 15:50:10 -0700609 if (runBackMidGesture) {
610 performBack();
611 }
Matthew Ngc83b9892018-08-21 16:31:13 -0700612 }
613 mHandler.removeCallbacks(mExecuteBackRunnable);
Matthew Ngc414e282018-09-05 15:50:10 -0700614 if (runBackMidGesture) {
615 mHandler.postDelayed(mExecuteBackRunnable, BACK_GESTURE_POLL_TIMEOUT);
616 }
Matthew Ngc83b9892018-08-21 16:31:13 -0700617 }
618 }
619
620 private void endBackGesture() {
621 if (mBackGestureActive) {
622 mHandler.removeCallbacks(mExecuteBackRunnable);
623 mHomeAnimator = mNavigationBarView.getHomeButton().getCurrentView()
624 .animate()
625 .setDuration(BACK_BUTTON_FADE_IN_ALPHA)
626 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
627 if (mIsVertical) {
628 mHomeAnimator.translationY(0);
629 } else {
630 mHomeAnimator.translationX(0);
631 }
632 mHomeAnimator.start();
Matthew Ngb687c8a2018-10-02 11:31:38 -0700633 if (!shouldhideBackButton(mContext)) {
Matthew Ngc83b9892018-08-21 16:31:13 -0700634 mNavigationBarView.getBackButton().setAlpha(
635 mOverviewEventSender.getBackButtonAlpha(), true /* animate */);
636 }
Matthew Ngb687c8a2018-10-02 11:31:38 -0700637 if (shouldExecuteBackOnUp(mContext)) {
Matthew Ngc414e282018-09-05 15:50:10 -0700638 performBack();
639 }
Matthew Ngc83b9892018-08-21 16:31:13 -0700640 }
641 }
642
Winson Chung661d5f92018-05-21 18:41:39 -0700643 private void animateEnd() {
644 if (mTrackAnimator != null) {
645 mTrackAnimator.cancel();
646 }
647
Winson Chung4baf1242018-05-24 14:21:57 -0700648 ObjectAnimator trackAnimator = ObjectAnimator.ofPropertyValuesHolder(this,
649 PropertyValuesHolder.ofFloat(mTrackAlphaProperty, 0f),
650 PropertyValuesHolder.ofFloat(mTrackScaleProperty, TRACK_SCALE));
Winson Chung661d5f92018-05-21 18:41:39 -0700651 trackAnimator.setInterpolator(ALPHA_OUT);
652 trackAnimator.setDuration(ANIM_OUT_DURATION_MS);
653 ObjectAnimator navBarAnimator = ObjectAnimator.ofFloat(this, mNavBarAlphaProperty, 1f);
654 navBarAnimator.setInterpolator(ALPHA_IN);
655 navBarAnimator.setDuration(ANIM_IN_DURATION_MS);
656 mTrackAnimator = new AnimatorSet();
657 mTrackAnimator.playTogether(trackAnimator, navBarAnimator);
658 mTrackAnimator.addListener(mQuickScrubEndListener);
659 mTrackAnimator.start();
660 }
661
662 private void resetQuickScrub() {
663 mQuickScrubActive = false;
664 mAllowGestureDetection = false;
Matthew Ng819daaa2018-07-23 15:12:57 -0700665 if (mCurrentNavigationBarView != null) {
666 mCurrentNavigationBarView.setAlpha(1f);
667 }
Winson Chung661d5f92018-05-21 18:41:39 -0700668 mCurrentNavigationBarView = null;
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700669 updateHighlight();
670 }
671
Matthew Ngc83b9892018-08-21 16:31:13 -0700672 private void moveHomeButton(float pos) {
673 if (mHomeAnimator != null) {
674 mHomeAnimator.cancel();
675 mHomeAnimator = null;
676 }
677 final View homeButton = mNavigationBarView.getHomeButton().getCurrentView();
678 if (mIsVertical) {
679 homeButton.setTranslationY(pos);
680 } else {
681 homeButton.setTranslationX(pos);
682 }
683 }
684
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700685 private void updateHighlight() {
Matthew Ng908111d2018-06-26 15:22:56 -0700686 if (mTrackRect.isEmpty()) {
687 return;
688 }
Matthew Ng4fa3a9d2018-06-12 16:42:11 -0700689 int colorBase, colorGrad;
690 if (mDarkIntensity > 0.5f) {
691 colorBase = mContext.getColor(R.color.quick_step_track_background_background_dark);
692 colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_dark);
693 } else {
694 colorBase = mContext.getColor(R.color.quick_step_track_background_background_light);
695 colorGrad = mContext.getColor(R.color.quick_step_track_background_foreground_light);
696 }
697 mHighlight = new RadialGradient(0, mTrackRect.height() / 2,
698 mTrackRect.width() * GRADIENT_WIDTH, colorGrad, colorBase,
699 Shader.TileMode.CLAMP);
700 mTrackPaint.setShader(mHighlight);
Winson Chung661d5f92018-05-21 18:41:39 -0700701 }
702
Matthew Ngc83b9892018-08-21 16:31:13 -0700703 private boolean canPerformHomeBackGesture() {
Matthew Ngb687c8a2018-10-02 11:31:38 -0700704 return swipeHomeGoBackGestureEnabled(mContext)
705 && mOverviewEventSender.getBackButtonAlpha() > 0;
Matthew Ngc83b9892018-08-21 16:31:13 -0700706 }
707
708 private void performBack() {
709 sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
710 sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
711 mNavigationBarView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
712 }
713
714 private void sendEvent(int action, int code) {
715 long when = SystemClock.uptimeMillis();
716 final KeyEvent ev = new KeyEvent(when, when, action, code, 0 /* repeat */,
717 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD, 0 /* scancode */,
718 KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
719 InputDevice.SOURCE_KEYBOARD);
720 InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
721 }
722
Matthew Ng2ea93b72018-03-14 19:43:18 +0000723 private boolean proxyMotionEvents(MotionEvent event) {
724 final IOverviewProxy overviewProxy = mOverviewEventSender.getProxy();
725 event.transform(mTransformGlobalMatrix);
726 try {
727 if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
728 overviewProxy.onPreMotionEvent(mNavigationBarView.getDownHitTarget());
729 }
730 overviewProxy.onMotionEvent(event);
731 if (DEBUG_OVERVIEW_PROXY) {
732 Log.d(TAG_OPS, "Send MotionEvent: " + event.toString());
733 }
734 return true;
735 } catch (RemoteException e) {
736 Log.e(TAG, "Callback failed", e);
737 } finally {
738 event.transform(mTransformLocalMatrix);
Matthew Ngdb2734c2018-02-16 16:02:20 -0800739 }
Matthew Ng2ea93b72018-03-14 19:43:18 +0000740 return false;
Matthew Ngdb2734c2018-02-16 16:02:20 -0800741 }
Matthew Ngb687c8a2018-10-02 11:31:38 -0700742
743 private static boolean getBoolGlobalSetting(Context context, String key) {
744 return Settings.Global.getInt(context.getContentResolver(), key, 0) != 0;
745 }
746
747 public static boolean swipeHomeGoBackGestureEnabled(Context context) {
748 return !getBoolGlobalSetting(context, NAVBAR_EXPERIMENTS_DISABLED)
749 && getBoolGlobalSetting(context, PULL_HOME_GO_BACK_PROP);
750 }
751
752 public static boolean shouldhideBackButton(Context context) {
753 return swipeHomeGoBackGestureEnabled(context)
754 && getBoolGlobalSetting(context, HIDE_BACK_BUTTON_PROP);
755 }
756
757 public static boolean shouldExecuteBackOnUp(Context context) {
758 return !getBoolGlobalSetting(context, NAVBAR_EXPERIMENTS_DISABLED)
759 && getBoolGlobalSetting(context, BACK_AFTER_END_PROP);
760 }
Matthew Nga8f24262017-12-19 11:54:24 -0800761}