blob: 285980b39020128bc51fc405b7d370d81ec00eb2 [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;
Jason Monk00659ba2017-03-03 10:28:45 -050032import android.app.ActivityManager;
Daniel Sandler328310c2011-09-23 15:56:52 -040033import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040034import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020035import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080036import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070037import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050038import android.graphics.Rect;
Mike Digmana48cf192018-02-12 17:52:48 -080039import android.graphics.drawable.AnimatedVectorDrawable;
Daniel Sandler0b69b592012-01-23 21:08:36 -050040import android.os.Handler;
41import android.os.Message;
Jason Monk17488b92014-11-06 11:26:14 -050042import android.os.RemoteException;
Matthew Ng8f25fb962018-01-16 17:17:24 -080043import android.os.SystemProperties;
Mike Digman7d092772018-01-11 12:10:32 -080044import android.support.annotation.ColorInt;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040045import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040046import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050047import android.util.SparseArray;
Jorim Jaggi40db0292016-06-27 17:58:03 -070048import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040049import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040050import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040051import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040052import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040053import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040054import android.view.WindowManager;
Jason Monkf1ff2092014-04-29 16:50:53 -040055import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040056import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040057
Jason Monk9a376bc2017-05-10 09:52:10 -040058import com.android.settingslib.Utils;
Jason Monkde850bb2017-02-01 19:26:30 -050059import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040060import com.android.systemui.DockedStackExistsListener;
Mike Digmana48cf192018-02-12 17:52:48 -080061import com.android.systemui.Interpolators;
Matthew Ng7d05e772017-11-09 14:41:07 -080062import com.android.systemui.OverviewProxyService;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040063import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080064import com.android.systemui.RecentsComponent;
Jason Monk67e6c802016-08-30 14:09:21 -040065import com.android.systemui.plugins.PluginListener;
66import com.android.systemui.plugins.PluginManager;
67import com.android.systemui.plugins.statusbar.phone.NavGesture;
68import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
Tony Wickham05c1f852018-02-06 12:32:54 -080069import com.android.systemui.recents.RecentsOnboarding;
Matthew Ng87cbf342018-02-15 12:21:18 -080070import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungc4e06202018-02-13 10:37:35 -080071import com.android.systemui.shared.system.NavigationBarCompat;
Jorim Jaggidd98d412015-11-18 15:57:38 -080072import com.android.systemui.stackdivider.Divider;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040073import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070074import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Tony Wickhamfb63fe82018-01-16 12:14:06 -080075import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070076
John Spurlockde84f0e2013-06-12 12:41:00 -040077import java.io.FileDescriptor;
78import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040079import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040080
Matthew Ng8f25fb962018-01-16 17:17:24 -080081import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
82import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_SWIPE_UP;
83import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_HIDE_BACK_BUTTON;
84import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
85
Jason Monk67e6c802016-08-30 14:09:21 -040086public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040087 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070088 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040089
Mike Digmana48cf192018-02-12 17:52:48 -080090 final static int BUTTON_FADE_IN_OUT_DURATION_MS = 100;
91
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 Digmana48cf192018-02-12 17:52:48 -0800155 private Animator mRotateHideAnimator;
156
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 Digman7d092772018-01-11 12:10:32 -0800432 int lightColor = Utils.getColorAttr(lightContext, R.attr.singleToneColor);
433 int darkColor = Utils.getColorAttr(darkContext, R.attr.singleToneColor);
434 mRotateSuggestionIcon = getDrawable(ctx, R.drawable.ic_sysbar_rotate_button,
435 lightColor, darkColor);
436
Justin Paupore01915a12016-09-28 17:41:26 -0700437 if (ALTERNATE_CAR_MODE_UI) {
438 updateCarModeIcons(ctx);
439 }
Winsonfde2e6a2016-03-22 16:03:10 -0700440 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700441 }
442
Matthew Ng87cbf342018-02-15 12:21:18 -0800443 public KeyButtonDrawable getBackDrawable(Context ctx) {
444 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back,
445 R.drawable.ic_sysbar_back_dark, R.drawable.ic_sysbar_back_quick_step,
446 R.drawable.ic_sysbar_back_quick_step_dark);
447 }
448
449 public KeyButtonDrawable getBackImeDrawable(Context ctx) {
450 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_back_ime,
451 R.drawable.ic_sysbar_back_ime_dark, R.drawable.ic_sysbar_back_ime_quick_step,
452 R.drawable.ic_sysbar_back_ime_quick_step_dark);
453 }
454
455 public KeyButtonDrawable getHomeDrawable(Context ctx) {
456 return chooseNavigationIconDrawable(ctx, R.drawable.ic_sysbar_home,
457 R.drawable.ic_sysbar_home_dark, R.drawable.ic_sysbar_home_quick_step,
458 R.drawable.ic_sysbar_home_quick_step_dark);
459 }
460
461 private KeyButtonDrawable chooseNavigationIconDrawable(Context ctx, @DrawableRes int iconLight,
462 @DrawableRes int iconDark, @DrawableRes int quickStepIconLight,
463 @DrawableRes int quickStepIconDark) {
464 final boolean quickStepEnabled = isQuickStepSwipeUpEnabled() || isQuickScrubEnabled();
465 return quickStepEnabled
466 ? getDrawable(ctx, quickStepIconLight, quickStepIconDark)
467 : getDrawable(ctx, iconLight, iconDark);
468 }
469
Jorim Jaggi40db0292016-06-27 17:58:03 -0700470 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
471 @DrawableRes int darkIcon) {
472 return getDrawable(ctx, ctx, lightIcon, darkIcon);
473 }
474
475 private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
476 @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
477 return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
478 darkContext.getDrawable(darkIcon));
479 }
480
Mike Digman7d092772018-01-11 12:10:32 -0800481 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
482 @ColorInt int lightColor, @ColorInt int darkColor) {
483 return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
484 }
485
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700486 @Override
487 public void setLayoutDirection(int layoutDirection) {
Winsonfde2e6a2016-03-22 16:03:10 -0700488 // Reload all the icons
489 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700490
491 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400492 }
493
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100494 public void notifyScreenOn() {
John Spurlock1bbd49d2012-10-19 11:09:32 -0400495 setDisabledFlags(mDisabledFlags, true);
496 }
497
Daniel Sandler328310c2011-09-23 15:56:52 -0400498 public void setNavigationIconHints(int hints) {
499 setNavigationIconHints(hints, false);
500 }
501
Jorim Jaggi40db0292016-06-27 17:58:03 -0700502 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800503 return landscape
504 ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
505 : carMode ? mBackAltCarModeIcon : mBackAltIcon;
506 }
507
Jorim Jaggi40db0292016-06-27 17:58:03 -0700508 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800509 return landscape
510 ? carMode ? mBackLandCarModeIcon : mBackLandIcon
511 : carMode ? mBackCarModeIcon : mBackIcon;
512 }
513
Daniel Sandler328310c2011-09-23 15:56:52 -0400514 public void setNavigationIconHints(int hints, boolean force) {
515 if (!force && hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400516 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
517 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
518 mTransitionListener.onBackAltCleared();
519 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400520 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500521 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400522 "Navigation icon hints = " + hints,
523 500).show();
524 }
525
526 mNavigationIconHints = hints;
527
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800528 // We have to replace or restore the back and home button icons when exiting or entering
529 // carmode, respectively. Recents are not available in CarMode in nav bar so change
530 // to recent icon is not required.
Jorim Jaggi40db0292016-06-27 17:58:03 -0700531 KeyButtonDrawable backIcon = (backAlt)
Justin Paupore01915a12016-09-28 17:41:26 -0700532 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
533 : getBackIcon(mUseCarModeUi, mVertical);
John Spurlocka9b46822012-11-02 10:42:39 -0400534
Jason Monka2081822016-01-18 14:41:03 -0500535 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800536
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800537 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800538
Justin Paupore01915a12016-09-28 17:41:26 -0700539 if (mUseCarModeUi) {
Jason Monka2081822016-01-18 14:41:03 -0500540 getHomeButton().setImageDrawable(mHomeCarModeIcon);
541 } else {
542 getHomeButton().setImageDrawable(mHomeDefaultIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800543 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700544
Mike Digmana48cf192018-02-12 17:52:48 -0800545 // Update IME button visibility, a11y and rotate button always overrides the appearance
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700546 final boolean showImeButton =
Mike Digmana48cf192018-02-12 17:52:48 -0800547 !mShowAccessibilityButton &&
548 !mShowRotateButton &&
549 ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
Jason Monka2081822016-01-18 14:41:03 -0500550 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700551 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800552
Mike Digmana48cf192018-02-12 17:52:48 -0800553 // Update menu button, visibility logic in method
Jason Monkf1ff2092014-04-29 16:50:53 -0400554 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700555 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400556
Mike Digmana48cf192018-02-12 17:52:48 -0800557 // Update rotate button, visibility altered by a11y button logic
558 getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
559
560 // Update a11y button, visibility logic in state method
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800561 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
562 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
563
John Spurlocka9b46822012-11-02 10:42:39 -0400564 setDisabledFlags(mDisabledFlags, true);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700565
566 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400567 }
568
Daniel Sandler6da2b762011-09-14 16:04:59 -0400569 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400570 setDisabledFlags(disabledFlags, false);
571 }
572
573 public void setDisabledFlags(int disabledFlags, boolean force) {
574 if (!force && mDisabledFlags == disabledFlags) return;
575
576 mDisabledFlags = disabledFlags;
577
Matthew Ng87cbf342018-02-15 12:21:18 -0800578 boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700579
Justin Paupore01915a12016-09-28 17:41:26 -0700580 // Always disable recents when alternate car mode UI is active.
581 boolean disableRecent = mUseCarModeUi
Charles Hee57ff812017-10-26 10:01:35 +0100582 || ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
583
584 boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
John Spurlocka9b46822012-11-02 10:42:39 -0400585 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400586
Matthew Ng87cbf342018-02-15 12:21:18 -0800587 // When screen pinning, don't hide back and home when connected service or back and
588 // recents buttons when disconnected from launcher service in screen pinning mode,
589 // as they are used for exiting.
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800590 if (mOverviewProxyService.getProxy() != null) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800591 // Use interaction flags to show/hide navigation buttons but will be shown if required
592 // to exit screen pinning.
Matthew Ng8f25fb962018-01-16 17:17:24 -0800593 final int flags = mOverviewProxyService.getInteractionFlags();
594 disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0;
Matthew Ng87cbf342018-02-15 12:21:18 -0800595 if (inScreenPinning()) {
596 disableBack = disableHome = false;
597 } else {
598 disableBack |= (flags & FLAG_HIDE_BACK_BUTTON) != 0;
599 }
600 } else if (inScreenPinning()) {
601 disableBack = disableRecent = false;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800602 }
Charles Hee57ff812017-10-26 10:01:35 +0100603
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800604 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400605 if (navButtons != null) {
606 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400607 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400608 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
609 lt.addTransitionListener(mTransitionListener);
610 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400611 }
612 }
613
Jason Monka2081822016-01-18 14:41:03 -0500614 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500615 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500616 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400617 }
618
Matthew Ng87cbf342018-02-15 12:21:18 -0800619 public boolean inScreenPinning() {
620 return ActivityManagerWrapper.getInstance().isLockToAppActive();
Jason Monk17488b92014-11-06 11:26:14 -0500621 }
622
Jorim Jaggi37c11802015-08-18 20:27:54 -0700623 public void setLayoutTransitionsEnabled(boolean enabled) {
624 mLayoutTransitionsEnabled = enabled;
625 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700626 }
627
Jorim Jaggi37c11802015-08-18 20:27:54 -0700628 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
629 setUseFadingAnimations(wakeAndUnlocking);
630 mWakeAndUnlocking = wakeAndUnlocking;
631 updateLayoutTransitionsEnabled();
632 }
633
634 private void updateLayoutTransitionsEnabled() {
635 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800636 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700637 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400638 if (lt != null) {
639 if (enabled) {
640 lt.enableTransitionType(LayoutTransition.APPEARING);
641 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
642 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
643 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
644 } else {
645 lt.disableTransitionType(LayoutTransition.APPEARING);
646 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
647 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
648 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
649 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700650 }
651 }
652
653 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500654 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
655 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700656 if (lp != null) {
657 boolean old = lp.windowAnimations != 0;
658 if (!old && useFadingAnimations) {
659 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
660 } else if (old && !useFadingAnimations) {
661 lp.windowAnimations = 0;
662 } else {
663 return;
664 }
665 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500666 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700667 }
668 }
669
Matthew Ng78f88d12018-01-23 12:39:55 -0800670 public void onPanelExpandedChange(boolean expanded) {
671 updateSlippery();
672 }
673
Matthew Ng8f25fb962018-01-16 17:17:24 -0800674 public void updateStates() {
675 updateSlippery();
676 setDisabledFlags(mDisabledFlags, true);
677 }
678
Matthew Ng78f88d12018-01-23 12:39:55 -0800679 private void updateSlippery() {
680 setSlippery(mOverviewProxyService.getProxy() != null && mPanelView.isFullyExpanded());
681 }
682
Matthew Ng7d05e772017-11-09 14:41:07 -0800683 private void setSlippery(boolean slippery) {
684 boolean changed = false;
685 final ViewGroup navbarView = ((ViewGroup) getParent());
686 final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
687 .getLayoutParams();
Matthew Ng9c3bce52018-02-01 22:00:31 +0000688 if (lp == null) {
689 return;
690 }
Matthew Ng7d05e772017-11-09 14:41:07 -0800691 if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
692 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
693 changed = true;
694 } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) {
695 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
696 changed = true;
697 }
698 if (changed) {
699 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
700 wm.updateViewLayout(navbarView, lp);
701 }
702 }
703
Daniel Sandler56598cd2011-09-15 16:02:56 -0400704 public void setMenuVisibility(final boolean show) {
705 setMenuVisibility(show, false);
706 }
707
708 public void setMenuVisibility(final boolean show, final boolean force) {
709 if (!force && mShowMenu == show) return;
710
711 mShowMenu = show;
712
Mike Digmana48cf192018-02-12 17:52:48 -0800713 // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown.
714 final boolean shouldShow = mShowMenu &&
715 !mShowAccessibilityButton &&
716 !mShowRotateButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400717 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800718
Jason Monka2081822016-01-18 14:41:03 -0500719 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400720 }
721
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800722 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
723 mShowAccessibilityButton = visible;
724 mLongClickableAccessibilityButton = longClickable;
725 if (visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800726 // Accessibility button overrides Menu, IME switcher and rotate buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800727 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700728 getImeSwitchButton().setVisibility(View.INVISIBLE);
Mike Digmana48cf192018-02-12 17:52:48 -0800729 setRotateSuggestionButtonState(false, true);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800730 }
731
732 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
733 getAccessibilityButton().setLongClickable(longClickable);
734 }
735
Mike Digmana48cf192018-02-12 17:52:48 -0800736 public void setRotateSuggestionButtonState(final boolean visible) {
737 setRotateSuggestionButtonState(visible, false);
738 }
739
740 public void setRotateSuggestionButtonState(final boolean visible, final boolean force) {
741 ButtonDispatcher rotBtn = getRotateSuggestionButton();
742 final boolean currentlyVisible = mShowRotateButton;
743
744 // Rerun a show animation to indicate change but don't rerun a hide animation
745 if (!visible && !currentlyVisible) return;
746
747 View currentView = rotBtn.getCurrentView();
748 if (currentView == null) return;
749
750 KeyButtonDrawable kbd = rotBtn.getImageDrawable();
751 if (kbd == null) return;
752
753 AnimatedVectorDrawable animIcon = null;
754 if (kbd.getDrawable(0) instanceof AnimatedVectorDrawable) {
755 animIcon = (AnimatedVectorDrawable) kbd.getDrawable(0);
756 }
757
758 if (visible) { // Appear and change, cannot force
759 setRotateButtonVisibility(true);
760
761 // Stop any currently running hide animations
762 if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
763 mRotateHideAnimator.pause();
764 }
765
766 // Reset the alpha if any has changed due to hide animation
767 currentView.setAlpha(1f);
768
769 // Run the rotate icon's animation if it has one
770 if (animIcon != null) {
771 animIcon.reset();
772 animIcon.start();
773 }
774
775 } else { // Hide
776 if (force) {
777 // If a hide animator is running stop it and instantly make invisible
778 if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) {
779 mRotateHideAnimator.pause();
780 }
781 setRotateButtonVisibility(false);
782 return;
783 }
784
785 // Don't start any new hide animations if one is running
786 if (mRotateHideAnimator != null && mRotateHideAnimator.isRunning()) return;
787
788 ObjectAnimator fadeOut = ObjectAnimator.ofFloat(currentView, "alpha",
789 0f);
790 fadeOut.setDuration(BUTTON_FADE_IN_OUT_DURATION_MS);
791 fadeOut.setInterpolator(Interpolators.LINEAR);
792 fadeOut.addListener(new AnimatorListenerAdapter() {
793 @Override
794 public void onAnimationEnd(Animator animation) {
795 setRotateButtonVisibility(false);
796 }
797 });
798
799 mRotateHideAnimator = fadeOut;
800 fadeOut.start();
801 }
802 }
803
804 private void setRotateButtonVisibility(final boolean visible) {
805 // Never show if a11y is visible
806 final boolean adjVisible = visible && !mShowAccessibilityButton;
807 final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
808
809 getRotateSuggestionButton().setVisibility(vis);
810 mShowRotateButton = visible;
811
812 // Hide/restore other button visibility, if necessary
813 setNavigationIconHints(mNavigationIconHints, true);
814 }
815
Jim Miller960892c2012-05-23 15:50:04 -0700816 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400817 public void onFinishInflate() {
Adrian Roosdb12b152016-07-12 15:38:55 -0700818 mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
819 R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700820 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500821
822 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200823
Jason Monk32e3bb52017-07-27 12:35:41 -0400824 DockedStackExistsListener.register(mDockedListener);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700825 updateRotatedViews();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100826 }
827
Matthew Nga8f24262017-12-19 11:54:24 -0800828 public void onDarkIntensityChange(float intensity) {
829 if (mGestureHelper != null) {
830 mGestureHelper.onDarkIntensityChange(intensity);
831 }
Tony Wickham05c1f852018-02-06 12:32:54 -0800832 if (mRecentsOnboarding != null) {
833 mRecentsOnboarding.setContentDarkIntensity(intensity);
Tony Wickham0239d5f2018-01-22 18:40:05 -0800834 }
Matthew Nga8f24262017-12-19 11:54:24 -0800835 }
836
Matthew Ng9c3bce52018-02-01 22:00:31 +0000837 public void onOverviewProxyConnectionChanged(boolean isConnected) {
Matthew Ng8f25fb962018-01-16 17:17:24 -0800838 updateStates();
839 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ngf2946542018-02-12 14:13:18 -0800840 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
841 setNavigationIconHints(mNavigationIconHints, true);
Matthew Ng9c3bce52018-02-01 22:00:31 +0000842 }
843
Matthew Nga8f24262017-12-19 11:54:24 -0800844 @Override
845 protected void onDraw(Canvas canvas) {
846 mGestureHelper.onDraw(canvas);
847 super.onDraw(canvas);
848 }
849
850 @Override
851 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
852 super.onLayout(changed, left, top, right, bottom);
Winson Chungc4e06202018-02-13 10:37:35 -0800853 updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
854 updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
Matthew Nga8f24262017-12-19 11:54:24 -0800855 mGestureHelper.onLayout(changed, left, top, right, bottom);
856 }
857
Winson Chungc4e06202018-02-13 10:37:35 -0800858 private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) {
859 View view = button.getCurrentView();
860 if (view == null) {
861 buttonBounds.setEmpty();
862 return;
863 }
864 view.getLocationInWindow(mTmpPosition);
865 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
866 mTmpPosition[0] + view.getMeasuredWidth(),
867 mTmpPosition[1] + view.getMeasuredHeight());
868 }
869
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700870 private void updateRotatedViews() {
Jason Monk9a6552d2016-05-20 11:21:59 -0400871 mRotatedViews[Surface.ROTATION_0] =
872 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
873 mRotatedViews[Surface.ROTATION_270] =
874 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
875
Jason Monk199a2d02017-07-28 11:08:27 -0400876 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400877 }
878
Adrian Roosa98b32c2016-08-11 10:41:08 -0700879 public boolean needsReorient(int rotation) {
880 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700881 }
882
Jason Monk199a2d02017-07-28 11:08:27 -0400883 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400884 final int rot = mDisplay.getRotation();
885 for (int i=0; i<4; i++) {
886 mRotatedViews[i].setVisibility(View.GONE);
887 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400888 mCurrentView = mRotatedViews[rot];
889 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700890 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Felipe Leme15f915c2016-10-31 12:47:15 -0700891 for (int i = 0; i < mButtonDispatchers.size(); i++) {
892 mButtonDispatchers.valueAt(i).setCurrentView(mCurrentView);
Jason Monka2081822016-01-18 14:41:03 -0500893 }
Jorim Jaggi37c11802015-08-18 20:27:54 -0700894 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700895 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400896 }
897
898 private void updateRecentsIcon() {
899 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700900 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400901 }
902
903 public boolean isVertical() {
904 return mVertical;
905 }
906
907 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400908 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400909
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400910 mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700911
912 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Jorim Jaggi7aaa3d72016-11-28 14:03:11 +0100913 mDeadZone.setDisplayRotation(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400914
Daniel Sandler6da2b762011-09-14 16:04:59 -0400915 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700916 mBarTransitions.init();
Daniel Sandler6da2b762011-09-14 16:04:59 -0400917 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400918 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400919
Daniel Sandler60ee2562011-07-22 12:34:33 -0400920 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700921 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400922 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800923
Matthew Ng5fd80412018-02-14 14:40:31 -0800924 // Resolve layout direction if not resolved since components changing layout direction such
925 // as changing languages will recreate this view and the direction will be resolved later
926 if (!isLayoutDirectionResolved()) {
927 resolveLayoutDirection();
928 }
Selim Cinek92d892c2014-09-11 15:11:00 +0200929 updateTaskSwitchHelper();
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800930 setNavigationIconHints(mNavigationIconHints, true);
Xiaohui Chen9efa5de2016-11-22 10:34:38 -0800931
Xiaohui Chen40e978e2016-11-29 15:10:04 -0800932 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400933 }
Daniel Sandler48852952011-12-01 14:34:23 -0500934
Selim Cinek92d892c2014-09-11 15:11:00 +0200935 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -0500936 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +0200937 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800938 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +0200939 }
940
Daniel Sandler0b69b592012-01-23 21:08:36 -0500941 @Override
942 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -0400943 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500944 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400945
946 final boolean newVertical = w > 0 && h > w;
947 if (newVertical != mVertical) {
948 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -0400949 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400950 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +0200951 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -0400952 }
953
Daniel Sandler0b69b592012-01-23 21:08:36 -0500954 postCheckForInvalidLayout("sizeChanged");
955 super.onSizeChanged(w, h, oldw, oldh);
956 }
957
Selim Cinek92d892c2014-09-11 15:11:00 +0200958 private void notifyVerticalChangedListener(boolean newVertical) {
959 if (mOnVerticalChangedListener != null) {
960 mOnVerticalChangedListener.onVerticalChanged(newVertical);
961 }
962 }
963
Selim Cinek17a327a2014-08-25 15:03:48 +0200964 @Override
965 protected void onConfigurationChanged(Configuration newConfig) {
966 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800967 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +0200968 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -0700969 updateIcons(getContext(), mConfiguration, newConfig);
970 updateRecentsIcon();
Tony Wickham05c1f852018-02-06 12:32:54 -0800971 mRecentsOnboarding.onConfigurationChanged(newConfig);
Jason Monk1f785d42017-07-25 15:46:33 -0400972 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
973 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700974 // If car mode or density changes, we need to reset the icons.
975 setNavigationIconHints(mNavigationIconHints, true);
976 }
Winsonfde2e6a2016-03-22 16:03:10 -0700977 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800978 }
979
980 /**
981 * If the configuration changed, update the carmode and return that it was updated.
982 */
983 private boolean updateCarMode(Configuration newConfig) {
984 boolean uiCarModeChanged = false;
985 if (newConfig != null) {
986 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -0700987 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
988
989 if (isCarMode != mInCarMode) {
990 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -0700991 if (ALTERNATE_CAR_MODE_UI) {
992 mUseCarModeUi = isCarMode;
993 uiCarModeChanged = true;
994 } else {
995 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
996 mUseCarModeUi = false;
997 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800998 }
999 }
1000 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +02001001 }
1002
Daniel Sandler0b69b592012-01-23 21:08:36 -05001003 /*
1004 @Override
1005 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -04001006 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -04001007 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -05001008 changed?"changed":"notchanged", left, top, right, bottom));
1009 super.onLayout(changed, left, top, right, bottom);
1010 }
1011
1012 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
1013 // fails, any touch on the display will fix the layout.
1014 @Override
1015 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -04001016 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -05001017 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1018 postCheckForInvalidLayout("touch");
1019 }
1020 return super.onInterceptTouchEvent(ev);
1021 }
1022 */
John Spurlock209bede2013-07-17 12:23:27 -04001023
Daniel Sandler0b69b592012-01-23 21:08:36 -05001024
Daniel Sandler48852952011-12-01 14:34:23 -05001025 private String getResourceName(int resId) {
1026 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -05001027 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -05001028 try {
1029 return res.getResourceName(resId);
1030 } catch (android.content.res.Resources.NotFoundException ex) {
1031 return "(unknown)";
1032 }
1033 } else {
1034 return "(null)";
1035 }
1036 }
1037
Daniel Sandler0b69b592012-01-23 21:08:36 -05001038 private void postCheckForInvalidLayout(final String how) {
1039 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
1040 }
1041
Daniel Sandler48852952011-12-01 14:34:23 -05001042 private static String visibilityToString(int vis) {
1043 switch (vis) {
1044 case View.INVISIBLE:
1045 return "INVISIBLE";
1046 case View.GONE:
1047 return "GONE";
1048 default:
1049 return "VISIBLE";
1050 }
1051 }
1052
Jason Monk67e6c802016-08-30 14:09:21 -04001053 @Override
1054 protected void onAttachedToWindow() {
1055 super.onAttachedToWindow();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -07001056 reorient();
Jason Monkde850bb2017-02-01 19:26:30 -05001057 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -08001058 Dependency.get(PluginManager.class).addPluginListener(this,
1059 NavGesture.class, false /* Only one */);
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001060 setUpSwipeUpOnboarding(mOverviewProxyService.getProxy() != null);
Jason Monk67e6c802016-08-30 14:09:21 -04001061 }
1062
1063 @Override
1064 protected void onDetachedFromWindow() {
1065 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -05001066 Dependency.get(PluginManager.class).removePluginListener(this);
1067 if (mGestureHelper != null) {
1068 mGestureHelper.destroy();
1069 }
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001070 setUpSwipeUpOnboarding(false);
1071 }
1072
1073 private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
1074 if (connectedToOverviewProxy) {
Tony Wickham05c1f852018-02-06 12:32:54 -08001075 mRecentsOnboarding.onConnectedToLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001076 } else {
Tony Wickham05c1f852018-02-06 12:32:54 -08001077 mRecentsOnboarding.onDisconnectedFromLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001078 }
Jason Monk67e6c802016-08-30 14:09:21 -04001079 }
1080
1081 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -05001082 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -04001083 mGestureHelper = plugin.getGestureHelper();
1084 updateTaskSwitchHelper();
1085 }
1086
1087 @Override
1088 public void onPluginDisconnected(NavGesture plugin) {
1089 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
1090 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -05001091 if (mGestureHelper != null) {
1092 mGestureHelper.destroy();
1093 }
Jason Monk67e6c802016-08-30 14:09:21 -04001094 mGestureHelper = defaultHelper;
1095 updateTaskSwitchHelper();
1096 }
1097
Daniel Sandler48852952011-12-01 14:34:23 -05001098 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1099 pw.println("NavigationBarView {");
1100 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -07001101 final Point size = new Point();
1102 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -05001103
Jason Monk2a6ea9c2017-01-26 11:14:51 -05001104 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -05001105 + " " + visibilityToString(getVisibility())));
1106
1107 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -07001108 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -04001109 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -05001110 + r.toShortString()
1111 + " " + visibilityToString(getWindowVisibility())
1112 + (offscreen ? " OFFSCREEN!" : ""));
1113
1114 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -08001115 getResourceName(getCurrentView().getId()),
1116 getCurrentView().getWidth(), getCurrentView().getHeight(),
1117 visibilityToString(getCurrentView().getVisibility())));
Daniel Sandler48852952011-12-01 14:34:23 -05001118
John Spurlock41c1e352013-09-16 13:57:13 -04001119 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -05001120 mDisabledFlags,
1121 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -05001122 mShowMenu ? "true" : "false"));
1123
John Spurlock56d007b2013-10-28 18:40:56 -04001124 dumpButton(pw, "back", getBackButton());
1125 dumpButton(pw, "home", getHomeButton());
1126 dumpButton(pw, "rcnt", getRecentsButton());
1127 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001128 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -05001129
Daniel Sandler48852952011-12-01 14:34:23 -05001130 pw.println(" }");
1131 }
Jim Millere898ac52012-04-06 17:10:57 -07001132
Jason Monka2081822016-01-18 14:41:03 -05001133 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -04001134 pw.print(" " + caption + ": ");
1135 if (button == null) {
1136 pw.print("null");
1137 } else {
Jason Monka2081822016-01-18 14:41:03 -05001138 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -04001139 + " alpha=" + button.getAlpha()
1140 );
John Spurlock56d007b2013-10-28 18:40:56 -04001141 }
1142 pw.println();
1143 }
1144
Jorim Jaggif4797922014-08-04 22:49:41 +02001145 public interface OnVerticalChangedListener {
1146 void onVerticalChanged(boolean isVertical);
1147 }
Jason Monka2081822016-01-18 14:41:03 -05001148
Jason Monk32e3bb52017-07-27 12:35:41 -04001149 private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> {
1150 mDockedStackExists = exists;
1151 updateRecentsIcon();
1152 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001153}