blob: 8d9d4610f1d437a78590727aa52b9260b292ece6 [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;
Jeff Browna8b9def2012-07-23 14:22:49 -070029import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050030import android.graphics.Rect;
Daniel Sandler0b69b592012-01-23 21:08:36 -050031import android.os.Handler;
32import android.os.Message;
Jason Monk17488b92014-11-06 11:26:14 -050033import android.os.RemoteException;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040034import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040035import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050036import android.util.SparseArray;
Jorim Jaggi40db0292016-06-27 17:58:03 -070037import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040038import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040039import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040040import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040041import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040042import android.view.ViewGroup;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040043import android.view.WindowManager;
Jason Monkf1ff2092014-04-29 16:50:53 -040044import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040045import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040046
Jason Monk9a376bc2017-05-10 09:52:10 -040047import com.android.settingslib.Utils;
Jason Monkde850bb2017-02-01 19:26:30 -050048import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040049import com.android.systemui.DockedStackExistsListener;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040050import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080051import com.android.systemui.RecentsComponent;
Jason Monk67e6c802016-08-30 14:09:21 -040052import com.android.systemui.plugins.PluginListener;
53import com.android.systemui.plugins.PluginManager;
54import com.android.systemui.plugins.statusbar.phone.NavGesture;
55import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
Jorim Jaggidd98d412015-11-18 15:57:38 -080056import com.android.systemui.stackdivider.Divider;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040057import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070058import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070059
John Spurlockde84f0e2013-06-12 12:41:00 -040060import java.io.FileDescriptor;
61import java.io.PrintWriter;
62
Jason Monk67e6c802016-08-30 14:09:21 -040063public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040064 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070065 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040066
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040067 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040068 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040069
Justin Paupore01915a12016-09-28 17:41:26 -070070 final static boolean ALTERNATE_CAR_MODE_UI = false;
71
Daniel Sandler8956dbb2011-04-22 07:55:02 -040072 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -040073 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040074 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -040075
Daniel Sandler60ee2562011-07-22 12:34:33 -040076 boolean mVertical;
John Spurlock1bbd49d2012-10-19 11:09:32 -040077 boolean mScreenOn;
Adrian Roos090b7d82016-08-02 18:36:12 -070078 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -040079
John Spurlock7edfbca2013-09-14 11:58:55 -040080 boolean mShowMenu;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080081 boolean mShowAccessibilityButton;
82 boolean mLongClickableAccessibilityButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -040083 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -040084 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040085
Jorim Jaggi40db0292016-06-27 17:58:03 -070086 private KeyButtonDrawable mBackIcon, mBackLandIcon, mBackAltIcon, mBackAltLandIcon;
87 private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
88 private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
89 private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
90 private KeyButtonDrawable mRecentIcon;
91 private KeyButtonDrawable mDockedIcon;
92 private KeyButtonDrawable mImeIcon;
93 private KeyButtonDrawable mMenuIcon;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -080094 private KeyButtonDrawable mAccessibilityIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -080095
Jason Monk67e6c802016-08-30 14:09:21 -040096 private GestureHelper mGestureHelper;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040097 private DeadZone mDeadZone;
John Spurlock89835dd2013-08-16 15:06:51 -040098 private final NavigationBarTransitions mBarTransitions;
Jim Millere898ac52012-04-06 17:10:57 -070099
Daniel Sandler0b69b592012-01-23 21:08:36 -0500100 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
101 final static boolean WORKAROUND_INVALID_LAYOUT = true;
102 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
103
John Spurlock56d007b2013-10-28 18:40:56 -0400104 // performs manual animation in sync with layout transitions
105 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
106
Jorim Jaggif4797922014-08-04 22:49:41 +0200107 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700108 private boolean mLayoutTransitionsEnabled = true;
109 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700110 private boolean mUseCarModeUi = false;
111 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800112 private boolean mDockedStackExists;
Jorim Jaggif4797922014-08-04 22:49:41 +0200113
Felipe Leme15f915c2016-10-31 12:47:15 -0700114 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Winsonfde2e6a2016-03-22 16:03:10 -0700115 private Configuration mConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500116
Adrian Roosdb12b152016-07-12 15:38:55 -0700117 private NavigationBarInflaterView mNavigationInflaterView;
Jason Monk67e6c802016-08-30 14:09:21 -0400118 private RecentsComponent mRecentsComponent;
119 private Divider mDivider;
Adrian Roosdb12b152016-07-12 15:38:55 -0700120
John Spurlock56d007b2013-10-28 18:40:56 -0400121 private class NavTransitionListener implements TransitionListener {
122 private boolean mBackTransitioning;
123 private boolean mHomeAppearing;
124 private long mStartDelay;
125 private long mDuration;
126 private TimeInterpolator mInterpolator;
127
128 @Override
129 public void startTransition(LayoutTransition transition, ViewGroup container,
130 View view, int transitionType) {
131 if (view.getId() == R.id.back) {
132 mBackTransitioning = true;
133 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
134 mHomeAppearing = true;
135 mStartDelay = transition.getStartDelay(transitionType);
136 mDuration = transition.getDuration(transitionType);
137 mInterpolator = transition.getInterpolator(transitionType);
138 }
139 }
140
141 @Override
142 public void endTransition(LayoutTransition transition, ViewGroup container,
143 View view, int transitionType) {
144 if (view.getId() == R.id.back) {
145 mBackTransitioning = false;
146 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
147 mHomeAppearing = false;
148 }
149 }
150
151 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500152 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800153
John Spurlock56d007b2013-10-28 18:40:56 -0400154 // When dismissing ime during unlock, force the back button to run the same appearance
155 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500156 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
157 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400158 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800159 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400160 a.setStartDelay(mStartDelay);
161 a.setDuration(mDuration);
162 a.setInterpolator(mInterpolator);
163 a.start();
164 }
165 }
166 }
167
Jason Monkf1ff2092014-04-29 16:50:53 -0400168 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
169 @Override
170 public void onClick(View view) {
Yohei Yukawa777ef952015-11-25 20:32:24 -0800171 mContext.getSystemService(InputMethodManager.class)
Seigo Nonaka14e13912015-05-06 21:04:13 -0700172 .showInputMethodPicker(true /* showAuxiliarySubtypes */);
Jason Monkf1ff2092014-04-29 16:50:53 -0400173 }
174 };
175
Daniel Sandler0b69b592012-01-23 21:08:36 -0500176 private class H extends Handler {
177 public void handleMessage(Message m) {
178 switch (m.what) {
179 case MSG_CHECK_INVALID_LAYOUT:
180 final String how = "" + m.obj;
181 final int w = getWidth();
182 final int h = getHeight();
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800183 final int vw = getCurrentView().getWidth();
184 final int vh = getCurrentView().getHeight();
Daniel Sandler0b69b592012-01-23 21:08:36 -0500185
186 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400187 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500188 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
189 how, w, h, vw, vh));
190 if (WORKAROUND_INVALID_LAYOUT) {
191 requestLayout();
192 }
193 }
194 break;
195 }
196 }
197 }
198
John Spurlocke932e302013-08-12 10:16:29 -0400199 public NavigationBarView(Context context, AttributeSet attrs) {
200 super(context, attrs);
201
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800202 mDisplay = ((WindowManager) context.getSystemService(
John Spurlocke932e302013-08-12 10:16:29 -0400203 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400204
John Spurlocke932e302013-08-12 10:16:29 -0400205 mVertical = false;
206 mShowMenu = false;
John Spurlocke932e302013-08-12 10:16:29 -0400207
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800208 mShowAccessibilityButton = false;
209 mLongClickableAccessibilityButton = false;
210
Winsonfde2e6a2016-03-22 16:03:10 -0700211 mConfiguration = new Configuration();
212 mConfiguration.updateFrom(context.getResources().getConfiguration());
213 updateIcons(context, Configuration.EMPTY, mConfiguration);
John Spurlocke932e302013-08-12 10:16:29 -0400214
John Spurlock7edfbca2013-09-14 11:58:55 -0400215 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500216
Felipe Leme15f915c2016-10-31 12:47:15 -0700217 mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
218 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
219 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
220 mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
221 mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800222 mButtonDispatchers.put(R.id.accessibility_button,
223 new ButtonDispatcher(R.id.accessibility_button));
John Spurlocke932e302013-08-12 10:16:29 -0400224 }
225
226 public BarTransitions getBarTransitions() {
227 return mBarTransitions;
228 }
229
Jorim Jaggi40db0292016-06-27 17:58:03 -0700230 public LightBarTransitionsController getLightTransitionsController() {
231 return mBarTransitions.getLightTransitionsController();
232 }
233
Jorim Jaggidd98d412015-11-18 15:57:38 -0800234 public void setComponents(RecentsComponent recentsComponent, Divider divider) {
Jason Monk67e6c802016-08-30 14:09:21 -0400235 mRecentsComponent = recentsComponent;
236 mDivider = divider;
237 if (mGestureHelper instanceof NavigationBarGestureHelper) {
238 ((NavigationBarGestureHelper) mGestureHelper).setComponents(
239 recentsComponent, divider, this);
240 }
Jim Millere898ac52012-04-06 17:10:57 -0700241 }
242
Jorim Jaggif4797922014-08-04 22:49:41 +0200243 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
244 mOnVerticalChangedListener = onVerticalChangedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200245 notifyVerticalChangedListener(mVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200246 }
247
Jim Millere898ac52012-04-06 17:10:57 -0700248 @Override
Jim Miller960892c2012-05-23 15:50:04 -0700249 public boolean onTouchEvent(MotionEvent event) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800250 if (mGestureHelper.onTouchEvent(event)) {
Winson Chungb1f74992014-08-08 12:53:09 -0700251 return true;
252 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400253 if (mDeadZone != null && event.getAction() == MotionEvent.ACTION_OUTSIDE) {
254 mDeadZone.poke(event);
Jim Miller960892c2012-05-23 15:50:04 -0700255 }
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400256 return super.onTouchEvent(event);
Jim Miller960892c2012-05-23 15:50:04 -0700257 }
258
259 @Override
Jim Millere898ac52012-04-06 17:10:57 -0700260 public boolean onInterceptTouchEvent(MotionEvent event) {
Jorim Jaggidd98d412015-11-18 15:57:38 -0800261 return mGestureHelper.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700262 }
263
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700264 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500265 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700266 }
267
Daniel Sandler0b69b592012-01-23 21:08:36 -0500268 private H mHandler = new H();
269
John Spurlock7edfbca2013-09-14 11:58:55 -0400270 public View getCurrentView() {
271 return mCurrentView;
272 }
273
Xiaohui Chen10942302015-12-16 16:38:13 -0800274 public View[] getAllViews() {
275 return mRotatedViews;
276 }
277
Jason Monka2081822016-01-18 14:41:03 -0500278 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700279 return mButtonDispatchers.get(R.id.recent_apps);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400280 }
281
Jason Monka2081822016-01-18 14:41:03 -0500282 public ButtonDispatcher getMenuButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700283 return mButtonDispatchers.get(R.id.menu);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400284 }
285
Jason Monka2081822016-01-18 14:41:03 -0500286 public ButtonDispatcher getBackButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700287 return mButtonDispatchers.get(R.id.back);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400288 }
289
Jason Monka2081822016-01-18 14:41:03 -0500290 public ButtonDispatcher getHomeButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700291 return mButtonDispatchers.get(R.id.home);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400292 }
293
Jason Monka2081822016-01-18 14:41:03 -0500294 public ButtonDispatcher getImeSwitchButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700295 return mButtonDispatchers.get(R.id.ime_switcher);
Jason Monkf1ff2092014-04-29 16:50:53 -0400296 }
297
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800298 public ButtonDispatcher getAccessibilityButton() {
299 return mButtonDispatchers.get(R.id.accessibility_button);
300 }
301
Jorim Jaggi40db0292016-06-27 17:58:03 -0700302 public SparseArray<ButtonDispatcher> getButtonDispatchers() {
303 return mButtonDispatchers;
304 }
305
Winsonfde2e6a2016-03-22 16:03:10 -0700306 private void updateCarModeIcons(Context ctx) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700307 mBackCarModeIcon = getDrawable(ctx,
308 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800309 mBackLandCarModeIcon = mBackCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700310 mBackAltCarModeIcon = getDrawable(ctx,
311 R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800312 mBackAltLandCarModeIcon = mBackAltCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700313 mHomeCarModeIcon = getDrawable(ctx,
314 R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800315 }
316
Winsonfde2e6a2016-03-22 16:03:10 -0700317 private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700318 if (oldConfig.orientation != newConfig.orientation
319 || oldConfig.densityDpi != newConfig.densityDpi) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700320 mDockedIcon = getDrawable(ctx,
321 R.drawable.ic_sysbar_docked, R.drawable.ic_sysbar_docked_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700322 }
323 if (oldConfig.densityDpi != newConfig.densityDpi) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700324 mBackIcon = getDrawable(ctx, R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700325 mBackLandIcon = mBackIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700326 mBackAltIcon = getDrawable(ctx,
327 R.drawable.ic_sysbar_back_ime, R.drawable.ic_sysbar_back_ime_dark);
Winsonfde2e6a2016-03-22 16:03:10 -0700328 mBackAltLandIcon = mBackAltIcon;
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800329
Jorim Jaggi40db0292016-06-27 17:58:03 -0700330 mHomeDefaultIcon = getDrawable(ctx,
331 R.drawable.ic_sysbar_home, R.drawable.ic_sysbar_home_dark);
332 mRecentIcon = getDrawable(ctx,
333 R.drawable.ic_sysbar_recent, R.drawable.ic_sysbar_recent_dark);
334 mMenuIcon = getDrawable(ctx, R.drawable.ic_sysbar_menu, R.drawable.ic_sysbar_menu_dark);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800335 mAccessibilityIcon = getDrawable(ctx, R.drawable.ic_sysbar_accessibility_button,
336 R.drawable.ic_sysbar_accessibility_button_dark);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700337
Jason Monk9a376bc2017-05-10 09:52:10 -0400338 int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
339 int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
340 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
341 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700342 mImeIcon = getDrawable(darkContext, lightContext,
343 R.drawable.ic_ime_switcher_default, R.drawable.ic_ime_switcher_default);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700344
Justin Paupore01915a12016-09-28 17:41:26 -0700345 if (ALTERNATE_CAR_MODE_UI) {
346 updateCarModeIcons(ctx);
347 }
Winsonfde2e6a2016-03-22 16:03:10 -0700348 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700349 }
350
Jorim Jaggi40db0292016-06-27 17:58:03 -0700351 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
352 @DrawableRes int darkIcon) {
353 return getDrawable(ctx, ctx, lightIcon, darkIcon);
354 }
355
356 private KeyButtonDrawable getDrawable(Context darkContext, Context lightContext,
357 @DrawableRes int lightIcon, @DrawableRes int darkIcon) {
358 return KeyButtonDrawable.create(lightContext.getDrawable(lightIcon),
359 darkContext.getDrawable(darkIcon));
360 }
361
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700362 @Override
363 public void setLayoutDirection(int layoutDirection) {
Winsonfde2e6a2016-03-22 16:03:10 -0700364 // Reload all the icons
365 updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700366
367 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400368 }
369
John Spurlock1bbd49d2012-10-19 11:09:32 -0400370 public void notifyScreenOn(boolean screenOn) {
371 mScreenOn = screenOn;
372 setDisabledFlags(mDisabledFlags, true);
373 }
374
Daniel Sandler328310c2011-09-23 15:56:52 -0400375 public void setNavigationIconHints(int hints) {
376 setNavigationIconHints(hints, false);
377 }
378
Jorim Jaggi40db0292016-06-27 17:58:03 -0700379 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800380 return landscape
381 ? carMode ? mBackAltLandCarModeIcon : mBackAltLandIcon
382 : carMode ? mBackAltCarModeIcon : mBackAltIcon;
383 }
384
Jorim Jaggi40db0292016-06-27 17:58:03 -0700385 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800386 return landscape
387 ? carMode ? mBackLandCarModeIcon : mBackLandIcon
388 : carMode ? mBackCarModeIcon : mBackIcon;
389 }
390
Daniel Sandler328310c2011-09-23 15:56:52 -0400391 public void setNavigationIconHints(int hints, boolean force) {
392 if (!force && hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400393 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
394 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
395 mTransitionListener.onBackAltCleared();
396 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400397 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500398 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400399 "Navigation icon hints = " + hints,
400 500).show();
401 }
402
403 mNavigationIconHints = hints;
404
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800405 // We have to replace or restore the back and home button icons when exiting or entering
406 // carmode, respectively. Recents are not available in CarMode in nav bar so change
407 // to recent icon is not required.
Jorim Jaggi40db0292016-06-27 17:58:03 -0700408 KeyButtonDrawable backIcon = (backAlt)
Justin Paupore01915a12016-09-28 17:41:26 -0700409 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
410 : getBackIcon(mUseCarModeUi, mVertical);
John Spurlocka9b46822012-11-02 10:42:39 -0400411
Jason Monka2081822016-01-18 14:41:03 -0500412 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800413
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800414 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800415
Justin Paupore01915a12016-09-28 17:41:26 -0700416 if (mUseCarModeUi) {
Jason Monka2081822016-01-18 14:41:03 -0500417 getHomeButton().setImageDrawable(mHomeCarModeIcon);
418 } else {
419 getHomeButton().setImageDrawable(mHomeDefaultIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800420 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700421
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700422 // The Accessibility button always overrides the appearance of the IME switcher
423 final boolean showImeButton =
424 !mShowAccessibilityButton && ((hints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN)
425 != 0);
Jason Monka2081822016-01-18 14:41:03 -0500426 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700427 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800428
Jason Monkf1ff2092014-04-29 16:50:53 -0400429 // Update menu button in case the IME state has changed.
430 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700431 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400432
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800433 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
434 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
435
John Spurlocka9b46822012-11-02 10:42:39 -0400436 setDisabledFlags(mDisabledFlags, true);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700437
438 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400439 }
440
Daniel Sandler6da2b762011-09-14 16:04:59 -0400441 public void setDisabledFlags(int disabledFlags) {
Daniel Sandler6da2b762011-09-14 16:04:59 -0400442 setDisabledFlags(disabledFlags, false);
443 }
444
445 public void setDisabledFlags(int disabledFlags, boolean force) {
446 if (!force && mDisabledFlags == disabledFlags) return;
447
448 mDisabledFlags = disabledFlags;
449
Daniel Sandlerdba93562011-10-06 16:39:58 -0400450 final boolean disableHome = ((disabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700451
Justin Paupore01915a12016-09-28 17:41:26 -0700452 // Always disable recents when alternate car mode UI is active.
453 boolean disableRecent = mUseCarModeUi
454 || ((disabledFlags & View.STATUS_BAR_DISABLE_RECENT) != 0);
John Spurlocka9b46822012-11-02 10:42:39 -0400455 final boolean disableBack = ((disabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0)
456 && ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) == 0);
Daniel Sandler029d5872011-09-12 00:58:58 -0400457
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800458 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400459 if (navButtons != null) {
460 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400461 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400462 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
463 lt.addTransitionListener(mTransitionListener);
464 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400465 }
466 }
Jason Monk17488b92014-11-06 11:26:14 -0500467 if (inLockTask() && disableRecent && !disableHome) {
468 // Don't hide recents when in lock task, it is used for exiting.
469 // Unless home is hidden, then in DPM locked mode and no exit available.
470 disableRecent = false;
471 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400472
Jason Monka2081822016-01-18 14:41:03 -0500473 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500474 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500475 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400476 }
477
Jason Monk17488b92014-11-06 11:26:14 -0500478 private boolean inLockTask() {
479 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800480 return ActivityManager.getService().isInLockTaskMode();
Jason Monk17488b92014-11-06 11:26:14 -0500481 } catch (RemoteException e) {
482 return false;
483 }
484 }
485
Jorim Jaggi37c11802015-08-18 20:27:54 -0700486 public void setLayoutTransitionsEnabled(boolean enabled) {
487 mLayoutTransitionsEnabled = enabled;
488 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700489 }
490
Jorim Jaggi37c11802015-08-18 20:27:54 -0700491 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
492 setUseFadingAnimations(wakeAndUnlocking);
493 mWakeAndUnlocking = wakeAndUnlocking;
494 updateLayoutTransitionsEnabled();
495 }
496
497 private void updateLayoutTransitionsEnabled() {
498 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800499 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700500 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400501 if (lt != null) {
502 if (enabled) {
503 lt.enableTransitionType(LayoutTransition.APPEARING);
504 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
505 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
506 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
507 } else {
508 lt.disableTransitionType(LayoutTransition.APPEARING);
509 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
510 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
511 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
512 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700513 }
514 }
515
516 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500517 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
518 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700519 if (lp != null) {
520 boolean old = lp.windowAnimations != 0;
521 if (!old && useFadingAnimations) {
522 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
523 } else if (old && !useFadingAnimations) {
524 lp.windowAnimations = 0;
525 } else {
526 return;
527 }
528 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500529 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700530 }
531 }
532
Daniel Sandler56598cd2011-09-15 16:02:56 -0400533 public void setMenuVisibility(final boolean show) {
534 setMenuVisibility(show, false);
535 }
536
537 public void setMenuVisibility(final boolean show, final boolean force) {
538 if (!force && mShowMenu == show) return;
539
540 mShowMenu = show;
541
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800542 // Only show Menu if IME switcher and Accessibility button not shown.
543 final boolean shouldShow = mShowMenu && !mShowAccessibilityButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400544 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800545
Jason Monka2081822016-01-18 14:41:03 -0500546 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400547 }
548
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800549 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
550 mShowAccessibilityButton = visible;
551 mLongClickableAccessibilityButton = longClickable;
552 if (visible) {
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700553 // Accessibility button overrides Menu and IME switcher buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800554 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700555 getImeSwitchButton().setVisibility(View.INVISIBLE);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800556 }
557
558 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
559 getAccessibilityButton().setLongClickable(longClickable);
560 }
561
Jim Miller960892c2012-05-23 15:50:04 -0700562 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400563 public void onFinishInflate() {
Adrian Roosdb12b152016-07-12 15:38:55 -0700564 mNavigationInflaterView = (NavigationBarInflaterView) findViewById(
565 R.id.navigation_inflater);
Jason Monk9a6552d2016-05-20 11:21:59 -0400566 updateRotatedViews();
Felipe Leme15f915c2016-10-31 12:47:15 -0700567 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500568
569 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200570
Jason Monkf85fc962017-04-19 17:13:41 -0400571 DockedStackExistsListener.register(exists -> mHandler.post(() -> {
572 mDockedStackExists = exists;
573 updateRecentsIcon();
574 }));
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100575 }
576
Jason Monk9a6552d2016-05-20 11:21:59 -0400577 void updateRotatedViews() {
578 mRotatedViews[Surface.ROTATION_0] =
579 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
580 mRotatedViews[Surface.ROTATION_270] =
581 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
582
583 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400584 }
585
Adrian Roosa98b32c2016-08-11 10:41:08 -0700586 public boolean needsReorient(int rotation) {
587 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700588 }
589
Jason Monk9a6552d2016-05-20 11:21:59 -0400590 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400591 final int rot = mDisplay.getRotation();
592 for (int i=0; i<4; i++) {
593 mRotatedViews[i].setVisibility(View.GONE);
594 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400595 mCurrentView = mRotatedViews[rot];
596 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700597 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Felipe Leme15f915c2016-10-31 12:47:15 -0700598 for (int i = 0; i < mButtonDispatchers.size(); i++) {
599 mButtonDispatchers.valueAt(i).setCurrentView(mCurrentView);
Jason Monka2081822016-01-18 14:41:03 -0500600 }
Jorim Jaggi37c11802015-08-18 20:27:54 -0700601 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700602 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400603 }
604
605 private void updateRecentsIcon() {
606 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700607 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400608 }
609
610 public boolean isVertical() {
611 return mVertical;
612 }
613
614 public void reorient() {
615 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400616
Jason Monka2081822016-01-18 14:41:03 -0500617 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Jason Monkf1ff2092014-04-29 16:50:53 -0400618
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400619 mDeadZone = (DeadZone) mCurrentView.findViewById(R.id.deadzone);
Jorim Jaggi7aaa3d72016-11-28 14:03:11 +0100620 mDeadZone.setDisplayRotation(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400621
Daniel Sandler6da2b762011-09-14 16:04:59 -0400622 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700623 mBarTransitions.init();
Daniel Sandler6da2b762011-09-14 16:04:59 -0400624 setDisabledFlags(mDisabledFlags, true /* force */);
Daniel Sandler56598cd2011-09-15 16:02:56 -0400625 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400626
Daniel Sandler60ee2562011-07-22 12:34:33 -0400627 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -0700628 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -0400629 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800630
Selim Cinek92d892c2014-09-11 15:11:00 +0200631 updateTaskSwitchHelper();
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -0800632 setNavigationIconHints(mNavigationIconHints, true);
Xiaohui Chen9efa5de2016-11-22 10:34:38 -0800633
Xiaohui Chen40e978e2016-11-29 15:10:04 -0800634 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400635 }
Daniel Sandler48852952011-12-01 14:34:23 -0500636
Vadim Tryshev9ef8a512016-04-07 14:27:46 -0700637 public void onKeyguardOccludedChanged(boolean keyguardOccluded) {
638 }
639
Selim Cinek92d892c2014-09-11 15:11:00 +0200640 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -0500641 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +0200642 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -0800643 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +0200644 }
645
Daniel Sandler0b69b592012-01-23 21:08:36 -0500646 @Override
647 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -0400648 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500649 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400650
651 final boolean newVertical = w > 0 && h > w;
652 if (newVertical != mVertical) {
653 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -0400654 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -0400655 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +0200656 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -0400657 }
658
Daniel Sandler0b69b592012-01-23 21:08:36 -0500659 postCheckForInvalidLayout("sizeChanged");
660 super.onSizeChanged(w, h, oldw, oldh);
661 }
662
Selim Cinek92d892c2014-09-11 15:11:00 +0200663 private void notifyVerticalChangedListener(boolean newVertical) {
664 if (mOnVerticalChangedListener != null) {
665 mOnVerticalChangedListener.onVerticalChanged(newVertical);
666 }
667 }
668
Selim Cinek17a327a2014-08-25 15:03:48 +0200669 @Override
670 protected void onConfigurationChanged(Configuration newConfig) {
671 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800672 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +0200673 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -0700674 updateIcons(getContext(), mConfiguration, newConfig);
675 updateRecentsIcon();
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700676 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi) {
677 // If car mode or density changes, we need to reset the icons.
678 setNavigationIconHints(mNavigationIconHints, true);
679 }
Winsonfde2e6a2016-03-22 16:03:10 -0700680 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800681 }
682
683 /**
684 * If the configuration changed, update the carmode and return that it was updated.
685 */
686 private boolean updateCarMode(Configuration newConfig) {
687 boolean uiCarModeChanged = false;
688 if (newConfig != null) {
689 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -0700690 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
691
692 if (isCarMode != mInCarMode) {
693 mInCarMode = isCarMode;
694 getHomeButton().setCarMode(isCarMode);
695
696 if (ALTERNATE_CAR_MODE_UI) {
697 mUseCarModeUi = isCarMode;
698 uiCarModeChanged = true;
699 } else {
700 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
701 mUseCarModeUi = false;
702 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800703 }
704 }
705 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +0200706 }
707
Daniel Sandler0b69b592012-01-23 21:08:36 -0500708 /*
709 @Override
710 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -0400711 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -0400712 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -0500713 changed?"changed":"notchanged", left, top, right, bottom));
714 super.onLayout(changed, left, top, right, bottom);
715 }
716
717 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
718 // fails, any touch on the display will fix the layout.
719 @Override
720 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -0400721 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -0500722 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
723 postCheckForInvalidLayout("touch");
724 }
725 return super.onInterceptTouchEvent(ev);
726 }
727 */
John Spurlock209bede2013-07-17 12:23:27 -0400728
Daniel Sandler0b69b592012-01-23 21:08:36 -0500729
Daniel Sandler48852952011-12-01 14:34:23 -0500730 private String getResourceName(int resId) {
731 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -0500732 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -0500733 try {
734 return res.getResourceName(resId);
735 } catch (android.content.res.Resources.NotFoundException ex) {
736 return "(unknown)";
737 }
738 } else {
739 return "(null)";
740 }
741 }
742
Daniel Sandler0b69b592012-01-23 21:08:36 -0500743 private void postCheckForInvalidLayout(final String how) {
744 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
745 }
746
Daniel Sandler48852952011-12-01 14:34:23 -0500747 private static String visibilityToString(int vis) {
748 switch (vis) {
749 case View.INVISIBLE:
750 return "INVISIBLE";
751 case View.GONE:
752 return "GONE";
753 default:
754 return "VISIBLE";
755 }
756 }
757
Jason Monk67e6c802016-08-30 14:09:21 -0400758 @Override
759 protected void onAttachedToWindow() {
760 super.onAttachedToWindow();
Jason Monkde850bb2017-02-01 19:26:30 -0500761 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -0800762 Dependency.get(PluginManager.class).addPluginListener(this,
763 NavGesture.class, false /* Only one */);
Jason Monk67e6c802016-08-30 14:09:21 -0400764 }
765
766 @Override
767 protected void onDetachedFromWindow() {
768 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -0500769 Dependency.get(PluginManager.class).removePluginListener(this);
770 if (mGestureHelper != null) {
771 mGestureHelper.destroy();
772 }
Jason Monk67e6c802016-08-30 14:09:21 -0400773 }
774
775 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -0500776 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -0400777 mGestureHelper = plugin.getGestureHelper();
778 updateTaskSwitchHelper();
779 }
780
781 @Override
782 public void onPluginDisconnected(NavGesture plugin) {
783 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
784 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -0500785 if (mGestureHelper != null) {
786 mGestureHelper.destroy();
787 }
Jason Monk67e6c802016-08-30 14:09:21 -0400788 mGestureHelper = defaultHelper;
789 updateTaskSwitchHelper();
790 }
791
Daniel Sandler48852952011-12-01 14:34:23 -0500792 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
793 pw.println("NavigationBarView {");
794 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -0700795 final Point size = new Point();
796 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -0500797
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500798 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -0500799 + " " + visibilityToString(getVisibility())));
800
801 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -0700802 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -0400803 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -0500804 + r.toShortString()
805 + " " + visibilityToString(getWindowVisibility())
806 + (offscreen ? " OFFSCREEN!" : ""));
807
808 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -0800809 getResourceName(getCurrentView().getId()),
810 getCurrentView().getWidth(), getCurrentView().getHeight(),
811 visibilityToString(getCurrentView().getVisibility())));
Daniel Sandler48852952011-12-01 14:34:23 -0500812
John Spurlock41c1e352013-09-16 13:57:13 -0400813 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -0500814 mDisabledFlags,
815 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -0500816 mShowMenu ? "true" : "false"));
817
John Spurlock56d007b2013-10-28 18:40:56 -0400818 dumpButton(pw, "back", getBackButton());
819 dumpButton(pw, "home", getHomeButton());
820 dumpButton(pw, "rcnt", getRecentsButton());
821 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800822 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -0500823
Daniel Sandler48852952011-12-01 14:34:23 -0500824 pw.println(" }");
825 }
Jim Millere898ac52012-04-06 17:10:57 -0700826
Jason Monka2081822016-01-18 14:41:03 -0500827 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -0400828 pw.print(" " + caption + ": ");
829 if (button == null) {
830 pw.print("null");
831 } else {
Jason Monka2081822016-01-18 14:41:03 -0500832 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -0400833 + " alpha=" + button.getAlpha()
834 );
John Spurlock56d007b2013-10-28 18:40:56 -0400835 }
836 pw.println();
837 }
838
Jorim Jaggif4797922014-08-04 22:49:41 +0200839 public interface OnVerticalChangedListener {
840 void onVerticalChanged(boolean isVertical);
841 }
Jason Monka2081822016-01-18 14:41:03 -0500842
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400843}