blob: 059ce929b290f207b99649491cb7653273128746 [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
John Spurlock1bbd49d2012-10-19 11:09:32 -040019import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040020import android.animation.LayoutTransition.TransitionListener;
21import android.animation.ObjectAnimator;
22import android.animation.TimeInterpolator;
23import android.animation.ValueAnimator;
Jorim Jaggi40db0292016-06-27 17:58:03 -070024import android.annotation.DrawableRes;
Jason Monk00659ba2017-03-03 10:28:45 -050025import android.app.ActivityManager;
Daniel Sandler328310c2011-09-23 15:56:52 -040026import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040027import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020028import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080029import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070030import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050031import android.graphics.Rect;
Daniel Sandler0b69b592012-01-23 21:08:36 -050032import android.os.Handler;
33import android.os.Message;
Jason Monk17488b92014-11-06 11:26:14 -050034import android.os.RemoteException;
Mike Digman7d092772018-01-11 12:10:32 -080035import android.support.annotation.ColorInt;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040036import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040037import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050038import android.util.SparseArray;
Jorim Jaggi40db0292016-06-27 17:58:03 -070039import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040040import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040041import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040042import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040043import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040044import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040045import android.view.WindowManager;
Jason Monkf1ff2092014-04-29 16:50:53 -040046import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040047import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040048
Jason Monk9a376bc2017-05-10 09:52:10 -040049import com.android.settingslib.Utils;
Jason Monkde850bb2017-02-01 19:26:30 -050050import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040051import com.android.systemui.DockedStackExistsListener;
Matthew Ng7d05e772017-11-09 14:41:07 -080052import com.android.systemui.OverviewProxyService;
53import com.android.systemui.OverviewProxyService.OverviewProxyListener;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040054import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080055import com.android.systemui.RecentsComponent;
Jason Monk67e6c802016-08-30 14:09:21 -040056import com.android.systemui.plugins.PluginListener;
57import com.android.systemui.plugins.PluginManager;
58import com.android.systemui.plugins.statusbar.phone.NavGesture;
59import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
Jorim Jaggidd98d412015-11-18 15:57:38 -080060import com.android.systemui.stackdivider.Divider;
Mike Digman7d092772018-01-11 12:10:32 -080061import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040062import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070063import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070064
John Spurlockde84f0e2013-06-12 12:41:00 -040065import java.io.FileDescriptor;
66import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040067import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040068
Jason Monk67e6c802016-08-30 14:09:21 -040069public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040070 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070071 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040072
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040073 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040074 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040075
Justin Paupore01915a12016-09-28 17:41:26 -070076 final static boolean ALTERNATE_CAR_MODE_UI = false;
77
Daniel Sandler8956dbb2011-04-22 07:55:02 -040078 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -040079 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040080 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -040081
Daniel Sandler60ee2562011-07-22 12:34:33 -040082 boolean mVertical;
Adrian Roos090b7d82016-08-02 18:36:12 -070083 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -040084
John Spurlock7edfbca2013-09-14 11:58:55 -040085 boolean mShowMenu;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080086 boolean mShowAccessibilityButton;
87 boolean mLongClickableAccessibilityButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -040088 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -040089 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040090
Jorim Jaggi40db0292016-06-27 17:58:03 -070091 private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
92 private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
93 private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
94 private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
95 private KeyButtonDrawable mRecentIcon;
96 private KeyButtonDrawable mDockedIcon;
97 private KeyButtonDrawable mImeIcon;
98 private KeyButtonDrawable mMenuIcon;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080099 private KeyButtonDrawable mAccessibilityIcon;
Mike Digman7d092772018-01-11 12:10:32 -0800100 private KeyButtonDrawable mRotateSuggestionIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800101
Jason Monk67e6c802016-08-30 14:09:21 -0400102 private GestureHelper mGestureHelper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400103 private DeadZone mDeadZone;
John Spurlock89835dd2013-08-16 15:06:51 -0400104 private final NavigationBarTransitions mBarTransitions;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800105 private final OverviewProxyService mOverviewProxyService;
Jim Millere898ac52012-04-06 17:10:57 -0700106
Daniel Sandler0b69b592012-01-23 21:08:36 -0500107 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
108 final static boolean WORKAROUND_INVALID_LAYOUT = true;
109 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
110
John Spurlock56d007b2013-10-28 18:40:56 -0400111 // performs manual animation in sync with layout transitions
112 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
113
Jorim Jaggif4797922014-08-04 22:49:41 +0200114 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700115 private boolean mLayoutTransitionsEnabled = true;
116 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700117 private boolean mUseCarModeUi = false;
118 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800119 private boolean mDockedStackExists;
Jorim Jaggif4797922014-08-04 22:49:41 +0200120
Felipe Leme15f915c2016-10-31 12:47:15 -0700121 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Winsonfde2e6a2016-03-22 16:03:10 -0700122 private Configuration mConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500123
Adrian Roosdb12b152016-07-12 15:38:55 -0700124 private NavigationBarInflaterView mNavigationInflaterView;
Jason Monk67e6c802016-08-30 14:09:21 -0400125 private RecentsComponent mRecentsComponent;
126 private Divider mDivider;
Adrian Roosdb12b152016-07-12 15:38:55 -0700127
John Spurlock56d007b2013-10-28 18:40:56 -0400128 private class NavTransitionListener implements TransitionListener {
129 private boolean mBackTransitioning;
130 private boolean mHomeAppearing;
131 private long mStartDelay;
132 private long mDuration;
133 private TimeInterpolator mInterpolator;
134
135 @Override
136 public void startTransition(LayoutTransition transition, ViewGroup container,
137 View view, int transitionType) {
138 if (view.getId() == R.id.back) {
139 mBackTransitioning = true;
140 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
141 mHomeAppearing = true;
142 mStartDelay = transition.getStartDelay(transitionType);
143 mDuration = transition.getDuration(transitionType);
144 mInterpolator = transition.getInterpolator(transitionType);
145 }
146 }
147
148 @Override
149 public void endTransition(LayoutTransition transition, ViewGroup container,
150 View view, int transitionType) {
151 if (view.getId() == R.id.back) {
152 mBackTransitioning = false;
153 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
154 mHomeAppearing = false;
155 }
156 }
157
158 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500159 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800160
John Spurlock56d007b2013-10-28 18:40:56 -0400161 // When dismissing ime during unlock, force the back button to run the same appearance
162 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500163 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
164 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400165 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800166 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400167 a.setStartDelay(mStartDelay);
168 a.setDuration(mDuration);
169 a.setInterpolator(mInterpolator);
170 a.start();
171 }
172 }
173 }
174
Jason Monkf1ff2092014-04-29 16:50:53 -0400175 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
176 @Override
177 public void onClick(View view) {
Yohei Yukawa777ef952015-11-25 20:32:24 -0800178 mContext.getSystemService(InputMethodManager.class)
Seigo Nonaka14e13912015-05-06 21:04:13 -0700179 .showInputMethodPicker(true /* showAuxiliarySubtypes */);
Jason Monkf1ff2092014-04-29 16:50:53 -0400180 }
181 };
182
Daniel Sandler0b69b592012-01-23 21:08:36 -0500183 private class H extends Handler {
184 public void handleMessage(Message m) {
185 switch (m.what) {
186 case MSG_CHECK_INVALID_LAYOUT:
187 final String how = "" + m.obj;
188 final int w = getWidth();
189 final int h = getHeight();
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800190 final int vw = getCurrentView().getWidth();
191 final int vh = getCurrentView().getHeight();
Daniel Sandler0b69b592012-01-23 21:08:36 -0500192
193 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400194 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500195 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
196 how, w, h, vw, vh));
197 if (WORKAROUND_INVALID_LAYOUT) {
198 requestLayout();
199 }
200 }
201 break;
202 }
203 }
204 }
205
Matthew Ng3c6f2f22018-01-08 14:26:40 -0800206 private final OverviewProxyListener mOverviewProxyListener = isConnected -> {
207 setSlippery(!isConnected);
208 setDisabledFlags(mDisabledFlags, true);
209 };
Matthew Ng7d05e772017-11-09 14:41:07 -0800210
John Spurlocke932e302013-08-12 10:16:29 -0400211 public NavigationBarView(Context context, AttributeSet attrs) {
212 super(context, attrs);
213
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800214 mDisplay = ((WindowManager) context.getSystemService(
John Spurlocke932e302013-08-12 10:16:29 -0400215 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400216
John Spurlocke932e302013-08-12 10:16:29 -0400217 mVertical = false;
218 mShowMenu = false;
John Spurlocke932e302013-08-12 10:16:29 -0400219
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800220 mShowAccessibilityButton = false;
221 mLongClickableAccessibilityButton = false;
222
Winsonfde2e6a2016-03-22 16:03:10 -0700223 mConfiguration = new Configuration();
224 mConfiguration.updateFrom(context.getResources().getConfiguration());
225 updateIcons(context, Configuration.EMPTY, mConfiguration);
John Spurlocke932e302013-08-12 10:16:29 -0400226
John Spurlock7edfbca2013-09-14 11:58:55 -0400227 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500228
Felipe Leme15f915c2016-10-31 12:47:15 -0700229 mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
230 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
231 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
232 mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
233 mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800234 mButtonDispatchers.put(R.id.accessibility_button,
235 new ButtonDispatcher(R.id.accessibility_button));
Mike Digman7d092772018-01-11 12:10:32 -0800236 mButtonDispatchers.put(R.id.rotate_suggestion,
237 new ButtonDispatcher(R.id.rotate_suggestion));
238
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800239 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
John Spurlocke932e302013-08-12 10:16:29 -0400240 }
241
242 public BarTransitions getBarTransitions() {
243 return mBarTransitions;
244 }
245
Jorim Jaggi40db0292016-06-27 17:58:03 -0700246 public LightBarTransitionsController getLightTransitionsController() {
247 return mBarTransitions.getLightTransitionsController();
248 }
249
Jorim Jaggidd98d412015-11-18 15:57:38 -0800250 public void setComponents(RecentsComponent recentsComponent, Divider divider) {
Jason Monk67e6c802016-08-30 14:09:21 -0400251 mRecentsComponent = recentsComponent;
252 mDivider = divider;
253 if (mGestureHelper instanceof NavigationBarGestureHelper) {
254 ((NavigationBarGestureHelper) mGestureHelper).setComponents(
255 recentsComponent, divider, this);
256 }
Jim Millere898ac52012-04-06 17:10:57 -0700257 }
258
Jorim Jaggif4797922014-08-04 22:49:41 +0200259 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
260 mOnVerticalChangedListener = onVerticalChangedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200261 notifyVerticalChangedListener(mVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200262 }
263
Jim Millere898ac52012-04-06 17:10:57 -0700264 @Override
Jim Miller960892c2012-05-23 15:50:04 -0700265 public boolean onTouchEvent(MotionEvent event) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800266 if (mGestureHelper.onTouchEvent(event)) {
Winson Chungb1f74992014-08-08 12:53:09 -0700267 return true;
268 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400269 return super.onTouchEvent(event);
Jim Miller960892c2012-05-23 15:50:04 -0700270 }
271
272 @Override
Jim Millere898ac52012-04-06 17:10:57 -0700273 public boolean onInterceptTouchEvent(MotionEvent event) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800274 return mGestureHelper.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700275 }
276
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700277 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500278 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700279 }
280
Daniel Sandler0b69b592012-01-23 21:08:36 -0500281 private H mHandler = new H();
282
John Spurlock7edfbca2013-09-14 11:58:55 -0400283 public View getCurrentView() {
284 return mCurrentView;
285 }
286
Xiaohui Chen10942302015-12-16 16:38:13 -0800287 public View[] getAllViews() {
288 return mRotatedViews;
289 }
290
Jason Monka2081822016-01-18 14:41:03 -0500291 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700292 return mButtonDispatchers.get(R.id.recent_apps);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400293 }
294
Jason Monka2081822016-01-18 14:41:03 -0500295 public ButtonDispatcher getMenuButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700296 return mButtonDispatchers.get(R.id.menu);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400297 }
298
Jason Monka2081822016-01-18 14:41:03 -0500299 public ButtonDispatcher getBackButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700300 return mButtonDispatchers.get(R.id.back);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400301 }
302
Jason Monka2081822016-01-18 14:41:03 -0500303 public ButtonDispatcher getHomeButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700304 return mButtonDispatchers.get(R.id.home);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400305 }
306
Jason Monka2081822016-01-18 14:41:03 -0500307 public ButtonDispatcher getImeSwitchButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700308 return mButtonDispatchers.get(R.id.ime_switcher);
Jason Monkf1ff2092014-04-29 16:50:53 -0400309 }
310
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800311 public ButtonDispatcher getAccessibilityButton() {
312 return mButtonDispatchers.get(R.id.accessibility_button);
313 }
314
Mike Digman7d092772018-01-11 12:10:32 -0800315 public ButtonDispatcher getRotateSuggestionButton() {
316 return mButtonDispatchers.get(R.id.rotate_suggestion);
317 }
318
Jorim Jaggi40db0292016-06-27 17:58:03 -0700319 public SparseArray<ButtonDispatcher> getButtonDispatchers() {
320 return mButtonDispatchers;
321 }
322
Winsonfde2e6a2016-03-22 16:03:10 -0700323 private void updateCarModeIcons(Context ctx) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700324 mBackCarModeIcon = getDrawable(ctx,
325 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800326 mBackLandCarModeIcon = mBackCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700327 mBackAltCarModeIcon = getDrawable(ctx,
328 R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800329 mBackAltLandCarModeIcon = mBackAltCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700330 mHomeCarModeIcon = getDrawable(ctx,
331 R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800332 }
333
Winsonfde2e6a2016-03-22 16:03:10 -0700334 private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700335 if (oldConfig.orientation != newConfig.orientation
336 || oldConfig.densityDpi != newConfig.densityDpi) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700337 mDockedIcon = getDrawable(ctx,
338 R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700339 }
Jason Monk1f785d42017-07-25 15:46:33 -0400340 if (oldConfig.densityDpi != newConfig.densityDpi
341 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700342 mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700343 mBackLandIcon = mBackIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700344 mBackAltIcon = getDrawable(ctx,
345 R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700346 mBackAltLandIcon = mBackAltIcon;
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800347
Jorim Jaggi40db0292016-06-27 17:58:03 -0700348 mHomeDefaultIcon = getDrawable(ctx,
349 R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
350 mRecentIcon = getDrawable(ctx,
351 R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
352 mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800353 mAccessibilityIcon = getDrawable(ctx, R.drawable.ic_sysbar_accessibility_button,
354 R.drawable.ic_sysbar_accessibility_button_dark);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700355
Jason Monk9a376bc2017-05-10 09:52:10 -0400356 int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
357 int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
358 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
359 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700360 mImeIcon = getDrawable(darkContext, lightContext,
361 R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700362
Mike Digman7d092772018-01-11 12:10:32 -0800363 int lightColor = Utils.getColorAttr(lightContext, R.attr.singleToneColor);
364 int darkColor = Utils.getColorAttr(darkContext, R.attr.singleToneColor);
365 mRotateSuggestionIcon = getDrawable(ctx, R.drawable.ic_sysbar_rotate_button,
366 lightColor, darkColor);
367
Justin Paupore01915a12016-09-28 17:41:26 -0700368 if (ALTERNATE_CAR_MODE_UI) {
369 updateCarModeIcons(ctx);
370 }
Winsonfde2e6a2016-03-22 16:03:10 -0700371 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700372 }
373
Jorim Jaggi40db0292016-06-27 17:58:03 -0700374 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
375 @DrawableRes int darkIcon) {
376 return getDrawable(ctx, ctx, lightIcon, darkIcon);
377 }
378
379 private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
380 @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
381 return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
382 darkContext.getDrawable(darkIcon));
383 }
384
Mike Digman7d092772018-01-11 12:10:32 -0800385 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
386 @ColorInt int lightColor, @ColorInt int darkColor) {
387 return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
388 }
389
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700390 @Override
391 public void setLayoutDirection(int layoutDirection) {
Winsonfde2e6a2016-03-22 16:03:10 -0700392 // Reload all the icons
393 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700394
395 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400396 }
397
Siarhei Vishniakoud002a0a2017-06-05 22:44:37 +0100398 public void notifyScreenOn() {
John Spurlock1bbd49d2012-10-19 11:09:32 -0400399 setDisabledFlags(mDisabledFlags, true);
400 }
401
Daniel Sandler328310c2011-09-23 15:56:52 -0400402 public void setNavigationIconHints(int hints) {
403 setNavigationIconHints(hints, false);
404 }
405
Jorim Jaggi40db0292016-06-27 17:58:03 -0700406 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800407 return landscape
408 ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
409 : carMode ? mBackAltCarModeIcon : mBackAltIcon;
410 }
411
Jorim Jaggi40db0292016-06-27 17:58:03 -0700412 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800413 return landscape
414 ? carMode ? mBackLandCarModeIcon : mBackLandIcon
415 : carMode ? mBackCarModeIcon : mBackIcon;
416 }
417
Daniel Sandler328310c2011-09-23 15:56:52 -0400418 public void setNavigationIconHints(int hints, boolean force) {
419 if (!force && hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400420 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
421 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
422 mTransitionListener.onBackAltCleared();
423 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400424 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500425 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400426 "Navigation icon hints = " + hints,
427 500).show();
428 }
429
430 mNavigationIconHints = hints;
431
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800432 // We have to replace or restore the back and home button icons when exiting or entering
433 // carmode, respectively. Recents are not available in CarMode in nav bar so change
434 // to recent icon is not required.
Jorim Jaggi40db0292016-06-27 17:58:03 -0700435 KeyButtonDrawable backIcon = (backAlt)
Justin Paupore01915a12016-09-28 17:41:26 -0700436 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
437 : getBackIcon(mUseCarModeUi, mVertical);
John Spurlocka9b46822012-11-02 10:42:39 -0400438
Jason Monka2081822016-01-18 14:41:03 -0500439 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800440
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800441 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800442
Justin Paupore01915a12016-09-28 17:41:26 -0700443 if (mUseCarModeUi) {
Jason Monka2081822016-01-18 14:41:03 -0500444 getHomeButton().setImageDrawable(mHomeCarModeIcon);
445 } else {
446 getHomeButton().setImageDrawable(mHomeDefaultIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800447 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700448
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700449 // The Accessibility button always overrides the appearance of the IME switcher
450 final boolean showImeButton =
451 !mShowAccessibilityButton && ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN)
452 != 0);
Jason Monka2081822016-01-18 14:41:03 -0500453 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700454 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800455
Jason Monkf1ff2092014-04-29 16:50:53 -0400456 // Update menu button in case the IME state has changed.
457 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700458 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400459
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800460 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
461 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
462
Mike Digman7d092772018-01-11 12:10:32 -0800463 getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
464
John Spurlocka9b46822012-11-02 10:42:39 -0400465 setDisabledFlags(mDisabledFlags, true);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700466
467 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400468 }
469
Daniel Sandler6da2b762011-09-14 16:04:59 -0400470 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400471 setDisabledFlags(disabledFlags, false);
472 }
473
474 public void setDisabledFlags(int disabledFlags, boolean force) {
475 if (!force && mDisabledFlags == disabledFlags) return;
476
477 mDisabledFlags = disabledFlags;
478
Daniel Sandlerdba93562011-10-06 16:39:58 -0400479 final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700480
Justin Paupore01915a12016-09-28 17:41:26 -0700481 // Always disable recents when alternate car mode UI is active.
482 boolean disableRecent = mUseCarModeUi
Charles Hee57ff812017-10-26 10:01:35 +0100483 || ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
484
485 boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
John Spurlocka9b46822012-11-02 10:42:39 -0400486 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400487
Charles Hee57ff812017-10-26 10:01:35 +0100488 if ((disableRecent || disableBack) && inScreenPinning()) {
489 // Don't hide back and recents buttons when in screen pinning mode, as they are used for
490 // exiting.
491 disableBack = false;
492 disableRecent = false;
493 }
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800494 if (mOverviewProxyService.getProxy() != null) {
495 // When overview is connected to the launcher service, disable the recents button
496 disableRecent = true;
497 }
Charles Hee57ff812017-10-26 10:01:35 +0100498
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800499 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400500 if (navButtons != null) {
501 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400502 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400503 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
504 lt.addTransitionListener(mTransitionListener);
505 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400506 }
507 }
508
Jason Monka2081822016-01-18 14:41:03 -0500509 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500510 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500511 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400512 }
513
Charles Hee57ff812017-10-26 10:01:35 +0100514 private boolean inScreenPinning() {
Jason Monk17488b92014-11-06 11:26:14 -0500515 try {
Charles Hee57ff812017-10-26 10:01:35 +0100516 return ActivityManager.getService().getLockTaskModeState()
517 == ActivityManager.LOCK_TASK_MODE_PINNED;
Jason Monk17488b92014-11-06 11:26:14 -0500518 } catch (RemoteException e) {
519 return false;
520 }
521 }
522
Jorim Jaggi37c11802015-08-18 20:27:54 -0700523 public void setLayoutTransitionsEnabled(boolean enabled) {
524 mLayoutTransitionsEnabled = enabled;
525 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700526 }
527
Jorim Jaggi37c11802015-08-18 20:27:54 -0700528 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
529 setUseFadingAnimations(wakeAndUnlocking);
530 mWakeAndUnlocking = wakeAndUnlocking;
531 updateLayoutTransitionsEnabled();
532 }
533
534 private void updateLayoutTransitionsEnabled() {
535 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800536 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700537 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400538 if (lt != null) {
539 if (enabled) {
540 lt.enableTransitionType(LayoutTransition.APPEARING);
541 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
542 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
543 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
544 } else {
545 lt.disableTransitionType(LayoutTransition.APPEARING);
546 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
547 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
548 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
549 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700550 }
551 }
552
553 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500554 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
555 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700556 if (lp != null) {
557 boolean old = lp.windowAnimations != 0;
558 if (!old && useFadingAnimations) {
559 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
560 } else if (old && !useFadingAnimations) {
561 lp.windowAnimations = 0;
562 } else {
563 return;
564 }
565 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500566 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700567 }
568 }
569
Matthew Ng7d05e772017-11-09 14:41:07 -0800570 private void setSlippery(boolean slippery) {
571 boolean changed = false;
572 final ViewGroup navbarView = ((ViewGroup) getParent());
573 final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
574 .getLayoutParams();
575 if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
576 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
577 changed = true;
578 } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) {
579 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
580 changed = true;
581 }
582 if (changed) {
583 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
584 wm.updateViewLayout(navbarView, lp);
585 }
586 }
587
Daniel Sandler56598cd2011-09-15 16:02:56 -0400588 public void setMenuVisibility(final boolean show) {
589 setMenuVisibility(show, false);
590 }
591
592 public void setMenuVisibility(final boolean show, final boolean force) {
593 if (!force && mShowMenu == show) return;
594
595 mShowMenu = show;
596
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800597 // Only show Menu if IME switcher and Accessibility button not shown.
598 final boolean shouldShow = mShowMenu && !mShowAccessibilityButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400599 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800600
Jason Monka2081822016-01-18 14:41:03 -0500601 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400602 }
603
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800604 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
605 mShowAccessibilityButton = visible;
606 mLongClickableAccessibilityButton = longClickable;
607 if (visible) {
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700608 // Accessibility button overrides Menu and IME switcher buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800609 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700610 getImeSwitchButton().setVisibility(View.INVISIBLE);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800611 }
612
613 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
614 getAccessibilityButton().setLongClickable(longClickable);
615 }
616
Jim Miller960892c2012-05-23 15:50:04 -0700617 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400618 public void onFinishInflate() {
Adrian Roosdb12b152016-07-12 15:38:55 -0700619 mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
620 R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700621 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500622
623 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200624
Jason Monk32e3bb52017-07-27 12:35:41 -0400625 DockedStackExistsListener.register(mDockedListener);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700626 updateRotatedViews();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100627 }
628
Matthew Nga8f24262017-12-19 11:54:24 -0800629 public void onDarkIntensityChange(float intensity) {
630 if (mGestureHelper != null) {
631 mGestureHelper.onDarkIntensityChange(intensity);
632 }
633 }
634
635 @Override
636 protected void onDraw(Canvas canvas) {
637 mGestureHelper.onDraw(canvas);
638 super.onDraw(canvas);
639 }
640
641 @Override
642 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
643 super.onLayout(changed, left, top, right, bottom);
644 mGestureHelper.onLayout(changed, left, top, right, bottom);
645 }
646
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700647 private void updateRotatedViews() {
Jason Monk9a6552d2016-05-20 11:21:59 -0400648 mRotatedViews[Surface.ROTATION_0] =
649 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
650 mRotatedViews[Surface.ROTATION_270] =
651 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
652
Jason Monk199a2d02017-07-28 11:08:27 -0400653 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400654 }
655
Adrian Roosa98b32c2016-08-11 10:41:08 -0700656 public boolean needsReorient(int rotation) {
657 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700658 }
659
Jason Monk199a2d02017-07-28 11:08:27 -0400660 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400661 final int rot = mDisplay.getRotation();
662 for (int i=0; i<4; i++) {
663 mRotatedViews[i].setVisibility(View.GONE);
664 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400665 mCurrentView = mRotatedViews[rot];
666 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700667 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Felipe Leme15f915c2016-10-31 12:47:15 -0700668 for (int i = 0; i < mButtonDispatchers.size(); i++) {
669 mButtonDispatchers.valueAt(i).setCurrentView(mCurrentView);
Jason Monka2081822016-01-18 14:41:03 -0500670 }
Jorim Jaggi37c11802015-08-18 20:27:54 -0700671 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700672 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400673 }
674
675 private void updateRecentsIcon() {
676 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700677 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400678 }
679
680 public boolean isVertical() {
681 return mVertical;
682 }
683
684 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400685 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400686
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400687 mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700688
689 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Jorim Jaggi7aaa3d72016-11-28 14:03:11 +0100690 mDeadZone.setDisplayRotation(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400691
Daniel Sandler6da2b762011-09-14 16:04:59 -0400692 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700693 mBarTransitions.init();
Daniel Sandler6da2b762011-09-14 16:04:59 -0400694 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400695 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400696
Daniel Sandler60ee2562011-07-22 12:34:33 -0400697 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700698 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400699 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800700
Selim Cinek92d892c2014-09-11 15:11:00 +0200701 updateTaskSwitchHelper();
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800702 setNavigationIconHints(mNavigationIconHints, true);
Xiaohui Chen9efa5de2016-11-22 10:34:38 -0800703
Xiaohui Chen40e978e2016-11-29 15:10:04 -0800704 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400705 }
Daniel Sandler48852952011-12-01 14:34:23 -0500706
Selim Cinek92d892c2014-09-11 15:11:00 +0200707 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -0500708 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +0200709 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800710 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +0200711 }
712
Daniel Sandler0b69b592012-01-23 21:08:36 -0500713 @Override
714 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -0400715 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500716 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400717
718 final boolean newVertical = w > 0 && h > w;
719 if (newVertical != mVertical) {
720 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -0400721 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400722 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +0200723 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -0400724 }
725
Daniel Sandler0b69b592012-01-23 21:08:36 -0500726 postCheckForInvalidLayout("sizeChanged");
727 super.onSizeChanged(w, h, oldw, oldh);
728 }
729
Selim Cinek92d892c2014-09-11 15:11:00 +0200730 private void notifyVerticalChangedListener(boolean newVertical) {
731 if (mOnVerticalChangedListener != null) {
732 mOnVerticalChangedListener.onVerticalChanged(newVertical);
733 }
734 }
735
Selim Cinek17a327a2014-08-25 15:03:48 +0200736 @Override
737 protected void onConfigurationChanged(Configuration newConfig) {
738 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800739 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +0200740 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -0700741 updateIcons(getContext(), mConfiguration, newConfig);
742 updateRecentsIcon();
Jason Monk1f785d42017-07-25 15:46:33 -0400743 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
744 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700745 // If car mode or density changes, we need to reset the icons.
746 setNavigationIconHints(mNavigationIconHints, true);
747 }
Winsonfde2e6a2016-03-22 16:03:10 -0700748 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800749 }
750
751 /**
752 * If the configuration changed, update the carmode and return that it was updated.
753 */
754 private boolean updateCarMode(Configuration newConfig) {
755 boolean uiCarModeChanged = false;
756 if (newConfig != null) {
757 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -0700758 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
759
760 if (isCarMode != mInCarMode) {
761 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -0700762 if (ALTERNATE_CAR_MODE_UI) {
763 mUseCarModeUi = isCarMode;
764 uiCarModeChanged = true;
765 } else {
766 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
767 mUseCarModeUi = false;
768 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800769 }
770 }
771 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +0200772 }
773
Daniel Sandler0b69b592012-01-23 21:08:36 -0500774 /*
775 @Override
776 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -0400777 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -0400778 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -0500779 changed?"changed":"notchanged", left, top, right, bottom));
780 super.onLayout(changed, left, top, right, bottom);
781 }
782
783 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
784 // fails, any touch on the display will fix the layout.
785 @Override
786 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -0400787 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -0500788 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
789 postCheckForInvalidLayout("touch");
790 }
791 return super.onInterceptTouchEvent(ev);
792 }
793 */
John Spurlock209bede2013-07-17 12:23:27 -0400794
Daniel Sandler0b69b592012-01-23 21:08:36 -0500795
Daniel Sandler48852952011-12-01 14:34:23 -0500796 private String getResourceName(int resId) {
797 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -0500798 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -0500799 try {
800 return res.getResourceName(resId);
801 } catch (android.content.res.Resources.NotFoundException ex) {
802 return "(unknown)";
803 }
804 } else {
805 return "(null)";
806 }
807 }
808
Daniel Sandler0b69b592012-01-23 21:08:36 -0500809 private void postCheckForInvalidLayout(final String how) {
810 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
811 }
812
Daniel Sandler48852952011-12-01 14:34:23 -0500813 private static String visibilityToString(int vis) {
814 switch (vis) {
815 case View.INVISIBLE:
816 return "INVISIBLE";
817 case View.GONE:
818 return "GONE";
819 default:
820 return "VISIBLE";
821 }
822 }
823
Jason Monk67e6c802016-08-30 14:09:21 -0400824 @Override
825 protected void onAttachedToWindow() {
826 super.onAttachedToWindow();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700827 reorient();
Jason Monkde850bb2017-02-01 19:26:30 -0500828 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -0800829 Dependency.get(PluginManager.class).addPluginListener(this,
830 NavGesture.class, false /* Only one */);
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800831 mOverviewProxyService.addCallback(mOverviewProxyListener);
Jason Monk67e6c802016-08-30 14:09:21 -0400832 }
833
834 @Override
835 protected void onDetachedFromWindow() {
836 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -0500837 Dependency.get(PluginManager.class).removePluginListener(this);
838 if (mGestureHelper != null) {
839 mGestureHelper.destroy();
840 }
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800841 mOverviewProxyService.removeCallback(mOverviewProxyListener);
Jason Monk67e6c802016-08-30 14:09:21 -0400842 }
843
844 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -0500845 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -0400846 mGestureHelper = plugin.getGestureHelper();
847 updateTaskSwitchHelper();
848 }
849
850 @Override
851 public void onPluginDisconnected(NavGesture plugin) {
852 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
853 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -0500854 if (mGestureHelper != null) {
855 mGestureHelper.destroy();
856 }
Jason Monk67e6c802016-08-30 14:09:21 -0400857 mGestureHelper = defaultHelper;
858 updateTaskSwitchHelper();
859 }
860
Daniel Sandler48852952011-12-01 14:34:23 -0500861 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
862 pw.println("NavigationBarView {");
863 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -0700864 final Point size = new Point();
865 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -0500866
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500867 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -0500868 + " " + visibilityToString(getVisibility())));
869
870 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -0700871 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -0400872 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -0500873 + r.toShortString()
874 + " " + visibilityToString(getWindowVisibility())
875 + (offscreen ? " OFFSCREEN!" : ""));
876
877 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -0800878 getResourceName(getCurrentView().getId()),
879 getCurrentView().getWidth(), getCurrentView().getHeight(),
880 visibilityToString(getCurrentView().getVisibility())));
Daniel Sandler48852952011-12-01 14:34:23 -0500881
John Spurlock41c1e352013-09-16 13:57:13 -0400882 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -0500883 mDisabledFlags,
884 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -0500885 mShowMenu ? "true" : "false"));
886
John Spurlock56d007b2013-10-28 18:40:56 -0400887 dumpButton(pw, "back", getBackButton());
888 dumpButton(pw, "home", getHomeButton());
889 dumpButton(pw, "rcnt", getRecentsButton());
890 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800891 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -0500892
Daniel Sandler48852952011-12-01 14:34:23 -0500893 pw.println(" }");
894 }
Jim Millere898ac52012-04-06 17:10:57 -0700895
Jason Monka2081822016-01-18 14:41:03 -0500896 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -0400897 pw.print(" " + caption + ": ");
898 if (button == null) {
899 pw.print("null");
900 } else {
Jason Monka2081822016-01-18 14:41:03 -0500901 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -0400902 + " alpha=" + button.getAlpha()
903 );
John Spurlock56d007b2013-10-28 18:40:56 -0400904 }
905 pw.println();
906 }
907
Jorim Jaggif4797922014-08-04 22:49:41 +0200908 public interface OnVerticalChangedListener {
909 void onVerticalChanged(boolean isVertical);
910 }
Jason Monka2081822016-01-18 14:41:03 -0500911
Jason Monk32e3bb52017-07-27 12:35:41 -0400912 private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> {
913 mDockedStackExists = exists;
914 updateRecentsIcon();
915 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400916}