blob: 2a1f92f5edda86e6426913da68dea8ef7fcfce14 [file] [log] [blame]
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001/*
2 * Copyright (C) 2008 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 Chungc4e06202018-02-13 10:37:35 -080019import static android.view.MotionEvent.ACTION_DOWN;
20import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
21import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
22import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
23
John Spurlock1bbd49d2012-10-19 11:09:32 -040024import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040025import android.animation.LayoutTransition.TransitionListener;
26import android.animation.ObjectAnimator;
27import android.animation.TimeInterpolator;
28import android.animation.ValueAnimator;
Jorim Jaggi40db0292016-06-27 17:58:03 -070029import android.annotation.DrawableRes;
Mike Digman1e28a5a2018-02-14 10:49:19 -080030import android.annotation.StyleRes;
Daniel Sandler328310c2011-09-23 15:56:52 -040031import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040032import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020033import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080034import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070035import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050036import android.graphics.Rect;
Mike Digmana48cf192018-02-12 17:52:48 -080037import android.graphics.drawable.AnimatedVectorDrawable;
Mike Digman1e28a5a2018-02-14 10:49:19 -080038import android.graphics.drawable.Drawable;
Matthew Ng44b14502018-05-04 11:10:14 -070039import android.os.Bundle;
Daniel Sandler0b69b592012-01-23 21:08:36 -050040import android.os.Handler;
41import android.os.Message;
Matthew Ng8f25fb962018-01-16 17:17:24 -080042import android.os.SystemProperties;
Mike Digman7d092772018-01-11 12:10:32 -080043import android.support.annotation.ColorInt;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040044import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040045import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050046import android.util.SparseArray;
Jorim Jaggi40db0292016-06-27 17:58:03 -070047import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040048import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040049import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040050import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040051import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040052import android.view.ViewGroup;
Adrian Roos7e58a082018-03-09 16:40:56 +010053import android.view.WindowInsets;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040054import android.view.WindowManager;
Matthew Ng44b14502018-05-04 11:10:14 -070055import android.view.accessibility.AccessibilityNodeInfo;
56import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jason Monkf1ff2092014-04-29 16:50:53 -040057import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040058import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040059
Jason Monk9a376bc2017-05-10 09:52:10 -040060import com.android.settingslib.Utils;
Jason Monkde850bb2017-02-01 19:26:30 -050061import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040062import com.android.systemui.DockedStackExistsListener;
Matthew Ng7d05e772017-11-09 14:41:07 -080063import com.android.systemui.OverviewProxyService;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040064import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080065import com.android.systemui.RecentsComponent;
Matthew Ng44b14502018-05-04 11:10:14 -070066import com.android.systemui.SysUiServiceProvider;
Jason Monk67e6c802016-08-30 14:09:21 -040067import com.android.systemui.plugins.PluginListener;
68import com.android.systemui.plugins.PluginManager;
69import com.android.systemui.plugins.statusbar.phone.NavGesture;
70import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
Matthew Ng44b14502018-05-04 11:10:14 -070071import com.android.systemui.recents.Recents;
Tony Wickham05c1f852018-02-06 12:32:54 -080072import com.android.systemui.recents.RecentsOnboarding;
Matthew Ng44b14502018-05-04 11:10:14 -070073import com.android.systemui.shared.recents.IOverviewProxy;
Matthew Ng87cbf342018-02-15 12:21:18 -080074import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungc4e06202018-02-13 10:37:35 -080075import com.android.systemui.shared.system.NavigationBarCompat;
Matthew Ng84db1612018-04-17 16:48:21 -070076import com.android.systemui.shared.system.WindowManagerWrapper;
Jorim Jaggidd98d412015-11-18 15:57:38 -080077import com.android.systemui.stackdivider.Divider;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040078import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070079import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Tony Wickhamfb63fe82018-01-16 12:14:06 -080080import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070081
John Spurlockde84f0e2013-06-12 12:41:00 -040082import java.io.FileDescriptor;
83import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040084import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040085
Matthew Ng8f25fb962018-01-16 17:17:24 -080086import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
Matthew Ng8f25fb962018-01-16 17:17:24 -080087import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
Matthew Ng8a8c89c2018-03-01 13:21:43 -080088import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
Winson Chung8079af72018-05-10 11:12:55 -070089import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
Matthew Ng8f25fb962018-01-16 17:17:24 -080090
Jason Monk67e6c802016-08-30 14:09:21 -040091public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040092 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070093 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040094
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040095 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040096 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040097
Justin Paupore01915a12016-09-28 17:41:26 -070098 final static boolean ALTERNATE_CAR_MODE_UI = false;
99
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400100 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -0400101 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400102 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -0400103
Daniel Sandler60ee2562011-07-22 12:34:33 -0400104 boolean mVertical;
Adrian Roos090b7d82016-08-02 18:36:12 -0700105 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400106
John Spurlock7edfbca2013-09-14 11:58:55 -0400107 boolean mShowMenu;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800108 boolean mShowAccessibilityButton;
109 boolean mLongClickableAccessibilityButton;
Mike Digmana48cf192018-02-12 17:52:48 -0800110 boolean mShowRotateButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -0400111 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -0400112 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400113
Winson Chungc4e06202018-02-13 10:37:35 -0800114 private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE;
115 private Rect mHomeButtonBounds = new Rect();
116 private Rect mBackButtonBounds = new Rect();
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800117 private Rect mRecentsButtonBounds = new Rect();
Winson Chung8079af72018-05-10 11:12:55 -0700118 private Rect mRotationButtonBounds = new Rect();
Winson Chungc4e06202018-02-13 10:37:35 -0800119 private int[] mTmpPosition = new int[2];
Winson Chung661d5f92018-05-21 18:41:39 -0700120 private Rect mTmpRect = new Rect();
Winson Chungc4e06202018-02-13 10:37:35 -0800121
Matthew Ngeb5ce832018-05-15 17:50:37 -0700122 private KeyButtonDrawable mBackIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700123 private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
124 private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
125 private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
126 private KeyButtonDrawable mRecentIcon;
127 private KeyButtonDrawable mDockedIcon;
128 private KeyButtonDrawable mImeIcon;
129 private KeyButtonDrawable mMenuIcon;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800130 private KeyButtonDrawable mAccessibilityIcon;
Mike Digmanc8217582018-03-06 13:08:33 -0800131 private TintedKeyButtonDrawable mRotateSuggestionIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800132
Jason Monk67e6c802016-08-30 14:09:21 -0400133 private GestureHelper mGestureHelper;
Matthew Ng603b3292018-03-30 17:15:39 -0700134 private final DeadZone mDeadZone;
Matthew Ng1e14e962018-05-03 12:51:43 -0700135 private boolean mDeadZoneConsuming = false;
John Spurlock89835dd2013-08-16 15:06:51 -0400136 private final NavigationBarTransitions mBarTransitions;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800137 private final OverviewProxyService mOverviewProxyService;
Jim Millere898ac52012-04-06 17:10:57 -0700138
Daniel Sandler0b69b592012-01-23 21:08:36 -0500139 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
140 final static boolean WORKAROUND_INVALID_LAYOUT = true;
141 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
142
John Spurlock56d007b2013-10-28 18:40:56 -0400143 // performs manual animation in sync with layout transitions
144 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
145
Jorim Jaggif4797922014-08-04 22:49:41 +0200146 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700147 private boolean mLayoutTransitionsEnabled = true;
148 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700149 private boolean mUseCarModeUi = false;
150 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800151 private boolean mDockedStackExists;
Jorim Jaggif4797922014-08-04 22:49:41 +0200152
Felipe Leme15f915c2016-10-31 12:47:15 -0700153 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Winsonfde2e6a2016-03-22 16:03:10 -0700154 private Configuration mConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500155
Adrian Roosdb12b152016-07-12 15:38:55 -0700156 private NavigationBarInflaterView mNavigationInflaterView;
Jason Monk67e6c802016-08-30 14:09:21 -0400157 private RecentsComponent mRecentsComponent;
158 private Divider mDivider;
Tony Wickham05c1f852018-02-06 12:32:54 -0800159 private RecentsOnboarding mRecentsOnboarding;
Matthew Ng78f88d12018-01-23 12:39:55 -0800160 private NotificationPanelView mPanelView;
Adrian Roosdb12b152016-07-12 15:38:55 -0700161
Mike Digman1e28a5a2018-02-14 10:49:19 -0800162 private int mRotateBtnStyle = R.style.RotateButtonCCWStart90;
Mike Digmana48cf192018-02-12 17:52:48 -0800163
John Spurlock56d007b2013-10-28 18:40:56 -0400164 private class NavTransitionListener implements TransitionListener {
165 private boolean mBackTransitioning;
166 private boolean mHomeAppearing;
167 private long mStartDelay;
168 private long mDuration;
169 private TimeInterpolator mInterpolator;
170
171 @Override
172 public void startTransition(LayoutTransition transition, ViewGroup container,
173 View view, int transitionType) {
174 if (view.getId() == R.id.back) {
175 mBackTransitioning = true;
176 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
177 mHomeAppearing = true;
178 mStartDelay = transition.getStartDelay(transitionType);
179 mDuration = transition.getDuration(transitionType);
180 mInterpolator = transition.getInterpolator(transitionType);
181 }
182 }
183
184 @Override
185 public void endTransition(LayoutTransition transition, ViewGroup container,
186 View view, int transitionType) {
187 if (view.getId() == R.id.back) {
188 mBackTransitioning = false;
189 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
190 mHomeAppearing = false;
191 }
192 }
193
194 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500195 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800196
John Spurlock56d007b2013-10-28 18:40:56 -0400197 // When dismissing ime during unlock, force the back button to run the same appearance
198 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500199 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
200 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400201 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800202 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400203 a.setStartDelay(mStartDelay);
204 a.setDuration(mDuration);
205 a.setInterpolator(mInterpolator);
206 a.start();
207 }
208 }
209 }
210
Jason Monkf1ff2092014-04-29 16:50:53 -0400211 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
212 @Override
213 public void onClick(View view) {
Yohei Yukawa777ef952015-11-25 20:32:24 -0800214 mContext.getSystemService(InputMethodManager.class)
Seigo Nonaka14e13912015-05-06 21:04:13 -0700215 .showInputMethodPicker(true /* showAuxiliarySubtypes */);
Jason Monkf1ff2092014-04-29 16:50:53 -0400216 }
217 };
218
Daniel Sandler0b69b592012-01-23 21:08:36 -0500219 private class H extends Handler {
220 public void handleMessage(Message m) {
221 switch (m.what) {
222 case MSG_CHECK_INVALID_LAYOUT:
223 final String how = "" + m.obj;
224 final int w = getWidth();
225 final int h = getHeight();
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800226 final int vw = getCurrentView().getWidth();
227 final int vh = getCurrentView().getHeight();
Daniel Sandler0b69b592012-01-23 21:08:36 -0500228
229 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400230 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500231 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
232 how, w, h, vw, vh));
233 if (WORKAROUND_INVALID_LAYOUT) {
234 requestLayout();
235 }
236 }
237 break;
238 }
239 }
240 }
241
Matthew Ng44b14502018-05-04 11:10:14 -0700242 private final AccessibilityDelegate mQuickStepAccessibilityDelegate
243 = new AccessibilityDelegate() {
244 private AccessibilityAction mToggleOverviewAction;
245
246 @Override
247 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
248 super.onInitializeAccessibilityNodeInfo(host, info);
249 if (mToggleOverviewAction == null) {
250 mToggleOverviewAction = new AccessibilityAction(R.id.action_toggle_overview,
251 getContext().getString(R.string.quick_step_accessibility_toggle_overview));
252 }
253 info.addAction(mToggleOverviewAction);
254 }
255
256 @Override
257 public boolean performAccessibilityAction(View host, int action, Bundle args) {
258 switch (action) {
259 case R.id.action_toggle_overview:
260 SysUiServiceProvider.getComponent(getContext(), Recents.class)
261 .toggleRecentApps();
262 break;
263 default:
264 return super.performAccessibilityAction(host, action, args);
265 }
266 return true;
267 }
268 };
269
John Spurlocke932e302013-08-12 10:16:29 -0400270 public NavigationBarView(Context context, AttributeSet attrs) {
271 super(context, attrs);
272
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800273 mDisplay = ((WindowManager) context.getSystemService(
John Spurlocke932e302013-08-12 10:16:29 -0400274 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400275
John Spurlocke932e302013-08-12 10:16:29 -0400276 mVertical = false;
277 mShowMenu = false;
John Spurlocke932e302013-08-12 10:16:29 -0400278
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800279 mShowAccessibilityButton = false;
280 mLongClickableAccessibilityButton = false;
281
Matthew Ngf2946542018-02-12 14:13:18 -0800282 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
283 mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
284
Winsonfde2e6a2016-03-22 16:03:10 -0700285 mConfiguration = new Configuration();
286 mConfiguration.updateFrom(context.getResources().getConfiguration());
Matthew Ngd0a73e72018-03-02 15:16:03 -0800287 reloadNavIcons();
John Spurlocke932e302013-08-12 10:16:29 -0400288
John Spurlock7edfbca2013-09-14 11:58:55 -0400289 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500290
Felipe Leme15f915c2016-10-31 12:47:15 -0700291 mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
292 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
293 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
294 mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
295 mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800296 mButtonDispatchers.put(R.id.accessibility_button,
297 new ButtonDispatcher(R.id.accessibility_button));
Mike Digman7d092772018-01-11 12:10:32 -0800298 mButtonDispatchers.put(R.id.rotate_suggestion,
299 new ButtonDispatcher(R.id.rotate_suggestion));
Matthew Ng6607c3d2018-04-26 15:23:27 -0700300 mButtonDispatchers.put(R.id.menu_container,
301 new ButtonDispatcher(R.id.menu_container));
Matthew Ng603b3292018-03-30 17:15:39 -0700302 mDeadZone = new DeadZone(this);
John Spurlocke932e302013-08-12 10:16:29 -0400303 }
304
305 public BarTransitions getBarTransitions() {
306 return mBarTransitions;
307 }
308
Jorim Jaggi40db0292016-06-27 17:58:03 -0700309 public LightBarTransitionsController getLightTransitionsController() {
310 return mBarTransitions.getLightTransitionsController();
311 }
312
Matthew Ng78f88d12018-01-23 12:39:55 -0800313 public void setComponents(RecentsComponent recentsComponent, Divider divider,
314 NotificationPanelView panel) {
Jason Monk67e6c802016-08-30 14:09:21 -0400315 mRecentsComponent = recentsComponent;
316 mDivider = divider;
Matthew Ng78f88d12018-01-23 12:39:55 -0800317 mPanelView = panel;
Jason Monk67e6c802016-08-30 14:09:21 -0400318 if (mGestureHelper instanceof NavigationBarGestureHelper) {
319 ((NavigationBarGestureHelper) mGestureHelper).setComponents(
320 recentsComponent, divider, this);
321 }
Jim Millere898ac52012-04-06 17:10:57 -0700322 }
323
Jorim Jaggif4797922014-08-04 22:49:41 +0200324 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
325 mOnVerticalChangedListener = onVerticalChangedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200326 notifyVerticalChangedListener(mVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200327 }
328
Jim Millere898ac52012-04-06 17:10:57 -0700329 @Override
330 public boolean onInterceptTouchEvent(MotionEvent event) {
Matthew Ng1e14e962018-05-03 12:51:43 -0700331 if (shouldDeadZoneConsumeTouchEvents(event)) {
Matthew Ng603b3292018-03-30 17:15:39 -0700332 return true;
333 }
Winson Chungc4e06202018-02-13 10:37:35 -0800334 switch (event.getActionMasked()) {
335 case ACTION_DOWN:
336 int x = (int) event.getX();
337 int y = (int) event.getY();
338 mDownHitTarget = HIT_TARGET_NONE;
Winson Chungc6c9d402018-05-25 18:25:52 -0700339 if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
Winson Chungc4e06202018-02-13 10:37:35 -0800340 mDownHitTarget = HIT_TARGET_BACK;
Winson Chungc6c9d402018-05-25 18:25:52 -0700341 } else if (getHomeButton().isVisible() && mHomeButtonBounds.contains(x, y)) {
Winson Chungc4e06202018-02-13 10:37:35 -0800342 mDownHitTarget = HIT_TARGET_HOME;
Winson Chungc6c9d402018-05-25 18:25:52 -0700343 } else if (getRecentsButton().isVisible() && mRecentsButtonBounds.contains(x, y)) {
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800344 mDownHitTarget = HIT_TARGET_OVERVIEW;
Winson Chungc6c9d402018-05-25 18:25:52 -0700345 } else if (getRotateSuggestionButton().isVisible()
346 && mRotationButtonBounds.contains(x, y)) {
Winson Chung8079af72018-05-10 11:12:55 -0700347 mDownHitTarget = HIT_TARGET_ROTATION;
Winson Chungc4e06202018-02-13 10:37:35 -0800348 }
349 break;
350 }
Winson Chung49658842018-02-08 12:52:21 -0800351 return mGestureHelper.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700352 }
353
Winson Chung4faf38a2018-02-06 08:53:37 -0800354 @Override
355 public boolean onTouchEvent(MotionEvent event) {
Matthew Ng1e14e962018-05-03 12:51:43 -0700356 if (shouldDeadZoneConsumeTouchEvents(event)) {
Matthew Ng603b3292018-03-30 17:15:39 -0700357 return true;
358 }
Winson Chung4faf38a2018-02-06 08:53:37 -0800359 if (mGestureHelper.onTouchEvent(event)) {
360 return true;
361 }
Winson Chung49658842018-02-08 12:52:21 -0800362 return super.onTouchEvent(event);
Winson Chung4faf38a2018-02-06 08:53:37 -0800363 }
364
Matthew Ng1e14e962018-05-03 12:51:43 -0700365 private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
366 if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
367 switch (event.getActionMasked()) {
368 case MotionEvent.ACTION_DOWN:
369 // Allow gestures starting in the deadzone to be slippery
370 setSlippery(true);
371 mDeadZoneConsuming = true;
372 break;
373 case MotionEvent.ACTION_CANCEL:
374 case MotionEvent.ACTION_UP:
375 // When a gesture started in the deadzone is finished, restore slippery state
376 updateSlippery();
377 mDeadZoneConsuming = false;
378 break;
379 }
380 return true;
381 }
382 return false;
383 }
384
Winson Chungc4e06202018-02-13 10:37:35 -0800385 public @NavigationBarCompat.HitTarget int getDownHitTarget() {
386 return mDownHitTarget;
387 }
388
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700389 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500390 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700391 }
392
Daniel Sandler0b69b592012-01-23 21:08:36 -0500393 private H mHandler = new H();
394
John Spurlock7edfbca2013-09-14 11:58:55 -0400395 public View getCurrentView() {
396 return mCurrentView;
397 }
398
Xiaohui Chen10942302015-12-16 16:38:13 -0800399 public View[] getAllViews() {
400 return mRotatedViews;
401 }
402
Jason Monka2081822016-01-18 14:41:03 -0500403 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700404 return mButtonDispatchers.get(R.id.recent_apps);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400405 }
406
Jason Monka2081822016-01-18 14:41:03 -0500407 public ButtonDispatcher getMenuButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700408 return mButtonDispatchers.get(R.id.menu);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400409 }
410
Jason Monka2081822016-01-18 14:41:03 -0500411 public ButtonDispatcher getBackButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700412 return mButtonDispatchers.get(R.id.back);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400413 }
414
Jason Monka2081822016-01-18 14:41:03 -0500415 public ButtonDispatcher getHomeButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700416 return mButtonDispatchers.get(R.id.home);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400417 }
418
Jason Monka2081822016-01-18 14:41:03 -0500419 public ButtonDispatcher getImeSwitchButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700420 return mButtonDispatchers.get(R.id.ime_switcher);
Jason Monkf1ff2092014-04-29 16:50:53 -0400421 }
422
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800423 public ButtonDispatcher getAccessibilityButton() {
424 return mButtonDispatchers.get(R.id.accessibility_button);
425 }
426
Mike Digman7d092772018-01-11 12:10:32 -0800427 public ButtonDispatcher getRotateSuggestionButton() {
428 return mButtonDispatchers.get(R.id.rotate_suggestion);
429 }
430
Matthew Ng6607c3d2018-04-26 15:23:27 -0700431 public ButtonDispatcher getMenuContainer() {
432 return mButtonDispatchers.get(R.id.menu_container);
433 }
434
Jorim Jaggi40db0292016-06-27 17:58:03 -0700435 public SparseArray<ButtonDispatcher> getButtonDispatchers() {
436 return mButtonDispatchers;
437 }
438
Matthew Ng9c3bce52018-02-01 22:00:31 +0000439 public boolean isRecentsButtonVisible() {
440 return getRecentsButton().getVisibility() == View.VISIBLE;
441 }
442
Matthew Ng6ff33b72018-02-27 13:47:38 -0800443 public boolean isOverviewEnabled() {
444 return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0;
445 }
446
Matthew Ng8f25fb962018-01-16 17:17:24 -0800447 public boolean isQuickStepSwipeUpEnabled() {
Matthew Ngc1a97b12018-03-28 14:02:00 -0700448 return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled();
Matthew Ng8f25fb962018-01-16 17:17:24 -0800449 }
450
451 public boolean isQuickScrubEnabled() {
452 return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
Winson Chungd95a2252018-04-04 17:02:29 +0000453 && mOverviewProxyService.isEnabled() && isOverviewEnabled()
Matthew Ngc1a97b12018-03-28 14:02:00 -0700454 && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
Matthew Ng8f25fb962018-01-16 17:17:24 -0800455 }
456
Matthew Ngeb5ce832018-05-15 17:50:37 -0700457 // TODO(b/80003212): change car mode icons to vector icons.
Winsonfde2e6a2016-03-22 16:03:10 -0700458 private void updateCarModeIcons(Context ctx) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700459 mBackCarModeIcon = getDrawable(ctx,
460 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800461 mBackLandCarModeIcon = mBackCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700462 mBackAltCarModeIcon = getDrawable(ctx,
463 R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800464 mBackAltLandCarModeIcon = mBackAltCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700465 mHomeCarModeIcon = getDrawable(ctx,
466 R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800467 }
468
Matthew Ngd0a73e72018-03-02 15:16:03 -0800469 private void reloadNavIcons() {
470 updateIcons(mContext, Configuration.EMPTY, mConfiguration);
471 }
472
Winsonfde2e6a2016-03-22 16:03:10 -0700473 private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700474 int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
475 int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
476 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
477 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
478
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700479 if (oldConfig.orientation != newConfig.orientation
480 || oldConfig.densityDpi != newConfig.densityDpi) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700481 mDockedIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_docked);
482 mHomeDefaultIcon = getHomeDrawable(lightContext, darkContext);
Winsonfde2e6a2016-03-22 16:03:10 -0700483 }
Jason Monk1f785d42017-07-25 15:46:33 -0400484 if (oldConfig.densityDpi != newConfig.densityDpi
485 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700486 mBackIcon = getBackDrawable(lightContext, darkContext);
487 mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
488 mMenuIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_menu);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700489
Matthew Ngeb5ce832018-05-15 17:50:37 -0700490 mAccessibilityIcon = getDrawable(lightContext, darkContext,
491 R.drawable.ic_sysbar_accessibility_button, false /* hasShadow */);
Mike Digmane3909de2018-03-30 11:22:05 -0700492
Matthew Ngeb5ce832018-05-15 17:50:37 -0700493 mImeIcon = getDrawable(lightContext, darkContext, R.drawable.ic_ime_switcher_default,
494 false /* hasShadow */);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700495
Mike Digman1e28a5a2018-02-14 10:49:19 -0800496 updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
Mike Digman7d092772018-01-11 12:10:32 -0800497
Justin Paupore01915a12016-09-28 17:41:26 -0700498 if (ALTERNATE_CAR_MODE_UI) {
499 updateCarModeIcons(ctx);
500 }
Winsonfde2e6a2016-03-22 16:03:10 -0700501 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700502 }
503
Matthew Ngeb5ce832018-05-15 17:50:37 -0700504 public KeyButtonDrawable getBackDrawable(Context lightContext, Context darkContext) {
505 KeyButtonDrawable drawable = chooseNavigationIconDrawable(lightContext, darkContext,
506 R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_quick_step);
507 orientBackButton(drawable);
508 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800509 }
510
Matthew Ngeb5ce832018-05-15 17:50:37 -0700511 public KeyButtonDrawable getHomeDrawable(Context lightContext, Context darkContext) {
512 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
513 KeyButtonDrawable drawable = quickStepEnabled
514 ? getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home_quick_step)
515 : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home,
516 false /* hasShadow */);
517 orientHomeButton(drawable);
518 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800519 }
520
Matthew Ngeb5ce832018-05-15 17:50:37 -0700521 private void orientBackButton(KeyButtonDrawable drawable) {
522 final boolean useAltBack =
523 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
524 drawable.setRotation(useAltBack
525 ? -90 : (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) ? 180 : 0);
Matthew Ng87cbf342018-02-15 12:21:18 -0800526 }
527
Matthew Ngeb5ce832018-05-15 17:50:37 -0700528 private void orientHomeButton(KeyButtonDrawable drawable) {
529 drawable.setRotation(mVertical ? 90 : 0);
530 }
531
532 private KeyButtonDrawable chooseNavigationIconDrawable(Context lightContext,
533 Context darkContext, @DrawableRes int icon, @DrawableRes int quickStepIcon) {
Matthew Ngc1a97b12018-03-28 14:02:00 -0700534 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
Matthew Ng87cbf342018-02-15 12:21:18 -0800535 return quickStepEnabled
Matthew Ngeb5ce832018-05-15 17:50:37 -0700536 ? getDrawable(lightContext, darkContext, quickStepIcon)
537 : getDrawable(lightContext, darkContext, icon);
538 }
539
540 private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
541 @DrawableRes int icon) {
542 return getDrawable(lightContext, darkContext, icon, true /* hasShadow */);
543 }
544
545 private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
546 @DrawableRes int icon, boolean hasShadow) {
547 return KeyButtonDrawable.create(lightContext, lightContext.getDrawable(icon),
548 darkContext.getDrawable(icon), hasShadow);
Matthew Ng87cbf342018-02-15 12:21:18 -0800549 }
550
Jorim Jaggi40db0292016-06-27 17:58:03 -0700551 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
552 @DrawableRes int darkIcon) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700553 // Legacy image icons using separate light and dark images will not support shadows
554 return KeyButtonDrawable.create(ctx, ctx.getDrawable(lightIcon),
555 ctx.getDrawable(darkIcon), false /* hasShadow */);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700556 }
557
Mike Digmanc8217582018-03-06 13:08:33 -0800558 private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
Mike Digman7d092772018-01-11 12:10:32 -0800559 @ColorInt int lightColor, @ColorInt int darkColor) {
560 return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
561 }
562
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700563 @Override
564 public void setLayoutDirection(int layoutDirection) {
Matthew Ngd0a73e72018-03-02 15:16:03 -0800565 reloadNavIcons();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700566
567 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400568 }
569
Jorim Jaggi40db0292016-06-27 17:58:03 -0700570 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800571 return landscape
Matthew Ngeb5ce832018-05-15 17:50:37 -0700572 ? carMode ? mBackAltLandCarModeIcon : mBackIcon
573 : carMode ? mBackAltCarModeIcon : mBackIcon;
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800574 }
575
Jorim Jaggi40db0292016-06-27 17:58:03 -0700576 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800577 return landscape
Matthew Ngeb5ce832018-05-15 17:50:37 -0700578 ? carMode ? mBackLandCarModeIcon : mBackIcon
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800579 : carMode ? mBackCarModeIcon : mBackIcon;
580 }
581
Matthew Ngd0a73e72018-03-02 15:16:03 -0800582 public void setNavigationIconHints(int hints) {
583 if (hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400584 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
585 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
586 mTransitionListener.onBackAltCleared();
587 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400588 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500589 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400590 "Navigation icon hints = " + hints,
591 500).show();
592 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400593 mNavigationIconHints = hints;
Matthew Ngd0a73e72018-03-02 15:16:03 -0800594 updateNavButtonIcons();
595 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400596
Matthew Ngd0a73e72018-03-02 15:16:03 -0800597 public void setDisabledFlags(int disabledFlags) {
598 if (mDisabledFlags == disabledFlags) return;
599
600 final boolean overviewEnabledBefore = isOverviewEnabled();
601 mDisabledFlags = disabledFlags;
602
603 // Update icons if overview was just enabled to ensure the correct icons are present
604 if (!overviewEnabledBefore && isOverviewEnabled()) {
605 reloadNavIcons();
606 }
607
608 updateNavButtonIcons();
Winson Chung1be4c7e2018-05-23 18:24:13 -0700609 updateSlippery();
Tracy Zhou98140912018-06-05 12:09:14 -0700610 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ngd0a73e72018-03-02 15:16:03 -0800611 }
612
613 public void updateNavButtonIcons() {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800614 // We have to replace or restore the back and home button icons when exiting or entering
615 // carmode, respectively. Recents are not available in CarMode in nav bar so change
616 // to recent icon is not required.
Matthew Ngeb5ce832018-05-15 17:50:37 -0700617 final boolean useAltBack =
618 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
619 KeyButtonDrawable backIcon = useAltBack
620 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
621 : getBackIcon(mUseCarModeUi, mVertical);
622 KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
623 if (!mUseCarModeUi) {
624 orientBackButton(backIcon);
625 orientHomeButton(homeIcon);
626 }
627 getHomeButton().setImageDrawable(homeIcon);
Jason Monka2081822016-01-18 14:41:03 -0500628 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800629
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800630 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800631
Mike Digmana48cf192018-02-12 17:52:48 -0800632 // Update IME button visibility, a11y and rotate button always overrides the appearance
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700633 final boolean showImeButton =
Mike Digmana48cf192018-02-12 17:52:48 -0800634 !mShowAccessibilityButton &&
Matthew Ngd0a73e72018-03-02 15:16:03 -0800635 !mShowRotateButton &&
636 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
Jason Monka2081822016-01-18 14:41:03 -0500637 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700638 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800639
Mike Digmana48cf192018-02-12 17:52:48 -0800640 // Update menu button, visibility logic in method
Jason Monkf1ff2092014-04-29 16:50:53 -0400641 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700642 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400643
Mike Digmana48cf192018-02-12 17:52:48 -0800644 // Update rotate button, visibility altered by a11y button logic
645 getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
646
647 // Update a11y button, visibility logic in state method
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800648 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
649 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
650
Jorim Jaggi40db0292016-06-27 17:58:03 -0700651 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400652
Matthew Ngd0a73e72018-03-02 15:16:03 -0800653 boolean disableHome = ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700654
Justin Paupore01915a12016-09-28 17:41:26 -0700655 // Always disable recents when alternate car mode UI is active.
Matthew Ng6ff33b72018-02-27 13:47:38 -0800656 boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
Charles Hee57ff812017-10-26 10:01:35 +0100657
Matthew Ngeb5ce832018-05-15 17:50:37 -0700658 boolean disableBack = ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack;
Daniel Sandler029d5872011-09-12 00:58:58 -0400659
Matthew Ng87cbf342018-02-15 12:21:18 -0800660 // When screen pinning, don't hide back and home when connected service or back and
661 // recents buttons when disconnected from launcher service in screen pinning mode,
662 // as they are used for exiting.
Matthew Ng6ff33b72018-02-27 13:47:38 -0800663 final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
Winson Chungd95a2252018-04-04 17:02:29 +0000664 if (mOverviewProxyService.isEnabled()) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800665 // Use interaction flags to show/hide navigation buttons but will be shown if required
666 // to exit screen pinning.
Matthew Ng8f25fb962018-01-16 17:17:24 -0800667 final int flags = mOverviewProxyService.getInteractionFlags();
668 disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0;
Matthew Ng6ff33b72018-02-27 13:47:38 -0800669 if (pinningActive) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800670 disableBack = disableHome = false;
Matthew Ng87cbf342018-02-15 12:21:18 -0800671 }
Matthew Ng6ff33b72018-02-27 13:47:38 -0800672 } else if (pinningActive) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800673 disableBack = disableRecent = false;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800674 }
Charles Hee57ff812017-10-26 10:01:35 +0100675
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800676 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400677 if (navButtons != null) {
678 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400679 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400680 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
681 lt.addTransitionListener(mTransitionListener);
682 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400683 }
684 }
685
Jason Monka2081822016-01-18 14:41:03 -0500686 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500687 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500688 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400689 }
690
Matthew Ng87cbf342018-02-15 12:21:18 -0800691 public boolean inScreenPinning() {
Matthew Ng6ff33b72018-02-27 13:47:38 -0800692 return ActivityManagerWrapper.getInstance().isScreenPinningActive();
Jason Monk17488b92014-11-06 11:26:14 -0500693 }
694
Jorim Jaggi37c11802015-08-18 20:27:54 -0700695 public void setLayoutTransitionsEnabled(boolean enabled) {
696 mLayoutTransitionsEnabled = enabled;
697 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700698 }
699
Jorim Jaggi37c11802015-08-18 20:27:54 -0700700 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
701 setUseFadingAnimations(wakeAndUnlocking);
702 mWakeAndUnlocking = wakeAndUnlocking;
703 updateLayoutTransitionsEnabled();
704 }
705
706 private void updateLayoutTransitionsEnabled() {
707 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800708 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700709 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400710 if (lt != null) {
711 if (enabled) {
712 lt.enableTransitionType(LayoutTransition.APPEARING);
713 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
714 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
715 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
716 } else {
717 lt.disableTransitionType(LayoutTransition.APPEARING);
718 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
719 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
720 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
721 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700722 }
723 }
724
725 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500726 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
727 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700728 if (lp != null) {
729 boolean old = lp.windowAnimations != 0;
730 if (!old && useFadingAnimations) {
731 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
732 } else if (old && !useFadingAnimations) {
733 lp.windowAnimations = 0;
734 } else {
735 return;
736 }
737 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500738 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700739 }
740 }
741
Matthew Ng2ea93b72018-03-14 19:43:18 +0000742 public void onNavigationButtonLongPress(View v) {
743 mGestureHelper.onNavigationButtonLongPress(v);
744 }
745
Matthew Ng78f88d12018-01-23 12:39:55 -0800746 public void onPanelExpandedChange(boolean expanded) {
747 updateSlippery();
748 }
749
Matthew Ng8f25fb962018-01-16 17:17:24 -0800750 public void updateStates() {
Matthew Ng44b14502018-05-04 11:10:14 -0700751 final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
Mike Digmanf77fb912018-05-21 11:21:30 -0700752
753 if (mNavigationInflaterView != null) {
754 // Reinflate the navbar if needed, no-op unless the swipe up state changes
755 mNavigationInflaterView.onLikelyDefaultLayoutChange();
756 }
757
Matthew Ng8f25fb962018-01-16 17:17:24 -0800758 updateSlippery();
Winson Chung770d7e92018-03-20 17:51:39 -0700759 reloadNavIcons();
Matthew Ngd0a73e72018-03-02 15:16:03 -0800760 updateNavButtonIcons();
Winson Chungf9e30272018-03-26 17:25:36 -0700761 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ng44b14502018-05-04 11:10:14 -0700762 WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!showSwipeUpUI);
763 getHomeButton().setAccessibilityDelegate(
764 showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
Matthew Ng8f25fb962018-01-16 17:17:24 -0800765 }
766
Matthew Ng78f88d12018-01-23 12:39:55 -0800767 private void updateSlippery() {
Winson Chung770d7e92018-03-20 17:51:39 -0700768 setSlippery(!isQuickStepSwipeUpEnabled() || mPanelView.isFullyExpanded());
Matthew Ng78f88d12018-01-23 12:39:55 -0800769 }
770
Matthew Ng7d05e772017-11-09 14:41:07 -0800771 private void setSlippery(boolean slippery) {
772 boolean changed = false;
773 final ViewGroup navbarView = ((ViewGroup) getParent());
774 final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
775 .getLayoutParams();
Matthew Ng9c3bce52018-02-01 22:00:31 +0000776 if (lp == null) {
777 return;
778 }
Matthew Ng7d05e772017-11-09 14:41:07 -0800779 if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
780 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
781 changed = true;
782 } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) {
783 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
784 changed = true;
785 }
786 if (changed) {
787 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
788 wm.updateViewLayout(navbarView, lp);
789 }
790 }
791
Daniel Sandler56598cd2011-09-15 16:02:56 -0400792 public void setMenuVisibility(final boolean show) {
793 setMenuVisibility(show, false);
794 }
795
796 public void setMenuVisibility(final boolean show, final boolean force) {
797 if (!force && mShowMenu == show) return;
798
799 mShowMenu = show;
800
Mike Digmana48cf192018-02-12 17:52:48 -0800801 // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown.
802 final boolean shouldShow = mShowMenu &&
803 !mShowAccessibilityButton &&
804 !mShowRotateButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400805 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800806
Jason Monka2081822016-01-18 14:41:03 -0500807 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400808 }
809
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800810 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
811 mShowAccessibilityButton = visible;
812 mLongClickableAccessibilityButton = longClickable;
813 if (visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800814 // Accessibility button overrides Menu, IME switcher and rotate buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800815 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700816 getImeSwitchButton().setVisibility(View.INVISIBLE);
Mike Digman1e28a5a2018-02-14 10:49:19 -0800817 setRotateButtonVisibility(false);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800818 }
819
820 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
821 getAccessibilityButton().setLongClickable(longClickable);
822 }
823
Mike Digman1e28a5a2018-02-14 10:49:19 -0800824 public void updateRotateSuggestionButtonStyle(@StyleRes int style, boolean setIcon) {
825 mRotateBtnStyle = style;
826 final Context ctx = getContext();
827
828 // Extract the dark and light tints
829 final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
830 final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
831 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
832 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
833 final int lightColor = Utils.getColorAttr(lightContext, R.attr.singleToneColor);
834 final int darkColor = Utils.getColorAttr(darkContext, R.attr.singleToneColor);
835
836 // Use the supplied style to set the icon's rotation parameters
837 Context rotateContext = new ContextThemeWrapper(ctx, style);
838
839 // Recreate the icon and set it if needed
Mike Digmanc8217582018-03-06 13:08:33 -0800840 TintedKeyButtonDrawable priorIcon = mRotateSuggestionIcon;
Mike Digman1e28a5a2018-02-14 10:49:19 -0800841 mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
842 lightColor, darkColor);
Mike Digmanc8217582018-03-06 13:08:33 -0800843
844 // Apply any prior set dark intensity
845 if (priorIcon != null && priorIcon.isDarkIntensitySet()) {
846 mRotateSuggestionIcon.setDarkIntensity(priorIcon.getDarkIntensity());
847 }
848
Mike Digman1e28a5a2018-02-14 10:49:19 -0800849 if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
Mike Digmana48cf192018-02-12 17:52:48 -0800850 }
851
Mike Digman9b50b762018-04-19 10:50:35 -0700852 public int setRotateButtonVisibility(final boolean visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800853 // Never show if a11y is visible
854 final boolean adjVisible = visible && !mShowAccessibilityButton;
855 final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
856
Mike Digman1e28a5a2018-02-14 10:49:19 -0800857 // No need to do anything if the request matches the current state
Mike Digman9b50b762018-04-19 10:50:35 -0700858 if (vis == getRotateSuggestionButton().getVisibility()) return vis;
Mike Digman1e28a5a2018-02-14 10:49:19 -0800859
Mike Digmana48cf192018-02-12 17:52:48 -0800860 getRotateSuggestionButton().setVisibility(vis);
861 mShowRotateButton = visible;
862
Mike Digman1e28a5a2018-02-14 10:49:19 -0800863 // Stop any active animations if hidden
864 if (!visible) {
865 Drawable d = mRotateSuggestionIcon.getDrawable(0);
866 if (d instanceof AnimatedVectorDrawable) {
867 AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d;
868 avd.clearAnimationCallbacks();
869 avd.reset();
870 }
871 }
872
Mike Digmana48cf192018-02-12 17:52:48 -0800873 // Hide/restore other button visibility, if necessary
Matthew Ngd0a73e72018-03-02 15:16:03 -0800874 updateNavButtonIcons();
Mike Digman9b50b762018-04-19 10:50:35 -0700875
876 // Return applied visibility
877 return vis;
Mike Digmana48cf192018-02-12 17:52:48 -0800878 }
879
Mike Digman1e28a5a2018-02-14 10:49:19 -0800880 public boolean isRotateButtonVisible() { return mShowRotateButton; }
881
Winson Chung661d5f92018-05-21 18:41:39 -0700882 /**
883 * @return the button at the given {@param x} and {@param y}.
884 */
885 ButtonDispatcher getButtonAtPosition(int x, int y) {
886 for (int i = 0; i < mButtonDispatchers.size(); i++) {
887 ButtonDispatcher button = mButtonDispatchers.valueAt(i);
888 View buttonView = button.getCurrentView();
889 if (buttonView != null) {
890 buttonView.getHitRect(mTmpRect);
891 offsetDescendantRectToMyCoords(buttonView, mTmpRect);
892 if (mTmpRect.contains(x, y)) {
893 return button;
894 }
895 }
896 }
897 return null;
Matthew Ng6607c3d2018-04-26 15:23:27 -0700898 }
899
Jim Miller960892c2012-05-23 15:50:04 -0700900 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400901 public void onFinishInflate() {
Winson Chung661d5f92018-05-21 18:41:39 -0700902 mNavigationInflaterView = findViewById(R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700903 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500904
905 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200906
Jason Monk32e3bb52017-07-27 12:35:41 -0400907 DockedStackExistsListener.register(mDockedListener);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700908 updateRotatedViews();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100909 }
910
Matthew Nga8f24262017-12-19 11:54:24 -0800911 public void onDarkIntensityChange(float intensity) {
912 if (mGestureHelper != null) {
913 mGestureHelper.onDarkIntensityChange(intensity);
914 }
915 }
916
917 @Override
918 protected void onDraw(Canvas canvas) {
919 mGestureHelper.onDraw(canvas);
Matthew Ng603b3292018-03-30 17:15:39 -0700920 mDeadZone.onDraw(canvas);
Matthew Nga8f24262017-12-19 11:54:24 -0800921 super.onDraw(canvas);
922 }
923
924 @Override
925 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
926 super.onLayout(changed, left, top, right, bottom);
Winson Chungc4e06202018-02-13 10:37:35 -0800927 updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
928 updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800929 updateButtonLocationOnScreen(getRecentsButton(), mRecentsButtonBounds);
Winson Chung8079af72018-05-10 11:12:55 -0700930 updateButtonLocationOnScreen(getRotateSuggestionButton(), mRotationButtonBounds);
Matthew Nga8f24262017-12-19 11:54:24 -0800931 mGestureHelper.onLayout(changed, left, top, right, bottom);
Tracy Zhou559d97c2018-04-07 23:54:46 -0700932 mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
Matthew Nga8f24262017-12-19 11:54:24 -0800933 }
934
Winson Chungc4e06202018-02-13 10:37:35 -0800935 private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) {
936 View view = button.getCurrentView();
937 if (view == null) {
938 buttonBounds.setEmpty();
939 return;
940 }
Matthew Ng3b7e3902018-03-22 16:06:09 -0700941 // Temporarily reset the translation back to origin to get the position in window
942 final float posX = view.getTranslationX();
943 final float posY = view.getTranslationY();
944 view.setTranslationX(0);
945 view.setTranslationY(0);
Winson Chungc4e06202018-02-13 10:37:35 -0800946 view.getLocationInWindow(mTmpPosition);
947 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
948 mTmpPosition[0] + view.getMeasuredWidth(),
949 mTmpPosition[1] + view.getMeasuredHeight());
Matthew Ng3b7e3902018-03-22 16:06:09 -0700950 view.setTranslationX(posX);
951 view.setTranslationY(posY);
Winson Chungc4e06202018-02-13 10:37:35 -0800952 }
953
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700954 private void updateRotatedViews() {
Jason Monk9a6552d2016-05-20 11:21:59 -0400955 mRotatedViews[Surface.ROTATION_0] =
956 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
957 mRotatedViews[Surface.ROTATION_270] =
958 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
959
Jason Monk199a2d02017-07-28 11:08:27 -0400960 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400961 }
962
Adrian Roosa98b32c2016-08-11 10:41:08 -0700963 public boolean needsReorient(int rotation) {
964 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700965 }
966
Jason Monk199a2d02017-07-28 11:08:27 -0400967 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400968 final int rot = mDisplay.getRotation();
969 for (int i=0; i<4; i++) {
970 mRotatedViews[i].setVisibility(View.GONE);
971 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400972 mCurrentView = mRotatedViews[rot];
973 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700974 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Matthew Ng1efc9c32018-04-11 18:13:56 -0700975 mNavigationInflaterView.updateButtonDispatchersCurrentView();
Jorim Jaggi37c11802015-08-18 20:27:54 -0700976 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700977 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400978 }
979
980 private void updateRecentsIcon() {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700981 mDockedIcon.setRotation(mDockedStackExists && mVertical ? 90 : 0);
Jason Monk9a6552d2016-05-20 11:21:59 -0400982 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700983 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400984 }
985
986 public boolean isVertical() {
987 return mVertical;
988 }
989
990 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400991 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400992
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700993 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Matthew Ng603b3292018-03-30 17:15:39 -0700994 mDeadZone.onConfigurationChanged(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400995
Daniel Sandler6da2b762011-09-14 16:04:59 -0400996 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700997 mBarTransitions.init();
Daniel Sandler56598cd2011-09-15 16:02:56 -0400998 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400999
Daniel Sandler60ee2562011-07-22 12:34:33 -04001000 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -07001001 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -04001002 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -08001003
Matthew Ng5fd80412018-02-14 14:40:31 -08001004 // Resolve layout direction if not resolved since components changing layout direction such
1005 // as changing languages will recreate this view and the direction will be resolved later
1006 if (!isLayoutDirectionResolved()) {
1007 resolveLayoutDirection();
1008 }
Selim Cinek92d892c2014-09-11 15:11:00 +02001009 updateTaskSwitchHelper();
Matthew Ngd0a73e72018-03-02 15:16:03 -08001010 updateNavButtonIcons();
Xiaohui Chen9efa5de2016-11-22 10:34:38 -08001011
Xiaohui Chen40e978e2016-11-29 15:10:04 -08001012 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001013 }
Daniel Sandler48852952011-12-01 14:34:23 -05001014
Selim Cinek92d892c2014-09-11 15:11:00 +02001015 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -05001016 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +02001017 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -08001018 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +02001019 }
1020
Daniel Sandler0b69b592012-01-23 21:08:36 -05001021 @Override
1022 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -04001023 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -05001024 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -04001025
1026 final boolean newVertical = w > 0 && h > w;
1027 if (newVertical != mVertical) {
1028 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -04001029 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -04001030 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +02001031 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -04001032 }
1033
Daniel Sandler0b69b592012-01-23 21:08:36 -05001034 postCheckForInvalidLayout("sizeChanged");
1035 super.onSizeChanged(w, h, oldw, oldh);
1036 }
1037
Selim Cinek92d892c2014-09-11 15:11:00 +02001038 private void notifyVerticalChangedListener(boolean newVertical) {
1039 if (mOnVerticalChangedListener != null) {
1040 mOnVerticalChangedListener.onVerticalChanged(newVertical);
1041 }
1042 }
1043
Selim Cinek17a327a2014-08-25 15:03:48 +02001044 @Override
1045 protected void onConfigurationChanged(Configuration newConfig) {
1046 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001047 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +02001048 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -07001049 updateIcons(getContext(), mConfiguration, newConfig);
1050 updateRecentsIcon();
Tony Wickham05c1f852018-02-06 12:32:54 -08001051 mRecentsOnboarding.onConfigurationChanged(newConfig);
Jason Monk1f785d42017-07-25 15:46:33 -04001052 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
1053 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001054 // If car mode or density changes, we need to reset the icons.
Matthew Ngd0a73e72018-03-02 15:16:03 -08001055 updateNavButtonIcons();
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001056 }
Winsonfde2e6a2016-03-22 16:03:10 -07001057 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001058 }
1059
1060 /**
1061 * If the configuration changed, update the carmode and return that it was updated.
1062 */
1063 private boolean updateCarMode(Configuration newConfig) {
1064 boolean uiCarModeChanged = false;
1065 if (newConfig != null) {
1066 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -07001067 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
1068
1069 if (isCarMode != mInCarMode) {
1070 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -07001071 if (ALTERNATE_CAR_MODE_UI) {
1072 mUseCarModeUi = isCarMode;
1073 uiCarModeChanged = true;
1074 } else {
1075 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
1076 mUseCarModeUi = false;
1077 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001078 }
1079 }
1080 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +02001081 }
1082
Daniel Sandler0b69b592012-01-23 21:08:36 -05001083 /*
1084 @Override
1085 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -04001086 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -04001087 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -05001088 changed?"changed":"notchanged", left, top, right, bottom));
1089 super.onLayout(changed, left, top, right, bottom);
1090 }
1091
1092 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
1093 // fails, any touch on the display will fix the layout.
1094 @Override
1095 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -04001096 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -05001097 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1098 postCheckForInvalidLayout("touch");
1099 }
1100 return super.onInterceptTouchEvent(ev);
1101 }
1102 */
John Spurlock209bede2013-07-17 12:23:27 -04001103
Daniel Sandler0b69b592012-01-23 21:08:36 -05001104
Daniel Sandler48852952011-12-01 14:34:23 -05001105 private String getResourceName(int resId) {
1106 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -05001107 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -05001108 try {
1109 return res.getResourceName(resId);
1110 } catch (android.content.res.Resources.NotFoundException ex) {
1111 return "(unknown)";
1112 }
1113 } else {
1114 return "(null)";
1115 }
1116 }
1117
Daniel Sandler0b69b592012-01-23 21:08:36 -05001118 private void postCheckForInvalidLayout(final String how) {
1119 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
1120 }
1121
Daniel Sandler48852952011-12-01 14:34:23 -05001122 private static String visibilityToString(int vis) {
1123 switch (vis) {
1124 case View.INVISIBLE:
1125 return "INVISIBLE";
1126 case View.GONE:
1127 return "GONE";
1128 default:
1129 return "VISIBLE";
1130 }
1131 }
1132
Jason Monk67e6c802016-08-30 14:09:21 -04001133 @Override
1134 protected void onAttachedToWindow() {
1135 super.onAttachedToWindow();
Adrian Roos7e58a082018-03-09 16:40:56 +01001136 requestApplyInsets();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -07001137 reorient();
Jason Monkde850bb2017-02-01 19:26:30 -05001138 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -08001139 Dependency.get(PluginManager.class).addPluginListener(this,
1140 NavGesture.class, false /* Only one */);
Winson Chungf9e30272018-03-26 17:25:36 -07001141 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Jason Monk67e6c802016-08-30 14:09:21 -04001142 }
1143
1144 @Override
1145 protected void onDetachedFromWindow() {
1146 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -05001147 Dependency.get(PluginManager.class).removePluginListener(this);
1148 if (mGestureHelper != null) {
1149 mGestureHelper.destroy();
1150 }
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001151 setUpSwipeUpOnboarding(false);
1152 }
1153
1154 private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
1155 if (connectedToOverviewProxy) {
Tony Wickham05c1f852018-02-06 12:32:54 -08001156 mRecentsOnboarding.onConnectedToLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001157 } else {
Tony Wickham05c1f852018-02-06 12:32:54 -08001158 mRecentsOnboarding.onDisconnectedFromLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001159 }
Jason Monk67e6c802016-08-30 14:09:21 -04001160 }
1161
1162 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -05001163 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -04001164 mGestureHelper = plugin.getGestureHelper();
1165 updateTaskSwitchHelper();
1166 }
1167
1168 @Override
1169 public void onPluginDisconnected(NavGesture plugin) {
1170 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
1171 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -05001172 if (mGestureHelper != null) {
1173 mGestureHelper.destroy();
1174 }
Jason Monk67e6c802016-08-30 14:09:21 -04001175 mGestureHelper = defaultHelper;
1176 updateTaskSwitchHelper();
1177 }
1178
Daniel Sandler48852952011-12-01 14:34:23 -05001179 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1180 pw.println("NavigationBarView {");
1181 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -07001182 final Point size = new Point();
1183 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -05001184
Jason Monk2a6ea9c2017-01-26 11:14:51 -05001185 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -05001186 + " " + visibilityToString(getVisibility())));
1187
1188 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -07001189 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -04001190 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -05001191 + r.toShortString()
1192 + " " + visibilityToString(getWindowVisibility())
1193 + (offscreen ? " OFFSCREEN!" : ""));
1194
Winson Chung661d5f92018-05-21 18:41:39 -07001195 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -08001196 getResourceName(getCurrentView().getId()),
1197 getCurrentView().getWidth(), getCurrentView().getHeight(),
Winson Chung661d5f92018-05-21 18:41:39 -07001198 visibilityToString(getCurrentView().getVisibility()),
1199 getCurrentView().getAlpha()));
Daniel Sandler48852952011-12-01 14:34:23 -05001200
John Spurlock41c1e352013-09-16 13:57:13 -04001201 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -05001202 mDisabledFlags,
1203 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -05001204 mShowMenu ? "true" : "false"));
1205
John Spurlock56d007b2013-10-28 18:40:56 -04001206 dumpButton(pw, "back", getBackButton());
1207 dumpButton(pw, "home", getHomeButton());
1208 dumpButton(pw, "rcnt", getRecentsButton());
1209 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001210 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -05001211
Tracy Zhou66efefd2018-05-16 15:03:09 -07001212 mRecentsOnboarding.dump(pw);
1213
Daniel Sandler48852952011-12-01 14:34:23 -05001214 pw.println(" }");
1215 }
Jim Millere898ac52012-04-06 17:10:57 -07001216
Adrian Roos7e58a082018-03-09 16:40:56 +01001217 @Override
1218 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
1219 setPadding(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
1220 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
1221 return super.onApplyWindowInsets(insets);
1222 }
1223
Jason Monka2081822016-01-18 14:41:03 -05001224 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -04001225 pw.print(" " + caption + ": ");
1226 if (button == null) {
1227 pw.print("null");
1228 } else {
Jason Monka2081822016-01-18 14:41:03 -05001229 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -04001230 + " alpha=" + button.getAlpha()
1231 );
John Spurlock56d007b2013-10-28 18:40:56 -04001232 }
1233 pw.println();
1234 }
1235
Jorim Jaggif4797922014-08-04 22:49:41 +02001236 public interface OnVerticalChangedListener {
1237 void onVerticalChanged(boolean isVertical);
1238 }
Jason Monka2081822016-01-18 14:41:03 -05001239
Jason Monk32e3bb52017-07-27 12:35:41 -04001240 private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> {
1241 mDockedStackExists = exists;
1242 updateRecentsIcon();
1243 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001244}