blob: a5621e5a401028a66a71e0458a1a96672c0b30f2 [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
Mike Digmana48cf192018-02-12 17:52:48 -080024import android.animation.Animator;
25import android.animation.AnimatorListenerAdapter;
John Spurlock1bbd49d2012-10-19 11:09:32 -040026import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040027import android.animation.LayoutTransition.TransitionListener;
28import android.animation.ObjectAnimator;
29import android.animation.TimeInterpolator;
30import android.animation.ValueAnimator;
Jorim Jaggi40db0292016-06-27 17:58:03 -070031import android.annotation.DrawableRes;
Mike Digman1e28a5a2018-02-14 10:49:19 -080032import android.annotation.StyleRes;
Jason Monk00659ba2017-03-03 10:28:45 -050033import android.app.ActivityManager;
Daniel Sandler328310c2011-09-23 15:56:52 -040034import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040035import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020036import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080037import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070038import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050039import android.graphics.Rect;
Mike Digmana48cf192018-02-12 17:52:48 -080040import android.graphics.drawable.AnimatedVectorDrawable;
Mike Digman1e28a5a2018-02-14 10:49:19 -080041import android.graphics.drawable.Drawable;
Daniel Sandler0b69b592012-01-23 21:08:36 -050042import android.os.Handler;
43import android.os.Message;
Jason Monk17488b92014-11-06 11:26:14 -050044import android.os.RemoteException;
Matthew Ng8f25fb962018-01-16 17:17:24 -080045import android.os.SystemProperties;
Mike Digman7d092772018-01-11 12:10:32 -080046import android.support.annotation.ColorInt;
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;
Jorim Jaggi40db0292016-06-27 17:58:03 -070050import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040051import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040052import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040053import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040054import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040055import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040056import android.view.WindowManager;
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;
Mike Digmana48cf192018-02-12 17:52:48 -080063import com.android.systemui.Interpolators;
Matthew Ng7d05e772017-11-09 14:41:07 -080064import com.android.systemui.OverviewProxyService;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040065import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080066import com.android.systemui.RecentsComponent;
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;
Tony Wickham05c1f852018-02-06 12:32:54 -080071import com.android.systemui.recents.RecentsOnboarding;
Matthew Ng87cbf342018-02-15 12:21:18 -080072import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungc4e06202018-02-13 10:37:35 -080073import com.android.systemui.shared.system.NavigationBarCompat;
Jorim Jaggidd98d412015-11-18 15:57:38 -080074import com.android.systemui.stackdivider.Divider;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040075import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070076import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Tony Wickhamfb63fe82018-01-16 12:14:06 -080077import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070078
John Spurlockde84f0e2013-06-12 12:41:00 -040079import java.io.FileDescriptor;
80import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040081import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040082
Matthew Ng8f25fb962018-01-16 17:17:24 -080083import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
84import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
85import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
86import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
87
Jason Monk67e6c802016-08-30 14:09:21 -040088public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040089 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070090 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040091
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040092 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040093 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040094
Justin Paupore01915a12016-09-28 17:41:26 -070095 final static boolean ALTERNATE_CAR_MODE_UI = false;
96
Daniel Sandler8956dbb2011-04-22 07:55:02 -040097 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -040098 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040099 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -0400100
Daniel Sandler60ee2562011-07-22 12:34:33 -0400101 boolean mVertical;
Adrian Roos090b7d82016-08-02 18:36:12 -0700102 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400103
John Spurlock7edfbca2013-09-14 11:58:55 -0400104 boolean mShowMenu;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800105 boolean mShowAccessibilityButton;
106 boolean mLongClickableAccessibilityButton;
Mike Digmana48cf192018-02-12 17:52:48 -0800107 boolean mShowRotateButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -0400108 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -0400109 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400110
Winson Chungc4e06202018-02-13 10:37:35 -0800111 private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE;
112 private Rect mHomeButtonBounds = new Rect();
113 private Rect mBackButtonBounds = new Rect();
114 private int[] mTmpPosition = new int[2];
115
Jorim Jaggi40db0292016-06-27 17:58:03 -0700116 private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
117 private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
118 private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
119 private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
120 private KeyButtonDrawable mRecentIcon;
121 private KeyButtonDrawable mDockedIcon;
122 private KeyButtonDrawable mImeIcon;
123 private KeyButtonDrawable mMenuIcon;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800124 private KeyButtonDrawable mAccessibilityIcon;
Mike Digman7d092772018-01-11 12:10:32 -0800125 private KeyButtonDrawable mRotateSuggestionIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800126
Jason Monk67e6c802016-08-30 14:09:21 -0400127 private GestureHelper mGestureHelper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400128 private DeadZone mDeadZone;
John Spurlock89835dd2013-08-16 15:06:51 -0400129 private final NavigationBarTransitions mBarTransitions;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800130 private final OverviewProxyService mOverviewProxyService;
Jim Millere898ac52012-04-06 17:10:57 -0700131
Daniel Sandler0b69b592012-01-23 21:08:36 -0500132 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
133 final static boolean WORKAROUND_INVALID_LAYOUT = true;
134 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
135
John Spurlock56d007b2013-10-28 18:40:56 -0400136 // performs manual animation in sync with layout transitions
137 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
138
Jorim Jaggif4797922014-08-04 22:49:41 +0200139 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700140 private boolean mLayoutTransitionsEnabled = true;
141 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700142 private boolean mUseCarModeUi = false;
143 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800144 private boolean mDockedStackExists;
Jorim Jaggif4797922014-08-04 22:49:41 +0200145
Felipe Leme15f915c2016-10-31 12:47:15 -0700146 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Winsonfde2e6a2016-03-22 16:03:10 -0700147 private Configuration mConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500148
Adrian Roosdb12b152016-07-12 15:38:55 -0700149 private NavigationBarInflaterView mNavigationInflaterView;
Jason Monk67e6c802016-08-30 14:09:21 -0400150 private RecentsComponent mRecentsComponent;
151 private Divider mDivider;
Tony Wickham05c1f852018-02-06 12:32:54 -0800152 private RecentsOnboarding mRecentsOnboarding;
Matthew Ng78f88d12018-01-23 12:39:55 -0800153 private NotificationPanelView mPanelView;
Adrian Roosdb12b152016-07-12 15:38:55 -0700154
Mike Digman1e28a5a2018-02-14 10:49:19 -0800155 private int mRotateBtnStyle = R.style.RotateButtonCCWStart90;
Mike Digmana48cf192018-02-12 17:52:48 -0800156
John Spurlock56d007b2013-10-28 18:40:56 -0400157 private class NavTransitionListener implements TransitionListener {
158 private boolean mBackTransitioning;
159 private boolean mHomeAppearing;
160 private long mStartDelay;
161 private long mDuration;
162 private TimeInterpolator mInterpolator;
163
164 @Override
165 public void startTransition(LayoutTransition transition, ViewGroup container,
166 View view, int transitionType) {
167 if (view.getId() == R.id.back) {
168 mBackTransitioning = true;
169 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
170 mHomeAppearing = true;
171 mStartDelay = transition.getStartDelay(transitionType);
172 mDuration = transition.getDuration(transitionType);
173 mInterpolator = transition.getInterpolator(transitionType);
174 }
175 }
176
177 @Override
178 public void endTransition(LayoutTransition transition, ViewGroup container,
179 View view, int transitionType) {
180 if (view.getId() == R.id.back) {
181 mBackTransitioning = false;
182 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
183 mHomeAppearing = false;
184 }
185 }
186
187 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500188 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800189
John Spurlock56d007b2013-10-28 18:40:56 -0400190 // When dismissing ime during unlock, force the back button to run the same appearance
191 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500192 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
193 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400194 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800195 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400196 a.setStartDelay(mStartDelay);
197 a.setDuration(mDuration);
198 a.setInterpolator(mInterpolator);
199 a.start();
200 }
201 }
202 }
203
Jason Monkf1ff2092014-04-29 16:50:53 -0400204 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
205 @Override
206 public void onClick(View view) {
Yohei Yukawa777ef952015-11-25 20:32:24 -0800207 mContext.getSystemService(InputMethodManager.class)
Seigo Nonaka14e13912015-05-06 21:04:13 -0700208 .showInputMethodPicker(true /* showAuxiliarySubtypes */);
Jason Monkf1ff2092014-04-29 16:50:53 -0400209 }
210 };
211
Daniel Sandler0b69b592012-01-23 21:08:36 -0500212 private class H extends Handler {
213 public void handleMessage(Message m) {
214 switch (m.what) {
215 case MSG_CHECK_INVALID_LAYOUT:
216 final String how = "" + m.obj;
217 final int w = getWidth();
218 final int h = getHeight();
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800219 final int vw = getCurrentView().getWidth();
220 final int vh = getCurrentView().getHeight();
Daniel Sandler0b69b592012-01-23 21:08:36 -0500221
222 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400223 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500224 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
225 how, w, h, vw, vh));
226 if (WORKAROUND_INVALID_LAYOUT) {
227 requestLayout();
228 }
229 }
230 break;
231 }
232 }
233 }
234
John Spurlocke932e302013-08-12 10:16:29 -0400235 public NavigationBarView(Context context, AttributeSet attrs) {
236 super(context, attrs);
237
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800238 mDisplay = ((WindowManager) context.getSystemService(
John Spurlocke932e302013-08-12 10:16:29 -0400239 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400240
John Spurlocke932e302013-08-12 10:16:29 -0400241 mVertical = false;
242 mShowMenu = false;
John Spurlocke932e302013-08-12 10:16:29 -0400243
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800244 mShowAccessibilityButton = false;
245 mLongClickableAccessibilityButton = false;
246
Matthew Ngf2946542018-02-12 14:13:18 -0800247 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
248 mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
249
Winsonfde2e6a2016-03-22 16:03:10 -0700250 mConfiguration = new Configuration();
251 mConfiguration.updateFrom(context.getResources().getConfiguration());
252 updateIcons(context, Configuration.EMPTY, mConfiguration);
John Spurlocke932e302013-08-12 10:16:29 -0400253
John Spurlock7edfbca2013-09-14 11:58:55 -0400254 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500255
Felipe Leme15f915c2016-10-31 12:47:15 -0700256 mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
257 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
258 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
259 mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
260 mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800261 mButtonDispatchers.put(R.id.accessibility_button,
262 new ButtonDispatcher(R.id.accessibility_button));
Mike Digman7d092772018-01-11 12:10:32 -0800263 mButtonDispatchers.put(R.id.rotate_suggestion,
264 new ButtonDispatcher(R.id.rotate_suggestion));
John Spurlocke932e302013-08-12 10:16:29 -0400265 }
266
267 public BarTransitions getBarTransitions() {
268 return mBarTransitions;
269 }
270
Jorim Jaggi40db0292016-06-27 17:58:03 -0700271 public LightBarTransitionsController getLightTransitionsController() {
272 return mBarTransitions.getLightTransitionsController();
273 }
274
Matthew Ng78f88d12018-01-23 12:39:55 -0800275 public void setComponents(RecentsComponent recentsComponent, Divider divider,
276 NotificationPanelView panel) {
Jason Monk67e6c802016-08-30 14:09:21 -0400277 mRecentsComponent = recentsComponent;
278 mDivider = divider;
Matthew Ng78f88d12018-01-23 12:39:55 -0800279 mPanelView = panel;
Jason Monk67e6c802016-08-30 14:09:21 -0400280 if (mGestureHelper instanceof NavigationBarGestureHelper) {
281 ((NavigationBarGestureHelper) mGestureHelper).setComponents(
282 recentsComponent, divider, this);
283 }
Jim Millere898ac52012-04-06 17:10:57 -0700284 }
285
Jorim Jaggif4797922014-08-04 22:49:41 +0200286 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
287 mOnVerticalChangedListener = onVerticalChangedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200288 notifyVerticalChangedListener(mVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200289 }
290
Matthew Ng9c3bce52018-02-01 22:00:31 +0000291 public void setRecentsAnimationStarted(boolean started) {
Tony Wickham05c1f852018-02-06 12:32:54 -0800292 if (mRecentsOnboarding != null) {
293 mRecentsOnboarding.onRecentsAnimationStarted();
Matthew Ng9c3bce52018-02-01 22:00:31 +0000294 }
295 }
296
297 public void onConnectionChanged(boolean isConnected) {
298 updateSlippery();
299 setDisabledFlags(mDisabledFlags, true);
300 setUpSwipeUpOnboarding(isConnected);
301 }
302
Jim Millere898ac52012-04-06 17:10:57 -0700303 @Override
304 public boolean onInterceptTouchEvent(MotionEvent event) {
Winson Chungc4e06202018-02-13 10:37:35 -0800305 switch (event.getActionMasked()) {
306 case ACTION_DOWN:
307 int x = (int) event.getX();
308 int y = (int) event.getY();
309 mDownHitTarget = HIT_TARGET_NONE;
310 if (mBackButtonBounds.contains(x, y)) {
311 mDownHitTarget = HIT_TARGET_BACK;
312 } else if (mHomeButtonBounds.contains(x, y)) {
313 mDownHitTarget = HIT_TARGET_HOME;
314 }
315 break;
316 }
Winson Chung49658842018-02-08 12:52:21 -0800317 return mGestureHelper.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700318 }
319
Winson Chung4faf38a2018-02-06 08:53:37 -0800320 @Override
321 public boolean onTouchEvent(MotionEvent event) {
322 if (mGestureHelper.onTouchEvent(event)) {
323 return true;
324 }
Winson Chung49658842018-02-08 12:52:21 -0800325 return super.onTouchEvent(event);
Winson Chung4faf38a2018-02-06 08:53:37 -0800326 }
327
Winson Chungc4e06202018-02-13 10:37:35 -0800328 public @NavigationBarCompat.HitTarget int getDownHitTarget() {
329 return mDownHitTarget;
330 }
331
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700332 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500333 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700334 }
335
Daniel Sandler0b69b592012-01-23 21:08:36 -0500336 private H mHandler = new H();
337
John Spurlock7edfbca2013-09-14 11:58:55 -0400338 public View getCurrentView() {
339 return mCurrentView;
340 }
341
Xiaohui Chen10942302015-12-16 16:38:13 -0800342 public View[] getAllViews() {
343 return mRotatedViews;
344 }
345
Jason Monka2081822016-01-18 14:41:03 -0500346 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700347 return mButtonDispatchers.get(R.id.recent_apps);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400348 }
349
Jason Monka2081822016-01-18 14:41:03 -0500350 public ButtonDispatcher getMenuButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700351 return mButtonDispatchers.get(R.id.menu);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400352 }
353
Jason Monka2081822016-01-18 14:41:03 -0500354 public ButtonDispatcher getBackButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700355 return mButtonDispatchers.get(R.id.back);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400356 }
357
Jason Monka2081822016-01-18 14:41:03 -0500358 public ButtonDispatcher getHomeButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700359 return mButtonDispatchers.get(R.id.home);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400360 }
361
Jason Monka2081822016-01-18 14:41:03 -0500362 public ButtonDispatcher getImeSwitchButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700363 return mButtonDispatchers.get(R.id.ime_switcher);
Jason Monkf1ff2092014-04-29 16:50:53 -0400364 }
365
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800366 public ButtonDispatcher getAccessibilityButton() {
367 return mButtonDispatchers.get(R.id.accessibility_button);
368 }
369
Mike Digman7d092772018-01-11 12:10:32 -0800370 public ButtonDispatcher getRotateSuggestionButton() {
371 return mButtonDispatchers.get(R.id.rotate_suggestion);
372 }
373
Jorim Jaggi40db0292016-06-27 17:58:03 -0700374 public SparseArray<ButtonDispatcher> getButtonDispatchers() {
375 return mButtonDispatchers;
376 }
377
Matthew Ng9c3bce52018-02-01 22:00:31 +0000378 public boolean isRecentsButtonVisible() {
379 return getRecentsButton().getVisibility() == View.VISIBLE;
380 }
381
Matthew Ng8f25fb962018-01-16 17:17:24 -0800382 public boolean isQuickStepSwipeUpEnabled() {
383 return mOverviewProxyService.getProxy() != null
384 && ((mOverviewProxyService.getInteractionFlags()
385 & FLAG_DISABLE_SWIPE_UP) == 0);
386 }
387
388 public boolean isQuickScrubEnabled() {
389 return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
390 && mOverviewProxyService.getProxy() != null && !isRecentsButtonVisible()
391 && ((mOverviewProxyService.getInteractionFlags()
392 & FLAG_DISABLE_QUICK_SCRUB) == 0);
393 }
394
Winsonfde2e6a2016-03-22 16:03:10 -0700395 private void updateCarModeIcons(Context ctx) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700396 mBackCarModeIcon = getDrawable(ctx,
397 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800398 mBackLandCarModeIcon = mBackCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700399 mBackAltCarModeIcon = getDrawable(ctx,
400 R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800401 mBackAltLandCarModeIcon = mBackAltCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700402 mHomeCarModeIcon = getDrawable(ctx,
403 R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800404 }
405
Winsonfde2e6a2016-03-22 16:03:10 -0700406 private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700407 if (oldConfig.orientation != newConfig.orientation
408 || oldConfig.densityDpi != newConfig.densityDpi) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700409 mDockedIcon = getDrawable(ctx,
410 R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
Matthew Ng87cbf342018-02-15 12:21:18 -0800411 mHomeDefaultIcon = getHomeDrawable(ctx);
Winsonfde2e6a2016-03-22 16:03:10 -0700412 }
Jason Monk1f785d42017-07-25 15:46:33 -0400413 if (oldConfig.densityDpi != newConfig.densityDpi
414 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800415 mBackIcon = getBackDrawable(ctx);
Winsonfde2e6a2016-03-22 16:03:10 -0700416 mBackLandIcon = mBackIcon;
Matthew Ng87cbf342018-02-15 12:21:18 -0800417 mBackAltIcon = getBackImeDrawable(ctx);
Winsonfde2e6a2016-03-22 16:03:10 -0700418 mBackAltLandIcon = mBackAltIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700419 mRecentIcon = getDrawable(ctx,
420 R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
421 mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800422 mAccessibilityIcon = getDrawable(ctx, R.drawable.ic_sysbar_accessibility_button,
423 R.drawable.ic_sysbar_accessibility_button_dark);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700424
Jason Monk9a376bc2017-05-10 09:52:10 -0400425 int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
426 int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
427 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
428 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700429 mImeIcon = getDrawable(darkContext, lightContext,
430 R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700431
Mike Digman1e28a5a2018-02-14 10:49:19 -0800432 updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
Mike Digman7d092772018-01-11 12:10:32 -0800433
Justin Paupore01915a12016-09-28 17:41:26 -0700434 if (ALTERNATE_CAR_MODE_UI) {
435 updateCarModeIcons(ctx);
436 }
Winsonfde2e6a2016-03-22 16:03:10 -0700437 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700438 }
439
Matthew Ng87cbf342018-02-15 12:21:18 -0800440 public KeyButtonDrawable getBackDrawable(Context ctx) {
441 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back,
442 R.drawable.ic_sysbar_back_dark, R.drawable.ic_sysbar_back_quick_step,
443 R.drawable.ic_sysbar_back_quick_step_dark);
444 }
445
446 public KeyButtonDrawable getBackImeDrawable(Context ctx) {
447 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back_ime,
448 R.drawable.ic_sysbar_back_ime_dark, R.drawable.ic_sysbar_back_ime_quick_step,
449 R.drawable.ic_sysbar_back_ime_quick_step_dark);
450 }
451
452 public KeyButtonDrawable getHomeDrawable(Context ctx) {
453 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_home,
454 R.drawable.ic_sysbar_home_dark, R.drawable.ic_sysbar_home_quick_step,
455 R.drawable.ic_sysbar_home_quick_step_dark);
456 }
457
458 private KeyButtonDrawable chooseNavigationIconDrawable(Context ctx, @DrawableRes int iconLight,
459 @DrawableRes int iconDark, @DrawableRes int quickStepIconLight,
460 @DrawableRes int quickStepIconDark) {
461 final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
462 return quickStepEnabled
463 ? getDrawable(ctx, quickStepIconLight, quickStepIconDark)
464 : getDrawable(ctx, iconLight, iconDark);
465 }
466
Jorim Jaggi40db0292016-06-27 17:58:03 -0700467 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
468 @DrawableRes int darkIcon) {
469 return getDrawable(ctx, ctx, lightIcon, darkIcon);
470 }
471
472 private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
473 @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
474 return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
475 darkContext.getDrawable(darkIcon));
476 }
477
Mike Digman7d092772018-01-11 12:10:32 -0800478 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
479 @ColorInt int lightColor, @ColorInt int darkColor) {
480 return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
481 }
482
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700483 @Override
484 public void setLayoutDirection(int layoutDirection) {
Winsonfde2e6a2016-03-22 16:03:10 -0700485 // Reload all the icons
486 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700487
488 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400489 }
490
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100491 public void notifyScreenOn() {
John Spurlock1bbd49d2012-10-19 11:09:32 -0400492 setDisabledFlags(mDisabledFlags, true);
493 }
494
Daniel Sandler328310c2011-09-23 15:56:52 -0400495 public void setNavigationIconHints(int hints) {
496 setNavigationIconHints(hints, false);
497 }
498
Jorim Jaggi40db0292016-06-27 17:58:03 -0700499 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800500 return landscape
501 ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
502 : carMode ? mBackAltCarModeIcon : mBackAltIcon;
503 }
504
Jorim Jaggi40db0292016-06-27 17:58:03 -0700505 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800506 return landscape
507 ? carMode ? mBackLandCarModeIcon : mBackLandIcon
508 : carMode ? mBackCarModeIcon : mBackIcon;
509 }
510
Daniel Sandler328310c2011-09-23 15:56:52 -0400511 public void setNavigationIconHints(int hints, boolean force) {
512 if (!force && hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400513 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
514 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
515 mTransitionListener.onBackAltCleared();
516 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400517 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500518 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400519 "Navigation icon hints = " + hints,
520 500).show();
521 }
522
523 mNavigationIconHints = hints;
524
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800525 // We have to replace or restore the back and home button icons when exiting or entering
526 // carmode, respectively. Recents are not available in CarMode in nav bar so change
527 // to recent icon is not required.
Jorim Jaggi40db0292016-06-27 17:58:03 -0700528 KeyButtonDrawable backIcon = (backAlt)
Justin Paupore01915a12016-09-28 17:41:26 -0700529 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
530 : getBackIcon(mUseCarModeUi, mVertical);
John Spurlocka9b46822012-11-02 10:42:39 -0400531
Jason Monka2081822016-01-18 14:41:03 -0500532 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800533
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800534 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800535
Justin Paupore01915a12016-09-28 17:41:26 -0700536 if (mUseCarModeUi) {
Jason Monka2081822016-01-18 14:41:03 -0500537 getHomeButton().setImageDrawable(mHomeCarModeIcon);
538 } else {
539 getHomeButton().setImageDrawable(mHomeDefaultIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800540 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700541
Mike Digmana48cf192018-02-12 17:52:48 -0800542 // Update IME button visibility, a11y and rotate button always overrides the appearance
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700543 final boolean showImeButton =
Mike Digmana48cf192018-02-12 17:52:48 -0800544 !mShowAccessibilityButton &&
545 !mShowRotateButton &&
546 ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
Jason Monka2081822016-01-18 14:41:03 -0500547 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700548 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800549
Mike Digmana48cf192018-02-12 17:52:48 -0800550 // Update menu button, visibility logic in method
Jason Monkf1ff2092014-04-29 16:50:53 -0400551 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700552 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400553
Mike Digmana48cf192018-02-12 17:52:48 -0800554 // Update rotate button, visibility altered by a11y button logic
555 getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
556
557 // Update a11y button, visibility logic in state method
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800558 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
559 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
560
John Spurlocka9b46822012-11-02 10:42:39 -0400561 setDisabledFlags(mDisabledFlags, true);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700562
563 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400564 }
565
Daniel Sandler6da2b762011-09-14 16:04:59 -0400566 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400567 setDisabledFlags(disabledFlags, false);
568 }
569
570 public void setDisabledFlags(int disabledFlags, boolean force) {
571 if (!force && mDisabledFlags == disabledFlags) return;
572
573 mDisabledFlags = disabledFlags;
574
Matthew Ng87cbf342018-02-15 12:21:18 -0800575 boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700576
Justin Paupore01915a12016-09-28 17:41:26 -0700577 // Always disable recents when alternate car mode UI is active.
578 boolean disableRecent = mUseCarModeUi
Charles Hee57ff812017-10-26 10:01:35 +0100579 || ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
580
581 boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
John Spurlocka9b46822012-11-02 10:42:39 -0400582 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400583
Matthew Ng87cbf342018-02-15 12:21:18 -0800584 // When screen pinning, don't hide back and home when connected service or back and
585 // recents buttons when disconnected from launcher service in screen pinning mode,
586 // as they are used for exiting.
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800587 if (mOverviewProxyService.getProxy() != null) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800588 // Use interaction flags to show/hide navigation buttons but will be shown if required
589 // to exit screen pinning.
Matthew Ng8f25fb962018-01-16 17:17:24 -0800590 final int flags = mOverviewProxyService.getInteractionFlags();
591 disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0;
Matthew Ng87cbf342018-02-15 12:21:18 -0800592 if (inScreenPinning()) {
593 disableBack = disableHome = false;
594 } else {
595 disableBack |= (flags & FLAG_HIDE_BACK_BUTTON) != 0;
596 }
597 } else if (inScreenPinning()) {
598 disableBack = disableRecent = false;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800599 }
Charles Hee57ff812017-10-26 10:01:35 +0100600
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800601 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400602 if (navButtons != null) {
603 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400604 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400605 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
606 lt.addTransitionListener(mTransitionListener);
607 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400608 }
609 }
610
Jason Monka2081822016-01-18 14:41:03 -0500611 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500612 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500613 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400614 }
615
Matthew Ng87cbf342018-02-15 12:21:18 -0800616 public boolean inScreenPinning() {
617 return ActivityManagerWrapper.getInstance().isLockToAppActive();
Jason Monk17488b92014-11-06 11:26:14 -0500618 }
619
Jorim Jaggi37c11802015-08-18 20:27:54 -0700620 public void setLayoutTransitionsEnabled(boolean enabled) {
621 mLayoutTransitionsEnabled = enabled;
622 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700623 }
624
Jorim Jaggi37c11802015-08-18 20:27:54 -0700625 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
626 setUseFadingAnimations(wakeAndUnlocking);
627 mWakeAndUnlocking = wakeAndUnlocking;
628 updateLayoutTransitionsEnabled();
629 }
630
631 private void updateLayoutTransitionsEnabled() {
632 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800633 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700634 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400635 if (lt != null) {
636 if (enabled) {
637 lt.enableTransitionType(LayoutTransition.APPEARING);
638 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
639 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
640 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
641 } else {
642 lt.disableTransitionType(LayoutTransition.APPEARING);
643 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
644 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
645 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
646 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700647 }
648 }
649
650 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500651 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
652 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700653 if (lp != null) {
654 boolean old = lp.windowAnimations != 0;
655 if (!old && useFadingAnimations) {
656 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
657 } else if (old && !useFadingAnimations) {
658 lp.windowAnimations = 0;
659 } else {
660 return;
661 }
662 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500663 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700664 }
665 }
666
Matthew Ng78f88d12018-01-23 12:39:55 -0800667 public void onPanelExpandedChange(boolean expanded) {
668 updateSlippery();
669 }
670
Matthew Ng8f25fb962018-01-16 17:17:24 -0800671 public void updateStates() {
672 updateSlippery();
673 setDisabledFlags(mDisabledFlags, true);
674 }
675
Matthew Ng78f88d12018-01-23 12:39:55 -0800676 private void updateSlippery() {
677 setSlippery(mOverviewProxyService.getProxy() != null && mPanelView.isFullyExpanded());
678 }
679
Matthew Ng7d05e772017-11-09 14:41:07 -0800680 private void setSlippery(boolean slippery) {
681 boolean changed = false;
682 final ViewGroup navbarView = ((ViewGroup) getParent());
683 final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
684 .getLayoutParams();
Matthew Ng9c3bce52018-02-01 22:00:31 +0000685 if (lp == null) {
686 return;
687 }
Matthew Ng7d05e772017-11-09 14:41:07 -0800688 if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
689 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
690 changed = true;
691 } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) {
692 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
693 changed = true;
694 }
695 if (changed) {
696 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
697 wm.updateViewLayout(navbarView, lp);
698 }
699 }
700
Daniel Sandler56598cd2011-09-15 16:02:56 -0400701 public void setMenuVisibility(final boolean show) {
702 setMenuVisibility(show, false);
703 }
704
705 public void setMenuVisibility(final boolean show, final boolean force) {
706 if (!force && mShowMenu == show) return;
707
708 mShowMenu = show;
709
Mike Digmana48cf192018-02-12 17:52:48 -0800710 // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown.
711 final boolean shouldShow = mShowMenu &&
712 !mShowAccessibilityButton &&
713 !mShowRotateButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400714 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800715
Jason Monka2081822016-01-18 14:41:03 -0500716 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400717 }
718
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800719 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
720 mShowAccessibilityButton = visible;
721 mLongClickableAccessibilityButton = longClickable;
722 if (visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800723 // Accessibility button overrides Menu, IME switcher and rotate buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800724 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700725 getImeSwitchButton().setVisibility(View.INVISIBLE);
Mike Digman1e28a5a2018-02-14 10:49:19 -0800726 setRotateButtonVisibility(false);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800727 }
728
729 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
730 getAccessibilityButton().setLongClickable(longClickable);
731 }
732
Mike Digman1e28a5a2018-02-14 10:49:19 -0800733 public void updateRotateSuggestionButtonStyle(@StyleRes int style, boolean setIcon) {
734 mRotateBtnStyle = style;
735 final Context ctx = getContext();
736
737 // Extract the dark and light tints
738 final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
739 final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
740 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
741 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
742 final int lightColor = Utils.getColorAttr(lightContext, R.attr.singleToneColor);
743 final int darkColor = Utils.getColorAttr(darkContext, R.attr.singleToneColor);
744
745 // Use the supplied style to set the icon's rotation parameters
746 Context rotateContext = new ContextThemeWrapper(ctx, style);
747
748 // Recreate the icon and set it if needed
749 mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
750 lightColor, darkColor);
751 if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
Mike Digmana48cf192018-02-12 17:52:48 -0800752 }
753
Mike Digman1e28a5a2018-02-14 10:49:19 -0800754 public void setRotateButtonVisibility(final boolean visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800755 // Never show if a11y is visible
756 final boolean adjVisible = visible && !mShowAccessibilityButton;
757 final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
758
Mike Digman1e28a5a2018-02-14 10:49:19 -0800759 // No need to do anything if the request matches the current state
760 if (vis == getRotateSuggestionButton().getVisibility()) return;
761
Mike Digmana48cf192018-02-12 17:52:48 -0800762 getRotateSuggestionButton().setVisibility(vis);
763 mShowRotateButton = visible;
764
Mike Digman1e28a5a2018-02-14 10:49:19 -0800765 // Stop any active animations if hidden
766 if (!visible) {
767 Drawable d = mRotateSuggestionIcon.getDrawable(0);
768 if (d instanceof AnimatedVectorDrawable) {
769 AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d;
770 avd.clearAnimationCallbacks();
771 avd.reset();
772 }
773 }
774
Mike Digmana48cf192018-02-12 17:52:48 -0800775 // Hide/restore other button visibility, if necessary
776 setNavigationIconHints(mNavigationIconHints, true);
777 }
778
Mike Digman1e28a5a2018-02-14 10:49:19 -0800779 public boolean isRotateButtonVisible() { return mShowRotateButton; }
780
Jim Miller960892c2012-05-23 15:50:04 -0700781 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400782 public void onFinishInflate() {
Adrian Roosdb12b152016-07-12 15:38:55 -0700783 mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
784 R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700785 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500786
787 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200788
Jason Monk32e3bb52017-07-27 12:35:41 -0400789 DockedStackExistsListener.register(mDockedListener);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700790 updateRotatedViews();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100791 }
792
Matthew Nga8f24262017-12-19 11:54:24 -0800793 public void onDarkIntensityChange(float intensity) {
794 if (mGestureHelper != null) {
795 mGestureHelper.onDarkIntensityChange(intensity);
796 }
Tony Wickham05c1f852018-02-06 12:32:54 -0800797 if (mRecentsOnboarding != null) {
798 mRecentsOnboarding.setContentDarkIntensity(intensity);
Tony Wickham0239d5f2018-01-22 18:40:05 -0800799 }
Matthew Nga8f24262017-12-19 11:54:24 -0800800 }
801
Matthew Ng9c3bce52018-02-01 22:00:31 +0000802 public void onOverviewProxyConnectionChanged(boolean isConnected) {
Matthew Ng8f25fb962018-01-16 17:17:24 -0800803 updateStates();
804 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ngf2946542018-02-12 14:13:18 -0800805 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
806 setNavigationIconHints(mNavigationIconHints, true);
Matthew Ng9c3bce52018-02-01 22:00:31 +0000807 }
808
Matthew Nga8f24262017-12-19 11:54:24 -0800809 @Override
810 protected void onDraw(Canvas canvas) {
811 mGestureHelper.onDraw(canvas);
812 super.onDraw(canvas);
813 }
814
815 @Override
816 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
817 super.onLayout(changed, left, top, right, bottom);
Winson Chungc4e06202018-02-13 10:37:35 -0800818 updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
819 updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
Matthew Nga8f24262017-12-19 11:54:24 -0800820 mGestureHelper.onLayout(changed, left, top, right, bottom);
821 }
822
Winson Chungc4e06202018-02-13 10:37:35 -0800823 private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) {
824 View view = button.getCurrentView();
825 if (view == null) {
826 buttonBounds.setEmpty();
827 return;
828 }
829 view.getLocationInWindow(mTmpPosition);
830 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
831 mTmpPosition[0] + view.getMeasuredWidth(),
832 mTmpPosition[1] + view.getMeasuredHeight());
833 }
834
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700835 private void updateRotatedViews() {
Jason Monk9a6552d2016-05-20 11:21:59 -0400836 mRotatedViews[Surface.ROTATION_0] =
837 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
838 mRotatedViews[Surface.ROTATION_270] =
839 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
840
Jason Monk199a2d02017-07-28 11:08:27 -0400841 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400842 }
843
Adrian Roosa98b32c2016-08-11 10:41:08 -0700844 public boolean needsReorient(int rotation) {
845 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700846 }
847
Jason Monk199a2d02017-07-28 11:08:27 -0400848 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400849 final int rot = mDisplay.getRotation();
850 for (int i=0; i<4; i++) {
851 mRotatedViews[i].setVisibility(View.GONE);
852 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400853 mCurrentView = mRotatedViews[rot];
854 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700855 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Felipe Leme15f915c2016-10-31 12:47:15 -0700856 for (int i = 0; i < mButtonDispatchers.size(); i++) {
857 mButtonDispatchers.valueAt(i).setCurrentView(mCurrentView);
Jason Monka2081822016-01-18 14:41:03 -0500858 }
Jorim Jaggi37c11802015-08-18 20:27:54 -0700859 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700860 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400861 }
862
863 private void updateRecentsIcon() {
864 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700865 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400866 }
867
868 public boolean isVertical() {
869 return mVertical;
870 }
871
872 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400873 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400874
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400875 mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700876
877 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Jorim Jaggi7aaa3d72016-11-28 14:03:11 +0100878 mDeadZone.setDisplayRotation(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400879
Daniel Sandler6da2b762011-09-14 16:04:59 -0400880 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700881 mBarTransitions.init();
Daniel Sandler6da2b762011-09-14 16:04:59 -0400882 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400883 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400884
Daniel Sandler60ee2562011-07-22 12:34:33 -0400885 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700886 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400887 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800888
Matthew Ng5fd80412018-02-14 14:40:31 -0800889 // Resolve layout direction if not resolved since components changing layout direction such
890 // as changing languages will recreate this view and the direction will be resolved later
891 if (!isLayoutDirectionResolved()) {
892 resolveLayoutDirection();
893 }
Selim Cinek92d892c2014-09-11 15:11:00 +0200894 updateTaskSwitchHelper();
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800895 setNavigationIconHints(mNavigationIconHints, true);
Xiaohui Chen9efa5de2016-11-22 10:34:38 -0800896
Xiaohui Chen40e978e2016-11-29 15:10:04 -0800897 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400898 }
Daniel Sandler48852952011-12-01 14:34:23 -0500899
Selim Cinek92d892c2014-09-11 15:11:00 +0200900 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -0500901 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +0200902 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800903 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +0200904 }
905
Daniel Sandler0b69b592012-01-23 21:08:36 -0500906 @Override
907 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -0400908 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500909 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400910
911 final boolean newVertical = w > 0 && h > w;
912 if (newVertical != mVertical) {
913 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -0400914 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400915 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +0200916 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -0400917 }
918
Daniel Sandler0b69b592012-01-23 21:08:36 -0500919 postCheckForInvalidLayout("sizeChanged");
920 super.onSizeChanged(w, h, oldw, oldh);
921 }
922
Selim Cinek92d892c2014-09-11 15:11:00 +0200923 private void notifyVerticalChangedListener(boolean newVertical) {
924 if (mOnVerticalChangedListener != null) {
925 mOnVerticalChangedListener.onVerticalChanged(newVertical);
926 }
927 }
928
Selim Cinek17a327a2014-08-25 15:03:48 +0200929 @Override
930 protected void onConfigurationChanged(Configuration newConfig) {
931 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800932 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +0200933 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -0700934 updateIcons(getContext(), mConfiguration, newConfig);
935 updateRecentsIcon();
Tony Wickham05c1f852018-02-06 12:32:54 -0800936 mRecentsOnboarding.onConfigurationChanged(newConfig);
Jason Monk1f785d42017-07-25 15:46:33 -0400937 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
938 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700939 // If car mode or density changes, we need to reset the icons.
940 setNavigationIconHints(mNavigationIconHints, true);
941 }
Winsonfde2e6a2016-03-22 16:03:10 -0700942 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800943 }
944
945 /**
946 * If the configuration changed, update the carmode and return that it was updated.
947 */
948 private boolean updateCarMode(Configuration newConfig) {
949 boolean uiCarModeChanged = false;
950 if (newConfig != null) {
951 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -0700952 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
953
954 if (isCarMode != mInCarMode) {
955 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -0700956 if (ALTERNATE_CAR_MODE_UI) {
957 mUseCarModeUi = isCarMode;
958 uiCarModeChanged = true;
959 } else {
960 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
961 mUseCarModeUi = false;
962 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800963 }
964 }
965 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +0200966 }
967
Daniel Sandler0b69b592012-01-23 21:08:36 -0500968 /*
969 @Override
970 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -0400971 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -0400972 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -0500973 changed?"changed":"notchanged", left, top, right, bottom));
974 super.onLayout(changed, left, top, right, bottom);
975 }
976
977 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
978 // fails, any touch on the display will fix the layout.
979 @Override
980 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -0400981 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -0500982 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
983 postCheckForInvalidLayout("touch");
984 }
985 return super.onInterceptTouchEvent(ev);
986 }
987 */
John Spurlock209bede2013-07-17 12:23:27 -0400988
Daniel Sandler0b69b592012-01-23 21:08:36 -0500989
Daniel Sandler48852952011-12-01 14:34:23 -0500990 private String getResourceName(int resId) {
991 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -0500992 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -0500993 try {
994 return res.getResourceName(resId);
995 } catch (android.content.res.Resources.NotFoundException ex) {
996 return "(unknown)";
997 }
998 } else {
999 return "(null)";
1000 }
1001 }
1002
Daniel Sandler0b69b592012-01-23 21:08:36 -05001003 private void postCheckForInvalidLayout(final String how) {
1004 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
1005 }
1006
Daniel Sandler48852952011-12-01 14:34:23 -05001007 private static String visibilityToString(int vis) {
1008 switch (vis) {
1009 case View.INVISIBLE:
1010 return "INVISIBLE";
1011 case View.GONE:
1012 return "GONE";
1013 default:
1014 return "VISIBLE";
1015 }
1016 }
1017
Jason Monk67e6c802016-08-30 14:09:21 -04001018 @Override
1019 protected void onAttachedToWindow() {
1020 super.onAttachedToWindow();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -07001021 reorient();
Jason Monkde850bb2017-02-01 19:26:30 -05001022 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -08001023 Dependency.get(PluginManager.class).addPluginListener(this,
1024 NavGesture.class, false /* Only one */);
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001025 setUpSwipeUpOnboarding(mOverviewProxyService.getProxy() != null);
Jason Monk67e6c802016-08-30 14:09:21 -04001026 }
1027
1028 @Override
1029 protected void onDetachedFromWindow() {
1030 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -05001031 Dependency.get(PluginManager.class).removePluginListener(this);
1032 if (mGestureHelper != null) {
1033 mGestureHelper.destroy();
1034 }
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001035 setUpSwipeUpOnboarding(false);
1036 }
1037
1038 private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
1039 if (connectedToOverviewProxy) {
Tony Wickham05c1f852018-02-06 12:32:54 -08001040 mRecentsOnboarding.onConnectedToLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001041 } else {
Tony Wickham05c1f852018-02-06 12:32:54 -08001042 mRecentsOnboarding.onDisconnectedFromLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001043 }
Jason Monk67e6c802016-08-30 14:09:21 -04001044 }
1045
1046 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -05001047 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -04001048 mGestureHelper = plugin.getGestureHelper();
1049 updateTaskSwitchHelper();
1050 }
1051
1052 @Override
1053 public void onPluginDisconnected(NavGesture plugin) {
1054 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
1055 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -05001056 if (mGestureHelper != null) {
1057 mGestureHelper.destroy();
1058 }
Jason Monk67e6c802016-08-30 14:09:21 -04001059 mGestureHelper = defaultHelper;
1060 updateTaskSwitchHelper();
1061 }
1062
Daniel Sandler48852952011-12-01 14:34:23 -05001063 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1064 pw.println("NavigationBarView {");
1065 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -07001066 final Point size = new Point();
1067 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -05001068
Jason Monk2a6ea9c2017-01-26 11:14:51 -05001069 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -05001070 + " " + visibilityToString(getVisibility())));
1071
1072 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -07001073 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -04001074 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -05001075 + r.toShortString()
1076 + " " + visibilityToString(getWindowVisibility())
1077 + (offscreen ? " OFFSCREEN!" : ""));
1078
1079 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -08001080 getResourceName(getCurrentView().getId()),
1081 getCurrentView().getWidth(), getCurrentView().getHeight(),
1082 visibilityToString(getCurrentView().getVisibility())));
Daniel Sandler48852952011-12-01 14:34:23 -05001083
John Spurlock41c1e352013-09-16 13:57:13 -04001084 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -05001085 mDisabledFlags,
1086 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -05001087 mShowMenu ? "true" : "false"));
1088
John Spurlock56d007b2013-10-28 18:40:56 -04001089 dumpButton(pw, "back", getBackButton());
1090 dumpButton(pw, "home", getHomeButton());
1091 dumpButton(pw, "rcnt", getRecentsButton());
1092 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001093 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -05001094
Daniel Sandler48852952011-12-01 14:34:23 -05001095 pw.println(" }");
1096 }
Jim Millere898ac52012-04-06 17:10:57 -07001097
Jason Monka2081822016-01-18 14:41:03 -05001098 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -04001099 pw.print(" " + caption + ": ");
1100 if (button == null) {
1101 pw.print("null");
1102 } else {
Jason Monka2081822016-01-18 14:41:03 -05001103 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -04001104 + " alpha=" + button.getAlpha()
1105 );
John Spurlock56d007b2013-10-28 18:40:56 -04001106 }
1107 pw.println();
1108 }
1109
Jorim Jaggif4797922014-08-04 22:49:41 +02001110 public interface OnVerticalChangedListener {
1111 void onVerticalChanged(boolean isVertical);
1112 }
Jason Monka2081822016-01-18 14:41:03 -05001113
Jason Monk32e3bb52017-07-27 12:35:41 -04001114 private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> {
1115 mDockedStackExists = exists;
1116 updateRecentsIcon();
1117 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001118}