blob: f0415cb0c69fe49a2835212ffeec4c02983e8997 [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 Chung1aa24b92019-04-24 15:17:33 -070019import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON;
Hongwei Wang98d08582019-08-14 14:55:27 -070020import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
Gus Prevasab336792018-11-14 13:52:20 -050021
Winson Chunga7067002019-05-07 11:50:42 -070022import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
Winson Chunga3132982019-04-08 13:27:47 -070023import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
Winson Chunga7067002019-05-07 11:50:42 -070024import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
Winson Chung5b6a1fe2019-07-26 16:38:08 -070025import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
Winson Chunga7067002019-05-07 11:50:42 -070026import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
Winson Chungcb6454e2019-07-23 09:58:47 -070027import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SEARCH_DISABLED;
Tracy Zhou24fd0282019-05-20 14:40:38 -070028import static com.android.systemui.shared.system.QuickStepContract.isGesturalMode;
Winson Chung775d2872019-03-27 14:14:01 -070029import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
Winson Chungc4e06202018-02-13 10:37:35 -080030
John Spurlock1bbd49d2012-10-19 11:09:32 -040031import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040032import android.animation.LayoutTransition.TransitionListener;
33import android.animation.ObjectAnimator;
Matthew Ngca4592b2018-08-06 14:12:37 -070034import android.animation.PropertyValuesHolder;
John Spurlock56d007b2013-10-28 18:40:56 -040035import android.animation.TimeInterpolator;
36import android.animation.ValueAnimator;
Jorim Jaggi40db0292016-06-27 17:58:03 -070037import android.annotation.DrawableRes;
Daniel Sandler328310c2011-09-23 15:56:52 -040038import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040039import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020040import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080041import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070042import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050043import android.graphics.Rect;
Sunny Goyalaac6c882019-02-11 11:57:58 -080044import android.graphics.Region;
45import android.graphics.Region.Op;
Matthew Ng44b14502018-05-04 11:10:14 -070046import android.os.Bundle;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040047import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040048import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050049import android.util.SparseArray;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040050import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040051import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040052import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040053import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040054import android.view.ViewGroup;
Tracy Zhouefc34662019-04-22 13:37:12 -070055import android.view.ViewTreeObserver.InternalInsetsInfo;
56import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
Adrian Roos7e58a082018-03-09 16:40:56 +010057import android.view.WindowInsets;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040058import android.view.WindowManager;
Matthew Ng44b14502018-05-04 11:10:14 -070059import android.view.accessibility.AccessibilityNodeInfo;
60import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jason Monkf1ff2092014-04-29 16:50:53 -040061import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040062import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040063
Jeff Chang2aaa91a2018-11-08 18:04:16 +080064import com.android.internal.annotations.VisibleForTesting;
Jason Monkde850bb2017-02-01 19:26:30 -050065import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040066import com.android.systemui.DockedStackExistsListener;
Matthew Ngca4592b2018-08-06 14:12:37 -070067import com.android.systemui.Interpolators;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040068import com.android.systemui.R;
Matthew Ng44b14502018-05-04 11:10:14 -070069import com.android.systemui.SysUiServiceProvider;
Matthew Ng0548fbc2019-01-11 12:24:13 -080070import com.android.systemui.assist.AssistManager;
Gus Prevasab336792018-11-14 13:52:20 -050071import com.android.systemui.recents.OverviewProxyService;
Matthew Ng44b14502018-05-04 11:10:14 -070072import com.android.systemui.recents.Recents;
Tony Wickham05c1f852018-02-06 12:32:54 -080073import com.android.systemui.recents.RecentsOnboarding;
Matthew Ng87cbf342018-02-15 12:21:18 -080074import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chunge108b672019-03-06 16:11:28 -080075import com.android.systemui.shared.system.QuickStepContract;
Matthew Ng84db1612018-04-17 16:48:21 -070076import com.android.systemui.shared.system.WindowManagerWrapper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040077import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070078import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070079
John Spurlockde84f0e2013-06-12 12:41:00 -040080import java.io.FileDescriptor;
81import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040082import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040083
Matthew Nge0d5ccd32019-05-08 15:13:22 -070084public class NavigationBarView extends FrameLayout implements
Winson Chung1aa24b92019-04-24 15:17:33 -070085 NavigationModeController.ModeChangedListener {
Daniel Sandler60ee2562011-07-22 12:34:33 -040086 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070087 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040088
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040089 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040090 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040091
Justin Paupore01915a12016-09-28 17:41:26 -070092 final static boolean ALTERNATE_CAR_MODE_UI = false;
93
Daniel Sandler5c8da942011-06-28 00:29:04 -040094 View mCurrentView = null;
Charles Chenaa94d95b2019-02-19 14:18:19 +080095 private View mVertical;
96 private View mHorizontal;
Daniel Sandler60ee2562011-07-22 12:34:33 -040097
Charles Chenaa94d95b2019-02-19 14:18:19 +080098 /** Indicates that navigation bar is vertical. */
99 private boolean mIsVertical;
Adrian Roos090b7d82016-08-02 18:36:12 -0700100 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400101
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800102 boolean mLongClickableAccessibilityButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -0400103 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -0400104 int mNavigationIconHints = 0;
Winson Chung1aa24b92019-04-24 15:17:33 -0700105 private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400106
Winson Chungc4e06202018-02-13 10:37:35 -0800107 private Rect mHomeButtonBounds = new Rect();
108 private Rect mBackButtonBounds = new Rect();
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800109 private Rect mRecentsButtonBounds = new Rect();
Winson Chung8079af72018-05-10 11:12:55 -0700110 private Rect mRotationButtonBounds = new Rect();
Sunny Goyalaac6c882019-02-11 11:57:58 -0800111 private final Region mActiveRegion = new Region();
Winson Chungc4e06202018-02-13 10:37:35 -0800112 private int[] mTmpPosition = new int[2];
113
Matthew Ngeb5ce832018-05-15 17:50:37 -0700114 private KeyButtonDrawable mBackIcon;
Matthew Ngec5b8412018-08-22 10:45:08 -0700115 private KeyButtonDrawable mHomeDefaultIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700116 private KeyButtonDrawable mRecentIcon;
117 private KeyButtonDrawable mDockedIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800118
Sunny Goyala6a58122019-04-02 10:20:29 -0700119 private final EdgeBackGestureHandler mEdgeBackGestureHandler;
Matthew Ng603b3292018-03-30 17:15:39 -0700120 private final DeadZone mDeadZone;
Matthew Ng1e14e962018-05-03 12:51:43 -0700121 private boolean mDeadZoneConsuming = false;
John Spurlock89835dd2013-08-16 15:06:51 -0400122 private final NavigationBarTransitions mBarTransitions;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800123 private final OverviewProxyService mOverviewProxyService;
Jim Millere898ac52012-04-06 17:10:57 -0700124
John Spurlock56d007b2013-10-28 18:40:56 -0400125 // performs manual animation in sync with layout transitions
126 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
127
Jorim Jaggif4797922014-08-04 22:49:41 +0200128 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700129 private boolean mLayoutTransitionsEnabled = true;
130 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700131 private boolean mUseCarModeUi = false;
132 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800133 private boolean mDockedStackExists;
Matthew Ngf03c3a62019-04-03 13:52:57 -0700134 private boolean mImeVisible;
Jorim Jaggif4797922014-08-04 22:49:41 +0200135
Felipe Leme15f915c2016-10-31 12:47:15 -0700136 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Matthew Ng25593cc2018-09-12 16:05:41 -0700137 private final ContextualButtonGroup mContextualButtonGroup;
Winsonfde2e6a2016-03-22 16:03:10 -0700138 private Configuration mConfiguration;
Matthew Ng8c056c12018-10-15 15:16:46 -0700139 private Configuration mTmpLastConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500140
Adrian Roosdb12b152016-07-12 15:38:55 -0700141 private NavigationBarInflaterView mNavigationInflaterView;
Tony Wickham05c1f852018-02-06 12:32:54 -0800142 private RecentsOnboarding mRecentsOnboarding;
Matthew Ng78f88d12018-01-23 12:39:55 -0800143 private NotificationPanelView mPanelView;
Tracy Zhou24fd0282019-05-20 14:40:38 -0700144 private FloatingRotationButton mFloatingRotationButton;
145 private RotationButtonController mRotationButtonController;
Adrian Roosdb12b152016-07-12 15:38:55 -0700146
Winson Chung775d2872019-03-27 14:14:01 -0700147 private NavBarTintController mTintController;
Matthew Ngb831fb42019-01-30 11:20:48 -0800148
Matthew Ng20136e62018-05-30 12:20:31 -0700149 /**
150 * Helper that is responsible for showing the right toast when a disallowed activity operation
151 * occurred. In pinned mode, we show instructions on how to break out of this mode, whilst in
152 * fully locked mode we only show that unlocking is blocked.
153 */
154 private ScreenPinningNotify mScreenPinningNotify;
155
John Spurlock56d007b2013-10-28 18:40:56 -0400156 private class NavTransitionListener implements TransitionListener {
157 private boolean mBackTransitioning;
158 private boolean mHomeAppearing;
159 private long mStartDelay;
160 private long mDuration;
161 private TimeInterpolator mInterpolator;
162
163 @Override
164 public void startTransition(LayoutTransition transition, ViewGroup container,
165 View view, int transitionType) {
166 if (view.getId() == R.id.back) {
167 mBackTransitioning = true;
168 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
169 mHomeAppearing = true;
170 mStartDelay = transition.getStartDelay(transitionType);
171 mDuration = transition.getDuration(transitionType);
172 mInterpolator = transition.getInterpolator(transitionType);
173 }
174 }
175
176 @Override
177 public void endTransition(LayoutTransition transition, ViewGroup container,
178 View view, int transitionType) {
179 if (view.getId() == R.id.back) {
180 mBackTransitioning = false;
181 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
182 mHomeAppearing = false;
183 }
184 }
185
186 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500187 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800188
John Spurlock56d007b2013-10-28 18:40:56 -0400189 // When dismissing ime during unlock, force the back button to run the same appearance
190 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500191 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
192 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400193 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800194 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400195 a.setStartDelay(mStartDelay);
196 a.setDuration(mDuration);
197 a.setInterpolator(mInterpolator);
198 a.start();
199 }
200 }
201 }
202
Jason Monkf1ff2092014-04-29 16:50:53 -0400203 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
204 @Override
205 public void onClick(View view) {
lumark0b05f9e2018-11-26 15:09:06 +0800206 mContext.getSystemService(InputMethodManager.class).showInputMethodPickerFromSystem(
207 true /* showAuxiliarySubtypes */, getContext().getDisplayId());
Jason Monkf1ff2092014-04-29 16:50:53 -0400208 }
209 };
210
Matthew Ng44b14502018-05-04 11:10:14 -0700211 private final AccessibilityDelegate mQuickStepAccessibilityDelegate
212 = new AccessibilityDelegate() {
213 private AccessibilityAction mToggleOverviewAction;
214
215 @Override
216 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
217 super.onInitializeAccessibilityNodeInfo(host, info);
218 if (mToggleOverviewAction == null) {
219 mToggleOverviewAction = new AccessibilityAction(R.id.action_toggle_overview,
220 getContext().getString(R.string.quick_step_accessibility_toggle_overview));
221 }
222 info.addAction(mToggleOverviewAction);
223 }
224
225 @Override
226 public boolean performAccessibilityAction(View host, int action, Bundle args) {
Jason Monk05dd5672018-08-09 09:38:21 -0400227 if (action == R.id.action_toggle_overview) {
228 SysUiServiceProvider.getComponent(getContext(), Recents.class)
229 .toggleRecentApps();
230 } else {
231 return super.performAccessibilityAction(host, action, args);
Matthew Ng44b14502018-05-04 11:10:14 -0700232 }
233 return true;
234 }
235 };
236
Tracy Zhouefc34662019-04-22 13:37:12 -0700237 private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener = info -> {
238 // When the nav bar is in 2-button or 3-button mode, or when IME is visible in fully
239 // gestural mode, the entire nav bar should be touchable.
Tracy Zhou24fd0282019-05-20 14:40:38 -0700240 if (!isGesturalMode(mNavBarMode) || mImeVisible) {
Tracy Zhouefc34662019-04-22 13:37:12 -0700241 info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
242 return;
243 }
Winson Chungd882ce12019-06-05 09:57:01 -0700244
Tracy Zhouefc34662019-04-22 13:37:12 -0700245 info.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
Winson Chungd882ce12019-06-05 09:57:01 -0700246 ButtonDispatcher imeSwitchButton = getImeSwitchButton();
247 if (imeSwitchButton.getVisibility() == VISIBLE) {
248 // If the IME is not up, but the ime switch button is visible, then make sure that
249 // button is touchable
250 int[] loc = new int[2];
251 View buttonView = imeSwitchButton.getCurrentView();
252 buttonView.getLocationInWindow(loc);
253 info.touchableRegion.set(loc[0], loc[1], loc[0] + buttonView.getWidth(),
254 loc[1] + buttonView.getHeight());
255 return;
256 }
Tracy Zhou24fd0282019-05-20 14:40:38 -0700257 info.touchableRegion.setEmpty();
Tracy Zhouefc34662019-04-22 13:37:12 -0700258 };
259
John Spurlocke932e302013-08-12 10:16:29 -0400260 public NavigationBarView(Context context, AttributeSet attrs) {
261 super(context, attrs);
262
Charles Chenaa94d95b2019-02-19 14:18:19 +0800263 mIsVertical = false;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800264 mLongClickableAccessibilityButton = false;
Tracy Zhouefc34662019-04-22 13:37:12 -0700265 mNavBarMode = Dependency.get(NavigationModeController.class).addListener(this);
Tracy Zhou24fd0282019-05-20 14:40:38 -0700266 boolean isGesturalMode = isGesturalMode(mNavBarMode);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800267
Matthew Ng25593cc2018-09-12 16:05:41 -0700268 // Set up the context group of buttons
269 mContextualButtonGroup = new ContextualButtonGroup(R.id.menu_container);
Matthew Ng25593cc2018-09-12 16:05:41 -0700270 final ContextualButton imeSwitcherButton = new ContextualButton(R.id.ime_switcher,
271 R.drawable.ic_ime_switcher_default);
272 final RotationContextButton rotateSuggestionButton = new RotationContextButton(
Tracy Zhou24fd0282019-05-20 14:40:38 -0700273 R.id.rotate_suggestion, R.drawable.ic_sysbar_rotate_button);
Matthew Ng25593cc2018-09-12 16:05:41 -0700274 final ContextualButton accessibilityButton =
275 new ContextualButton(R.id.accessibility_button,
276 R.drawable.ic_sysbar_accessibility_button);
Matthew Ng25593cc2018-09-12 16:05:41 -0700277 mContextualButtonGroup.addButton(imeSwitcherButton);
Tracy Zhouefc34662019-04-22 13:37:12 -0700278 if (!isGesturalMode) {
279 mContextualButtonGroup.addButton(rotateSuggestionButton);
280 }
Matthew Ng25593cc2018-09-12 16:05:41 -0700281 mContextualButtonGroup.addButton(accessibilityButton);
282
Matthew Ngf2946542018-02-12 14:13:18 -0800283 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
284 mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
Tracy Zhou24fd0282019-05-20 14:40:38 -0700285 mFloatingRotationButton = new FloatingRotationButton(context);
286 mRotationButtonController = new RotationButtonController(context,
287 R.style.RotateButtonCCWStart90,
288 isGesturalMode ? mFloatingRotationButton : rotateSuggestionButton);
Matthew Ngf2946542018-02-12 14:13:18 -0800289
Tracy Zhouefc34662019-04-22 13:37:12 -0700290 final ContextualButton backButton = new ContextualButton(R.id.back, 0);
Tracy Zhouefc34662019-04-22 13:37:12 -0700291
Winsonfde2e6a2016-03-22 16:03:10 -0700292 mConfiguration = new Configuration();
Matthew Ng8c056c12018-10-15 15:16:46 -0700293 mTmpLastConfiguration = new Configuration();
Winsonfde2e6a2016-03-22 16:03:10 -0700294 mConfiguration.updateFrom(context.getResources().getConfiguration());
John Spurlocke932e302013-08-12 10:16:29 -0400295
Matthew Ng20136e62018-05-30 12:20:31 -0700296 mScreenPinningNotify = new ScreenPinningNotify(mContext);
John Spurlock7edfbca2013-09-14 11:58:55 -0400297 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500298
Tracy Zhouefc34662019-04-22 13:37:12 -0700299 mButtonDispatchers.put(R.id.back, backButton);
Felipe Leme15f915c2016-10-31 12:47:15 -0700300 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
Matthew Ngb55c02c2019-02-15 16:20:31 -0800301 mButtonDispatchers.put(R.id.home_handle, new ButtonDispatcher(R.id.home_handle));
Felipe Leme15f915c2016-10-31 12:47:15 -0700302 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
Matthew Ng25593cc2018-09-12 16:05:41 -0700303 mButtonDispatchers.put(R.id.ime_switcher, imeSwitcherButton);
304 mButtonDispatchers.put(R.id.accessibility_button, accessibilityButton);
305 mButtonDispatchers.put(R.id.rotate_suggestion, rotateSuggestionButton);
306 mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
Matthew Ng603b3292018-03-30 17:15:39 -0700307 mDeadZone = new DeadZone(this);
Matthew Ng86a436e2018-10-26 16:00:53 -0700308
Winson Chung04ff8bda2019-04-02 15:08:59 -0700309 mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService);
Winson Chung775d2872019-03-27 14:14:01 -0700310 mTintController = new NavBarTintController(this, getLightTransitionsController());
Matthew Ng355fe212018-12-14 17:42:38 -0800311 }
312
Winson Chung775d2872019-03-27 14:14:01 -0700313 public NavBarTintController getTintController() {
314 return mTintController;
John Spurlocke932e302013-08-12 10:16:29 -0400315 }
316
James O'Leary4335c702019-05-29 12:38:51 -0400317 public NavigationBarTransitions getBarTransitions() {
John Spurlocke932e302013-08-12 10:16:29 -0400318 return mBarTransitions;
319 }
320
Jorim Jaggi40db0292016-06-27 17:58:03 -0700321 public LightBarTransitionsController getLightTransitionsController() {
322 return mBarTransitions.getLightTransitionsController();
323 }
324
Matthew Ng0548fbc2019-01-11 12:24:13 -0800325 public void setComponents(NotificationPanelView panel, AssistManager assistManager) {
Matthew Ng78f88d12018-01-23 12:39:55 -0800326 mPanelView = panel;
Winson Chung56a667b2019-07-30 13:51:27 -0700327 updatePanelSystemUiStateFlags();
Matthew Ng1cf6eac2018-11-27 15:06:55 -0800328 }
329
Winson Chung600c1862019-03-07 15:14:49 -0800330 @Override
331 protected void dispatchDraw(Canvas canvas) {
332 super.dispatchDraw(canvas);
Winson Chung775d2872019-03-27 14:14:01 -0700333 mTintController.onDraw();
Winson Chung600c1862019-03-07 15:14:49 -0800334 }
335
Jorim Jaggif4797922014-08-04 22:49:41 +0200336 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
337 mOnVerticalChangedListener = onVerticalChangedListener;
Charles Chenaa94d95b2019-02-19 14:18:19 +0800338 notifyVerticalChangedListener(mIsVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200339 }
340
Jim Millere898ac52012-04-06 17:10:57 -0700341 @Override
342 public boolean onInterceptTouchEvent(MotionEvent event) {
Sunny Goyala6a58122019-04-02 10:20:29 -0700343 return shouldDeadZoneConsumeTouchEvents(event) || super.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700344 }
345
Winson Chung4faf38a2018-02-06 08:53:37 -0800346 @Override
347 public boolean onTouchEvent(MotionEvent event) {
Matthew Ng472d3e42018-06-14 15:16:55 -0700348 shouldDeadZoneConsumeTouchEvents(event);
Winson Chung49658842018-02-08 12:52:21 -0800349 return super.onTouchEvent(event);
Winson Chung4faf38a2018-02-06 08:53:37 -0800350 }
351
Winson Chung3d6c0802019-10-04 10:37:12 -0700352 void onSystemUiVisibilityChanged(int systemUiVisibility) {
353 mEdgeBackGestureHandler.onSystemUiVisibilityChanged(systemUiVisibility);
354 }
355
Winson Chung775d2872019-03-27 14:14:01 -0700356 void onBarTransition(int newMode) {
357 if (newMode == MODE_OPAQUE) {
358 // If the nav bar background is opaque, stop auto tinting since we know the icons are
359 // showing over a dark background
360 mTintController.stop();
361 getLightTransitionsController().setIconsDark(false /* dark */, true /* animate */);
362 } else {
363 mTintController.start();
364 }
365 }
366
Matthew Ng1e14e962018-05-03 12:51:43 -0700367 private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
Sunny Goyala6a58122019-04-02 10:20:29 -0700368 int action = event.getActionMasked();
369 if (action == MotionEvent.ACTION_DOWN) {
370 mDeadZoneConsuming = false;
371 }
Matthew Ng1e14e962018-05-03 12:51:43 -0700372 if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
Sunny Goyala6a58122019-04-02 10:20:29 -0700373 switch (action) {
Matthew Ng1e14e962018-05-03 12:51:43 -0700374 case MotionEvent.ACTION_DOWN:
375 // Allow gestures starting in the deadzone to be slippery
376 setSlippery(true);
377 mDeadZoneConsuming = true;
378 break;
379 case MotionEvent.ACTION_CANCEL:
380 case MotionEvent.ACTION_UP:
381 // When a gesture started in the deadzone is finished, restore slippery state
382 updateSlippery();
383 mDeadZoneConsuming = false;
384 break;
385 }
386 return true;
387 }
388 return false;
389 }
390
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700391 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500392 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700393 }
394
John Spurlock7edfbca2013-09-14 11:58:55 -0400395 public View getCurrentView() {
396 return mCurrentView;
397 }
398
Tracy Zhou24fd0282019-05-20 14:40:38 -0700399 public RotationButtonController getRotationButtonController() {
400 return mRotationButtonController;
401 }
402
403 public FloatingRotationButton getFloatingRotationButton() {
404 return mFloatingRotationButton;
405 }
406
Jason Monka2081822016-01-18 14:41:03 -0500407 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700408 return mButtonDispatchers.get(R.id.recent_apps);
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
Matthew Ng761562d2018-09-17 11:13:21 -0700427 public RotationContextButton getRotateSuggestionButton() {
Tracy Zhouefc34662019-04-22 13:37:12 -0700428 return (RotationContextButton) mButtonDispatchers.get(R.id.rotate_suggestion);
429 }
430
Matthew Ngb55c02c2019-02-15 16:20:31 -0800431 public ButtonDispatcher getHomeHandle() {
432 return mButtonDispatchers.get(R.id.home_handle);
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
Matthew Ngd0a73e72018-03-02 15:16:03 -0800451 private void reloadNavIcons() {
Matthew Ng8c056c12018-10-15 15:16:46 -0700452 updateIcons(Configuration.EMPTY);
Matthew Ngd0a73e72018-03-02 15:16:03 -0800453 }
454
Matthew Ng8c056c12018-10-15 15:16:46 -0700455 private void updateIcons(Configuration oldConfig) {
456 final boolean orientationChange = oldConfig.orientation != mConfiguration.orientation;
457 final boolean densityChange = oldConfig.densityDpi != mConfiguration.densityDpi;
458 final boolean dirChange = oldConfig.getLayoutDirection() != mConfiguration.getLayoutDirection();
Matthew Ngca4592b2018-08-06 14:12:37 -0700459
460 if (orientationChange || densityChange) {
Matthew Ngd6865ba2018-08-27 17:58:41 -0700461 mDockedIcon = getDrawable(R.drawable.ic_sysbar_docked);
462 mHomeDefaultIcon = getHomeDrawable();
Winsonfde2e6a2016-03-22 16:03:10 -0700463 }
Matthew Ngca4592b2018-08-06 14:12:37 -0700464 if (densityChange || dirChange) {
Matthew Ngd6865ba2018-08-27 17:58:41 -0700465 mRecentIcon = getDrawable(R.drawable.ic_sysbar_recent);
Matthew Ng25593cc2018-09-12 16:05:41 -0700466 mContextualButtonGroup.updateIcons();
Winsonfde2e6a2016-03-22 16:03:10 -0700467 }
Matthew Ngca4592b2018-08-06 14:12:37 -0700468 if (orientationChange || densityChange || dirChange) {
Matthew Ngd6865ba2018-08-27 17:58:41 -0700469 mBackIcon = getBackDrawable();
Matthew Ngca4592b2018-08-06 14:12:37 -0700470 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700471 }
472
Matthew Ngd6865ba2018-08-27 17:58:41 -0700473 public KeyButtonDrawable getBackDrawable() {
Tracy Zhouefc34662019-04-22 13:37:12 -0700474 KeyButtonDrawable drawable = getDrawable(getBackDrawableRes());
Matthew Ngeb5ce832018-05-15 17:50:37 -0700475 orientBackButton(drawable);
476 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800477 }
478
Tracy Zhouefc34662019-04-22 13:37:12 -0700479 public @DrawableRes int getBackDrawableRes() {
480 return chooseNavigationIconDrawableRes(R.drawable.ic_sysbar_back,
481 R.drawable.ic_sysbar_back_quick_step);
482 }
483
Matthew Ngd6865ba2018-08-27 17:58:41 -0700484 public KeyButtonDrawable getHomeDrawable() {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700485 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
486 KeyButtonDrawable drawable = quickStepEnabled
Matthew Ngd6865ba2018-08-27 17:58:41 -0700487 ? getDrawable(R.drawable.ic_sysbar_home_quick_step)
488 : getDrawable(R.drawable.ic_sysbar_home);
Matthew Ngeb5ce832018-05-15 17:50:37 -0700489 orientHomeButton(drawable);
490 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800491 }
492
Matthew Ngeb5ce832018-05-15 17:50:37 -0700493 private void orientBackButton(KeyButtonDrawable drawable) {
494 final boolean useAltBack =
Matthew Ngca4592b2018-08-06 14:12:37 -0700495 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
Matthew Ng8c056c12018-10-15 15:16:46 -0700496 final boolean isRtl = mConfiguration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
Matthew Ngd04bd0f2019-04-08 17:29:45 -0700497 float degrees = useAltBack ? (isRtl ? 90 : -90) : 0;
Matthew Ngca4592b2018-08-06 14:12:37 -0700498 if (drawable.getRotation() == degrees) {
499 return;
500 }
501
Tracy Zhou24fd0282019-05-20 14:40:38 -0700502 if (isGesturalMode(mNavBarMode)) {
Matthew Ngf03c3a62019-04-03 13:52:57 -0700503 drawable.setRotation(degrees);
504 return;
505 }
506
Matthew Ngca4592b2018-08-06 14:12:37 -0700507 // Animate the back button's rotation to the new degrees and only in portrait move up the
508 // back button to line up with the other buttons
Charles Chenaa94d95b2019-02-19 14:18:19 +0800509 float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mIsVertical && useAltBack
Matthew Ngca4592b2018-08-06 14:12:37 -0700510 ? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
511 : 0;
512 ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
513 PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_ROTATE, degrees),
514 PropertyValuesHolder.ofFloat(KeyButtonDrawable.KEY_DRAWABLE_TRANSLATE_Y, targetY));
515 navBarAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
516 navBarAnimator.setDuration(200);
517 navBarAnimator.start();
Matthew Ng87cbf342018-02-15 12:21:18 -0800518 }
519
Matthew Ngeb5ce832018-05-15 17:50:37 -0700520 private void orientHomeButton(KeyButtonDrawable drawable) {
Charles Chenaa94d95b2019-02-19 14:18:19 +0800521 drawable.setRotation(mIsVertical ? 90 : 0);
Matthew Ngeb5ce832018-05-15 17:50:37 -0700522 }
523
Matthew Ngd6865ba2018-08-27 17:58:41 -0700524 private KeyButtonDrawable chooseNavigationIconDrawable(@DrawableRes int icon,
525 @DrawableRes int quickStepIcon) {
Tracy Zhouefc34662019-04-22 13:37:12 -0700526 return getDrawable(chooseNavigationIconDrawableRes(icon, quickStepIcon));
527 }
528
529 private @DrawableRes int chooseNavigationIconDrawableRes(@DrawableRes int icon,
530 @DrawableRes int quickStepIcon) {
Matthew Ngc1a97b12018-03-28 14:02:00 -0700531 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
Tracy Zhouefc34662019-04-22 13:37:12 -0700532 return quickStepEnabled ? quickStepIcon : icon;
Matthew Ngeb5ce832018-05-15 17:50:37 -0700533 }
534
Matthew Ngd6865ba2018-08-27 17:58:41 -0700535 private KeyButtonDrawable getDrawable(@DrawableRes int icon) {
Matthew Ng25593cc2018-09-12 16:05:41 -0700536 return KeyButtonDrawable.create(mContext, icon, true /* hasShadow */);
Matthew Ngeb5ce832018-05-15 17:50:37 -0700537 }
538
Matthew Ngd6865ba2018-08-27 17:58:41 -0700539 private KeyButtonDrawable getDrawable(@DrawableRes int icon, boolean hasShadow) {
Matthew Ng25593cc2018-09-12 16:05:41 -0700540 return KeyButtonDrawable.create(mContext, icon, hasShadow);
Mike Digman7d092772018-01-11 12:10:32 -0800541 }
542
Winson Chung2102ae82019-06-19 13:15:24 -0700543 public void setWindowVisible(boolean visible) {
544 mTintController.setWindowVisible(visible);
545 mRotationButtonController.onNavigationBarWindowVisibilityChange(visible);
546 }
547
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700548 @Override
549 public void setLayoutDirection(int layoutDirection) {
Matthew Ngd0a73e72018-03-02 15:16:03 -0800550 reloadNavIcons();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700551
552 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400553 }
554
Matthew Ngd0a73e72018-03-02 15:16:03 -0800555 public void setNavigationIconHints(int hints) {
556 if (hints == mNavigationIconHints) return;
Matthew Ng691d5582019-04-04 14:59:17 -0700557 final boolean newBackAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
558 final boolean oldBackAlt =
559 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
560 if (newBackAlt != oldBackAlt) {
561 onImeVisibilityChanged(newBackAlt);
John Spurlock56d007b2013-10-28 18:40:56 -0400562 }
Matthew Ng691d5582019-04-04 14:59:17 -0700563
Daniel Sandler328310c2011-09-23 15:56:52 -0400564 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500565 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400566 "Navigation icon hints = " + hints,
567 500).show();
568 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400569 mNavigationIconHints = hints;
Matthew Ngd0a73e72018-03-02 15:16:03 -0800570 updateNavButtonIcons();
571 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400572
Matthew Ng691d5582019-04-04 14:59:17 -0700573 private void onImeVisibilityChanged(boolean visible) {
574 if (!visible) {
575 mTransitionListener.onBackAltCleared();
576 }
577 mImeVisible = visible;
Tracy Zhou24fd0282019-05-20 14:40:38 -0700578 mRotationButtonController.getRotationButton().setCanShowRotationButton(!mImeVisible);
Matthew Ng691d5582019-04-04 14:59:17 -0700579 }
580
Matthew Ngd0a73e72018-03-02 15:16:03 -0800581 public void setDisabledFlags(int disabledFlags) {
582 if (mDisabledFlags == disabledFlags) return;
583
584 final boolean overviewEnabledBefore = isOverviewEnabled();
585 mDisabledFlags = disabledFlags;
586
587 // Update icons if overview was just enabled to ensure the correct icons are present
588 if (!overviewEnabledBefore && isOverviewEnabled()) {
589 reloadNavIcons();
590 }
591
592 updateNavButtonIcons();
Winson Chung1be4c7e2018-05-23 18:24:13 -0700593 updateSlippery();
Tracy Zhou98140912018-06-05 12:09:14 -0700594 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Winson Chung56a667b2019-07-30 13:51:27 -0700595 updateDisabledSystemUiStateFlags();
Matthew Ngd0a73e72018-03-02 15:16:03 -0800596 }
597
598 public void updateNavButtonIcons() {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800599 // We have to replace or restore the back and home button icons when exiting or entering
600 // carmode, respectively. Recents are not available in CarMode in nav bar so change
601 // to recent icon is not required.
Matthew Ngeb5ce832018-05-15 17:50:37 -0700602 final boolean useAltBack =
603 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
Matthew Ngd6865ba2018-08-27 17:58:41 -0700604 KeyButtonDrawable backIcon = mBackIcon;
Matthew Ngec5b8412018-08-22 10:45:08 -0700605 orientBackButton(backIcon);
Matthew Ngd6865ba2018-08-27 17:58:41 -0700606 KeyButtonDrawable homeIcon = mHomeDefaultIcon;
Matthew Ngeb5ce832018-05-15 17:50:37 -0700607 if (!mUseCarModeUi) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700608 orientHomeButton(homeIcon);
609 }
610 getHomeButton().setImageDrawable(homeIcon);
Jason Monka2081822016-01-18 14:41:03 -0500611 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800612
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800613 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800614
Mike Digmana48cf192018-02-12 17:52:48 -0800615 // Update IME button visibility, a11y and rotate button always overrides the appearance
Tracy Zhouefc34662019-04-22 13:37:12 -0700616 mContextualButtonGroup.setButtonVisibility(R.id.ime_switcher,
Matthew Ng25593cc2018-09-12 16:05:41 -0700617 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800618
Jorim Jaggi40db0292016-06-27 17:58:03 -0700619 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400620
Tracy Zhou24fd0282019-05-20 14:40:38 -0700621 boolean disableHome = isGesturalMode(mNavBarMode)
Winson Chunge108b672019-03-06 16:11:28 -0800622 || ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700623
Jeff Chang2aaa91a2018-11-08 18:04:16 +0800624 // Always disable recents when alternate car mode UI is active and for secondary displays.
625 boolean disableRecent = isRecentsButtonDisabled();
Charles Hee57ff812017-10-26 10:01:35 +0100626
Sunny Goyalbe4e0542019-08-08 16:36:14 -0700627 // Disable the home handle if both hone and recents are disabled
628 boolean disableHomeHandle = disableRecent
629 && ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
630
Tracy Zhou24fd0282019-05-20 14:40:38 -0700631 boolean disableBack = !useAltBack && (isGesturalMode(mNavBarMode)
Matthew Ngf03c3a62019-04-03 13:52:57 -0700632 || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
Daniel Sandler029d5872011-09-12 00:58:58 -0400633
Matthew Ng87cbf342018-02-15 12:21:18 -0800634 // When screen pinning, don't hide back and home when connected service or back and
635 // recents buttons when disconnected from launcher service in screen pinning mode,
636 // as they are used for exiting.
Matthew Ng6ff33b72018-02-27 13:47:38 -0800637 final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
Winson Chungd95a2252018-04-04 17:02:29 +0000638 if (mOverviewProxyService.isEnabled()) {
Winson Chung30c62602019-05-09 13:34:48 -0700639 // Force disable recents when not in legacy mode
640 disableRecent |= !QuickStepContract.isLegacyMode(mNavBarMode);
Tracy Zhou63b50472019-07-01 15:27:02 -0700641 if (pinningActive && !QuickStepContract.isGesturalMode(mNavBarMode)) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800642 disableBack = disableHome = false;
Matthew Ng87cbf342018-02-15 12:21:18 -0800643 }
Matthew Ng6ff33b72018-02-27 13:47:38 -0800644 } else if (pinningActive) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800645 disableBack = disableRecent = false;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800646 }
Charles Hee57ff812017-10-26 10:01:35 +0100647
Winson Chunge108b672019-03-06 16:11:28 -0800648 ViewGroup navButtons = getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400649 if (navButtons != null) {
650 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400651 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400652 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
653 lt.addTransitionListener(mTransitionListener);
654 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400655 }
656 }
657
Jason Monka2081822016-01-18 14:41:03 -0500658 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500659 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500660 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
Sunny Goyalbe4e0542019-08-08 16:36:14 -0700661 getHomeHandle().setVisibility(disableHomeHandle ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400662 }
663
Jeff Chang2aaa91a2018-11-08 18:04:16 +0800664 @VisibleForTesting
665 boolean isRecentsButtonDisabled() {
666 return mUseCarModeUi || !isOverviewEnabled()
667 || getContext().getDisplayId() != Display.DEFAULT_DISPLAY;
668 }
669
670 private Display getContextDisplay() {
671 return getContext().getDisplay();
672 }
673
Jorim Jaggi37c11802015-08-18 20:27:54 -0700674 public void setLayoutTransitionsEnabled(boolean enabled) {
675 mLayoutTransitionsEnabled = enabled;
676 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700677 }
678
Jorim Jaggi37c11802015-08-18 20:27:54 -0700679 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
680 setUseFadingAnimations(wakeAndUnlocking);
681 mWakeAndUnlocking = wakeAndUnlocking;
682 updateLayoutTransitionsEnabled();
683 }
684
685 private void updateLayoutTransitionsEnabled() {
686 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800687 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700688 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400689 if (lt != null) {
690 if (enabled) {
691 lt.enableTransitionType(LayoutTransition.APPEARING);
692 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
693 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
694 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
695 } else {
696 lt.disableTransitionType(LayoutTransition.APPEARING);
697 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
698 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
699 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
700 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700701 }
702 }
703
704 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500705 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
706 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700707 if (lp != null) {
708 boolean old = lp.windowAnimations != 0;
709 if (!old && useFadingAnimations) {
710 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
711 } else if (old && !useFadingAnimations) {
712 lp.windowAnimations = 0;
713 } else {
714 return;
715 }
716 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500717 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700718 }
719 }
720
Winson Chung5b6a1fe2019-07-26 16:38:08 -0700721 public void onStatusBarPanelStateChanged() {
Matthew Ng78f88d12018-01-23 12:39:55 -0800722 updateSlippery();
Winson Chung56a667b2019-07-30 13:51:27 -0700723 updatePanelSystemUiStateFlags();
Winson Chunga7067002019-05-07 11:50:42 -0700724 }
725
Winson Chung56a667b2019-07-30 13:51:27 -0700726 public void updateDisabledSystemUiStateFlags() {
Winson Chunga7067002019-05-07 11:50:42 -0700727 int displayId = mContext.getDisplayId();
728 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SCREEN_PINNING,
729 ActivityManagerWrapper.getInstance().isScreenPinningActive(), displayId);
730 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_OVERVIEW_DISABLED,
731 (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0, displayId);
732 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_HOME_DISABLED,
733 (mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0, displayId);
Winson Chungcb6454e2019-07-23 09:58:47 -0700734 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_SEARCH_DISABLED,
735 (mDisabledFlags & View.STATUS_BAR_DISABLE_SEARCH) != 0, displayId);
Winson Chung56a667b2019-07-30 13:51:27 -0700736 }
737
738 public void updatePanelSystemUiStateFlags() {
739 int displayId = mContext.getDisplayId();
Winson Chunga7067002019-05-07 11:50:42 -0700740 if (mPanelView != null) {
741 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED,
742 mPanelView.isFullyExpanded() && !mPanelView.isInSettings(), displayId);
Winson Chung5b6a1fe2019-07-26 16:38:08 -0700743 mOverviewProxyService.setSystemUiStateFlag(SYSUI_STATE_QUICK_SETTINGS_EXPANDED,
744 mPanelView.isInSettings(), displayId);
Winson Chunga7067002019-05-07 11:50:42 -0700745 }
Matthew Ng78f88d12018-01-23 12:39:55 -0800746 }
747
Matthew Ng8f25fb962018-01-16 17:17:24 -0800748 public void updateStates() {
Matthew Ng44b14502018-05-04 11:10:14 -0700749 final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
Mike Digmanf77fb912018-05-21 11:21:30 -0700750
751 if (mNavigationInflaterView != null) {
752 // Reinflate the navbar if needed, no-op unless the swipe up state changes
753 mNavigationInflaterView.onLikelyDefaultLayoutChange();
754 }
755
Matthew Ng8f25fb962018-01-16 17:17:24 -0800756 updateSlippery();
Winson Chung770d7e92018-03-20 17:51:39 -0700757 reloadNavIcons();
Matthew Ngd0a73e72018-03-02 15:16:03 -0800758 updateNavButtonIcons();
Winson Chungf9e30272018-03-26 17:25:36 -0700759 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ng44b14502018-05-04 11:10:14 -0700760 WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!showSwipeUpUI);
761 getHomeButton().setAccessibilityDelegate(
762 showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
Matthew Ng8f25fb962018-01-16 17:17:24 -0800763 }
764
Matthew Ng90ef0632018-08-15 13:53:15 -0700765 /**
766 * Updates the {@link WindowManager.LayoutParams.FLAG_SLIPPERY} state dependent on if swipe up
767 * is enabled, or the notifications is fully opened without being in an animated state. If
768 * slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen
769 * app/home window, if not nav bar will receive a cancelled touch event once gesture leaves bar.
770 */
Matthew Ng472d3e42018-06-14 15:16:55 -0700771 public void updateSlippery() {
Matthew Ng90ef0632018-08-15 13:53:15 -0700772 setSlippery(!isQuickStepSwipeUpEnabled() ||
773 (mPanelView.isFullyExpanded() && !mPanelView.isCollapsing()));
Matthew Ng78f88d12018-01-23 12:39:55 -0800774 }
775
Matthew Ng7d05e772017-11-09 14:41:07 -0800776 private void setSlippery(boolean slippery) {
Matthew Ngb831fb42019-01-30 11:20:48 -0800777 setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery);
778 }
779
Matthew Ngb831fb42019-01-30 11:20:48 -0800780 private void setWindowFlag(int flags, boolean enable) {
Matthew Ng7d05e772017-11-09 14:41:07 -0800781 final ViewGroup navbarView = ((ViewGroup) getParent());
Matthew Ngb55c02c2019-02-15 16:20:31 -0800782 if (navbarView == null) {
783 return;
784 }
Matthew Ngb831fb42019-01-30 11:20:48 -0800785 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView.getLayoutParams();
786 if (lp == null || enable == ((lp.flags & flags) != 0)) {
Matthew Ng9c3bce52018-02-01 22:00:31 +0000787 return;
788 }
Matthew Ngb831fb42019-01-30 11:20:48 -0800789 if (enable) {
790 lp.flags |= flags;
791 } else {
792 lp.flags &= ~flags;
Matthew Ng7d05e772017-11-09 14:41:07 -0800793 }
Matthew Ngb831fb42019-01-30 11:20:48 -0800794 WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
795 wm.updateViewLayout(navbarView, lp);
Matthew Ng7d05e772017-11-09 14:41:07 -0800796 }
797
Winson Chung1aa24b92019-04-24 15:17:33 -0700798 @Override
799 public void onNavigationModeChanged(int mode) {
Winson Chung316f6732019-06-14 09:31:46 -0700800 Context curUserCtx = Dependency.get(NavigationModeController.class).getCurrentUserContext();
Winson Chung1aa24b92019-04-24 15:17:33 -0700801 mNavBarMode = mode;
802 mBarTransitions.onNavigationModeChanged(mNavBarMode);
Winson Chung316f6732019-06-14 09:31:46 -0700803 mEdgeBackGestureHandler.onNavigationModeChanged(mNavBarMode, curUserCtx);
Winson Chung1aa24b92019-04-24 15:17:33 -0700804 mRecentsOnboarding.onNavigationModeChanged(mNavBarMode);
Tracy Zhouefc34662019-04-22 13:37:12 -0700805 getRotateSuggestionButton().onNavigationModeChanged(mNavBarMode);
Matthew Ngb55c02c2019-02-15 16:20:31 -0800806
807 // Color adaption is tied with showing home handle, only avaliable if visible
Winson Chung1aa24b92019-04-24 15:17:33 -0700808 mTintController.onNavigationModeChanged(mNavBarMode);
Tracy Zhou24fd0282019-05-20 14:40:38 -0700809 if (isGesturalMode(mNavBarMode)) {
Winson Chung775d2872019-03-27 14:14:01 -0700810 mTintController.start();
Matthew Ngb55c02c2019-02-15 16:20:31 -0800811 } else {
Winson Chung775d2872019-03-27 14:14:01 -0700812 mTintController.stop();
Matthew Ngb55c02c2019-02-15 16:20:31 -0800813 }
814 }
815
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800816 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800817 mLongClickableAccessibilityButton = longClickable;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800818 getAccessibilityButton().setLongClickable(longClickable);
Tracy Zhouefc34662019-04-22 13:37:12 -0700819 mContextualButtonGroup.setButtonVisibility(R.id.accessibility_button, visible);
Mike Digmana48cf192018-02-12 17:52:48 -0800820 }
821
Tracy Zhou1ac592c2018-07-25 13:47:37 -0700822 void hideRecentsOnboarding() {
823 mRecentsOnboarding.hide(true);
824 }
825
Jim Miller960892c2012-05-23 15:50:04 -0700826 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400827 public void onFinishInflate() {
Winson Chung661d5f92018-05-21 18:41:39 -0700828 mNavigationInflaterView = findViewById(R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700829 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500830
831 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200832
Jason Monk32e3bb52017-07-27 12:35:41 -0400833 DockedStackExistsListener.register(mDockedListener);
Charles Chenaa94d95b2019-02-19 14:18:19 +0800834 updateOrientationViews();
Matthew Ng25593cc2018-09-12 16:05:41 -0700835 reloadNavIcons();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100836 }
837
Matthew Nga8f24262017-12-19 11:54:24 -0800838 @Override
839 protected void onDraw(Canvas canvas) {
Matthew Ng603b3292018-03-30 17:15:39 -0700840 mDeadZone.onDraw(canvas);
Matthew Nga8f24262017-12-19 11:54:24 -0800841 super.onDraw(canvas);
842 }
843
844 @Override
845 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
846 super.onLayout(changed, left, top, right, bottom);
Sunny Goyalaac6c882019-02-11 11:57:58 -0800847
848 mActiveRegion.setEmpty();
849 updateButtonLocation(getBackButton(), mBackButtonBounds, true);
850 updateButtonLocation(getHomeButton(), mHomeButtonBounds, false);
851 updateButtonLocation(getRecentsButton(), mRecentsButtonBounds, false);
852 updateButtonLocation(getRotateSuggestionButton(), mRotationButtonBounds, true);
853 // TODO: Handle button visibility changes
854 mOverviewProxyService.onActiveNavBarRegionChanges(mActiveRegion);
Tracy Zhou559d97c2018-04-07 23:54:46 -0700855 mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
Matthew Nga8f24262017-12-19 11:54:24 -0800856 }
857
Sunny Goyalaac6c882019-02-11 11:57:58 -0800858 private void updateButtonLocation(ButtonDispatcher button, Rect buttonBounds,
859 boolean isActive) {
Winson Chungc4e06202018-02-13 10:37:35 -0800860 View view = button.getCurrentView();
861 if (view == null) {
862 buttonBounds.setEmpty();
863 return;
864 }
Matthew Ng3b7e3902018-03-22 16:06:09 -0700865 // Temporarily reset the translation back to origin to get the position in window
866 final float posX = view.getTranslationX();
867 final float posY = view.getTranslationY();
868 view.setTranslationX(0);
869 view.setTranslationY(0);
Sunny Goyalaac6c882019-02-11 11:57:58 -0800870
871 if (isActive) {
872 view.getLocationOnScreen(mTmpPosition);
873 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
874 mTmpPosition[0] + view.getMeasuredWidth(),
875 mTmpPosition[1] + view.getMeasuredHeight());
876 mActiveRegion.op(buttonBounds, Op.UNION);
877 }
Winson Chungc4e06202018-02-13 10:37:35 -0800878 view.getLocationInWindow(mTmpPosition);
879 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
880 mTmpPosition[0] + view.getMeasuredWidth(),
881 mTmpPosition[1] + view.getMeasuredHeight());
Matthew Ng3b7e3902018-03-22 16:06:09 -0700882 view.setTranslationX(posX);
883 view.setTranslationY(posY);
Winson Chungc4e06202018-02-13 10:37:35 -0800884 }
885
Charles Chenaa94d95b2019-02-19 14:18:19 +0800886 private void updateOrientationViews() {
887 mHorizontal = findViewById(R.id.horizontal);
888 mVertical = findViewById(R.id.vertical);
Jason Monk9a6552d2016-05-20 11:21:59 -0400889
Jason Monk199a2d02017-07-28 11:08:27 -0400890 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400891 }
892
Charles Chenaa94d95b2019-02-19 14:18:19 +0800893 boolean needsReorient(int rotation) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700894 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700895 }
896
Jason Monk199a2d02017-07-28 11:08:27 -0400897 private void updateCurrentView() {
Charles Chenaa94d95b2019-02-19 14:18:19 +0800898 resetViews();
899 mCurrentView = mIsVertical ? mVertical : mHorizontal;
Daniel Sandler5c8da942011-06-28 00:29:04 -0400900 mCurrentView.setVisibility(View.VISIBLE);
Charles Chenaa94d95b2019-02-19 14:18:19 +0800901 mNavigationInflaterView.setVertical(mIsVertical);
902 mCurrentRotation = getContextDisplay().getRotation();
903 mNavigationInflaterView.setAlternativeOrder(mCurrentRotation == Surface.ROTATION_90);
Matthew Ng1efc9c32018-04-11 18:13:56 -0700904 mNavigationInflaterView.updateButtonDispatchersCurrentView();
Jorim Jaggi37c11802015-08-18 20:27:54 -0700905 updateLayoutTransitionsEnabled();
Charles Chenaa94d95b2019-02-19 14:18:19 +0800906 }
907
908 private void resetViews() {
909 mHorizontal.setVisibility(View.GONE);
910 mVertical.setVisibility(View.GONE);
Jason Monk9a6552d2016-05-20 11:21:59 -0400911 }
912
913 private void updateRecentsIcon() {
Charles Chenaa94d95b2019-02-19 14:18:19 +0800914 mDockedIcon.setRotation(mDockedStackExists && mIsVertical ? 90 : 0);
Jason Monk9a6552d2016-05-20 11:21:59 -0400915 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700916 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400917 }
918
Matthew Ng20136e62018-05-30 12:20:31 -0700919 public void showPinningEnterExitToast(boolean entering) {
920 if (entering) {
921 mScreenPinningNotify.showPinningStartToast();
922 } else {
923 mScreenPinningNotify.showPinningExitToast();
924 }
925 }
926
927 public void showPinningEscapeToast() {
Hongwei Wang98d08582019-08-14 14:55:27 -0700928 mScreenPinningNotify.showEscapeToast(
929 mNavBarMode == NAV_BAR_MODE_GESTURAL, isRecentsButtonVisible());
Matthew Ng20136e62018-05-30 12:20:31 -0700930 }
931
Jason Monk9a6552d2016-05-20 11:21:59 -0400932 public boolean isVertical() {
Charles Chenaa94d95b2019-02-19 14:18:19 +0800933 return mIsVertical;
Jason Monk9a6552d2016-05-20 11:21:59 -0400934 }
935
936 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400937 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400938
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700939 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Matthew Ng603b3292018-03-30 17:15:39 -0700940 mDeadZone.onConfigurationChanged(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400941
Daniel Sandler6da2b762011-09-14 16:04:59 -0400942 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700943 mBarTransitions.init();
Daniel Sandler6da2b762011-09-14 16:04:59 -0400944
Daniel Sandler60ee2562011-07-22 12:34:33 -0400945 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700946 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400947 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800948
Matthew Ng5fd80412018-02-14 14:40:31 -0800949 // Resolve layout direction if not resolved since components changing layout direction such
950 // as changing languages will recreate this view and the direction will be resolved later
951 if (!isLayoutDirectionResolved()) {
952 resolveLayoutDirection();
953 }
Matthew Ngd0a73e72018-03-02 15:16:03 -0800954 updateNavButtonIcons();
Xiaohui Chen9efa5de2016-11-22 10:34:38 -0800955
Charles Chenaa94d95b2019-02-19 14:18:19 +0800956 getHomeButton().setVertical(mIsVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400957 }
Daniel Sandler48852952011-12-01 14:34:23 -0500958
Daniel Sandler0b69b592012-01-23 21:08:36 -0500959 @Override
Matthew Ngff638122019-03-21 17:17:18 -0700960 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
961 int w = MeasureSpec.getSize(widthMeasureSpec);
962 int h = MeasureSpec.getSize(heightMeasureSpec);
John Spurlockcd686b52013-06-05 10:13:46 -0400963 if (DEBUG) Log.d(TAG, String.format(
Matthew Ngff638122019-03-21 17:17:18 -0700964 "onMeasure: (%dx%d) old: (%dx%d)", w, h, getMeasuredWidth(), getMeasuredHeight()));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400965
Winson Chung4723b4e2019-03-25 16:49:36 -0700966 final boolean newVertical = w > 0 && h > w
Tracy Zhou24fd0282019-05-20 14:40:38 -0700967 && !isGesturalMode(mNavBarMode);
Charles Chenaa94d95b2019-02-19 14:18:19 +0800968 if (newVertical != mIsVertical) {
969 mIsVertical = newVertical;
970 if (DEBUG) {
Matthew Ngff638122019-03-21 17:17:18 -0700971 Log.d(TAG, String.format("onMeasure: h=%d, w=%d, vert=%s", h, w,
Charles Chenaa94d95b2019-02-19 14:18:19 +0800972 mIsVertical ? "y" : "n"));
973 }
Daniel Sandlere03bc952012-04-27 16:11:22 -0400974 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +0200975 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -0400976 }
Winson Chung775d2872019-03-27 14:14:01 -0700977
Tracy Zhou24fd0282019-05-20 14:40:38 -0700978 if (isGesturalMode(mNavBarMode)) {
Winson Chung775d2872019-03-27 14:14:01 -0700979 // Update the nav bar background to match the height of the visible nav bar
980 int height = mIsVertical
981 ? getResources().getDimensionPixelSize(
982 com.android.internal.R.dimen.navigation_bar_height_landscape)
983 : getResources().getDimensionPixelSize(
984 com.android.internal.R.dimen.navigation_bar_height);
985 int frameHeight = getResources().getDimensionPixelSize(
986 com.android.internal.R.dimen.navigation_bar_frame_height);
987 mBarTransitions.setBackgroundFrame(new Rect(0, frameHeight - height, w, h));
988 }
989
Matthew Ngff638122019-03-21 17:17:18 -0700990 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Daniel Sandler0b69b592012-01-23 21:08:36 -0500991 }
992
Selim Cinek92d892c2014-09-11 15:11:00 +0200993 private void notifyVerticalChangedListener(boolean newVertical) {
994 if (mOnVerticalChangedListener != null) {
995 mOnVerticalChangedListener.onVerticalChanged(newVertical);
996 }
997 }
998
Selim Cinek17a327a2014-08-25 15:03:48 +0200999 @Override
1000 protected void onConfigurationChanged(Configuration newConfig) {
1001 super.onConfigurationChanged(newConfig);
Matthew Ng8c056c12018-10-15 15:16:46 -07001002 mTmpLastConfiguration.updateFrom(mConfiguration);
1003 mConfiguration.updateFrom(newConfig);
1004 boolean uiCarModeChanged = updateCarMode();
Matthew Ng8c056c12018-10-15 15:16:46 -07001005 updateIcons(mTmpLastConfiguration);
Winsonfde2e6a2016-03-22 16:03:10 -07001006 updateRecentsIcon();
Matthew Ng8c056c12018-10-15 15:16:46 -07001007 mRecentsOnboarding.onConfigurationChanged(mConfiguration);
1008 if (uiCarModeChanged || mTmpLastConfiguration.densityDpi != mConfiguration.densityDpi
1009 || mTmpLastConfiguration.getLayoutDirection() != mConfiguration.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001010 // If car mode or density changes, we need to reset the icons.
Matthew Ngd0a73e72018-03-02 15:16:03 -08001011 updateNavButtonIcons();
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001012 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001013 }
1014
1015 /**
1016 * If the configuration changed, update the carmode and return that it was updated.
1017 */
Matthew Ng8c056c12018-10-15 15:16:46 -07001018 private boolean updateCarMode() {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001019 boolean uiCarModeChanged = false;
Matthew Ng8c056c12018-10-15 15:16:46 -07001020 if (mConfiguration != null) {
1021 int uiMode = mConfiguration.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -07001022 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
1023
1024 if (isCarMode != mInCarMode) {
1025 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -07001026 if (ALTERNATE_CAR_MODE_UI) {
1027 mUseCarModeUi = isCarMode;
1028 uiCarModeChanged = true;
1029 } else {
1030 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
1031 mUseCarModeUi = false;
1032 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001033 }
1034 }
1035 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +02001036 }
1037
Daniel Sandler48852952011-12-01 14:34:23 -05001038 private String getResourceName(int resId) {
1039 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -05001040 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -05001041 try {
1042 return res.getResourceName(resId);
1043 } catch (android.content.res.Resources.NotFoundException ex) {
1044 return "(unknown)";
1045 }
1046 } else {
1047 return "(null)";
1048 }
1049 }
1050
1051 private static String visibilityToString(int vis) {
1052 switch (vis) {
1053 case View.INVISIBLE:
1054 return "INVISIBLE";
1055 case View.GONE:
1056 return "GONE";
1057 default:
1058 return "VISIBLE";
1059 }
1060 }
1061
Jason Monk67e6c802016-08-30 14:09:21 -04001062 @Override
1063 protected void onAttachedToWindow() {
1064 super.onAttachedToWindow();
Adrian Roos7e58a082018-03-09 16:40:56 +01001065 requestApplyInsets();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -07001066 reorient();
Tracy Zhouefc34662019-04-22 13:37:12 -07001067 onNavigationModeChanged(mNavBarMode);
Winson Chungf9e30272018-03-26 17:25:36 -07001068 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Tracy Zhoucb0362a2019-06-18 10:59:11 -07001069 if (mRotationButtonController != null) {
1070 mRotationButtonController.registerListeners();
1071 }
Matthew Ngb831fb42019-01-30 11:20:48 -08001072
Sunny Goyala6a58122019-04-02 10:20:29 -07001073 mEdgeBackGestureHandler.onNavBarAttached();
Tracy Zhouefc34662019-04-22 13:37:12 -07001074 getViewTreeObserver().addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
Jason Monk67e6c802016-08-30 14:09:21 -04001075 }
1076
1077 @Override
1078 protected void onDetachedFromWindow() {
1079 super.onDetachedFromWindow();
Winson Chung1aa24b92019-04-24 15:17:33 -07001080 Dependency.get(NavigationModeController.class).removeListener(this);
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001081 setUpSwipeUpOnboarding(false);
Matthew Ng761562d2018-09-17 11:13:21 -07001082 for (int i = 0; i < mButtonDispatchers.size(); ++i) {
1083 mButtonDispatchers.valueAt(i).onDestroy();
1084 }
Tracy Zhoucb0362a2019-06-18 10:59:11 -07001085 if (mRotationButtonController != null) {
1086 mRotationButtonController.unregisterListeners();
1087 }
1088
Sunny Goyala6a58122019-04-02 10:20:29 -07001089 mEdgeBackGestureHandler.onNavBarDetached();
Tracy Zhouefc34662019-04-22 13:37:12 -07001090 getViewTreeObserver().removeOnComputeInternalInsetsListener(
1091 mOnComputeInternalInsetsListener);
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001092 }
1093
1094 private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
1095 if (connectedToOverviewProxy) {
Tony Wickham05c1f852018-02-06 12:32:54 -08001096 mRecentsOnboarding.onConnectedToLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001097 } else {
Tony Wickham05c1f852018-02-06 12:32:54 -08001098 mRecentsOnboarding.onDisconnectedFromLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001099 }
Jason Monk67e6c802016-08-30 14:09:21 -04001100 }
1101
Daniel Sandler48852952011-12-01 14:34:23 -05001102 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1103 pw.println("NavigationBarView {");
1104 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -07001105 final Point size = new Point();
Jeff Chang2aaa91a2018-11-08 18:04:16 +08001106 getContextDisplay().getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -05001107
Jason Monk2a6ea9c2017-01-26 11:14:51 -05001108 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -05001109 + " " + visibilityToString(getVisibility())));
1110
1111 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -07001112 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -04001113 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -05001114 + r.toShortString()
1115 + " " + visibilityToString(getWindowVisibility())
1116 + (offscreen ? " OFFSCREEN!" : ""));
1117
Winson Chung661d5f92018-05-21 18:41:39 -07001118 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -08001119 getResourceName(getCurrentView().getId()),
1120 getCurrentView().getWidth(), getCurrentView().getHeight(),
Winson Chung661d5f92018-05-21 18:41:39 -07001121 visibilityToString(getCurrentView().getVisibility()),
1122 getCurrentView().getAlpha()));
Daniel Sandler48852952011-12-01 14:34:23 -05001123
Sunny Goyalded62f02019-05-01 14:35:49 -07001124 pw.println(String.format(" disabled=0x%08x vertical=%s darkIntensity=%.2f",
Daniel Sandler48852952011-12-01 14:34:23 -05001125 mDisabledFlags,
Charles Chenaa94d95b2019-02-19 14:18:19 +08001126 mIsVertical ? "true" : "false",
Matthew Ngeb0b0942018-10-12 16:42:11 -07001127 getLightTransitionsController().getCurrentDarkIntensity()));
Daniel Sandler48852952011-12-01 14:34:23 -05001128
John Spurlock56d007b2013-10-28 18:40:56 -04001129 dumpButton(pw, "back", getBackButton());
1130 dumpButton(pw, "home", getHomeButton());
1131 dumpButton(pw, "rcnt", getRecentsButton());
Matthew Ng25593cc2018-09-12 16:05:41 -07001132 dumpButton(pw, "rota", getRotateSuggestionButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001133 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -05001134
Daniel Sandler48852952011-12-01 14:34:23 -05001135 pw.println(" }");
Matthew Ng25593cc2018-09-12 16:05:41 -07001136
1137 mContextualButtonGroup.dump(pw);
1138 mRecentsOnboarding.dump(pw);
Winson Chung775d2872019-03-27 14:14:01 -07001139 mTintController.dump(pw);
Winson Chung316f6732019-06-14 09:31:46 -07001140 mEdgeBackGestureHandler.dump(pw);
Daniel Sandler48852952011-12-01 14:34:23 -05001141 }
Jim Millere898ac52012-04-06 17:10:57 -07001142
Adrian Roos7e58a082018-03-09 16:40:56 +01001143 @Override
1144 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Selim Cineke50b1212019-06-04 18:40:31 -07001145 int leftInset = insets.getSystemWindowInsetLeft();
1146 int rightInset = insets.getSystemWindowInsetRight();
1147 setPadding(leftInset, insets.getSystemWindowInsetTop(), rightInset,
1148 insets.getSystemWindowInsetBottom());
1149 // we're passing the insets onto the gesture handler since the back arrow is only
1150 // conditionally added and doesn't always get all the insets.
1151 mEdgeBackGestureHandler.setInsets(leftInset, rightInset);
Adrian Roos7e58a082018-03-09 16:40:56 +01001152 return super.onApplyWindowInsets(insets);
1153 }
1154
Jason Monka2081822016-01-18 14:41:03 -05001155 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -04001156 pw.print(" " + caption + ": ");
1157 if (button == null) {
1158 pw.print("null");
1159 } else {
Jason Monka2081822016-01-18 14:41:03 -05001160 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -04001161 + " alpha=" + button.getAlpha()
1162 );
John Spurlock56d007b2013-10-28 18:40:56 -04001163 }
1164 pw.println();
1165 }
1166
Jorim Jaggif4797922014-08-04 22:49:41 +02001167 public interface OnVerticalChangedListener {
1168 void onVerticalChanged(boolean isVertical);
1169 }
Jason Monka2081822016-01-18 14:41:03 -05001170
Matthew Ngff638122019-03-21 17:17:18 -07001171 private final Consumer<Boolean> mDockedListener = exists -> post(() -> {
Jason Monk32e3bb52017-07-27 12:35:41 -04001172 mDockedStackExists = exists;
1173 updateRecentsIcon();
1174 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001175}