blob: f8b79c61c430b13028b506314e4827cc41eb3ff4 [file] [log] [blame]
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.statusbar.phone;
18
Winson Chungc4e06202018-02-13 10:37:35 -080019import static android.view.MotionEvent.ACTION_DOWN;
20import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
Matthew Ng472d3e42018-06-14 15:16:55 -070021import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_DEAD_ZONE;
Winson Chungc4e06202018-02-13 10:37:35 -080022import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_HOME;
23import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
24
John Spurlock1bbd49d2012-10-19 11:09:32 -040025import android.animation.LayoutTransition;
John Spurlock56d007b2013-10-28 18:40:56 -040026import android.animation.LayoutTransition.TransitionListener;
27import android.animation.ObjectAnimator;
28import android.animation.TimeInterpolator;
29import android.animation.ValueAnimator;
Jorim Jaggi40db0292016-06-27 17:58:03 -070030import android.annotation.DrawableRes;
Mike Digman1e28a5a2018-02-14 10:49:19 -080031import android.annotation.StyleRes;
Daniel Sandler328310c2011-09-23 15:56:52 -040032import android.app.StatusBarManager;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040033import android.content.Context;
Selim Cinek17a327a2014-08-25 15:03:48 +020034import android.content.res.Configuration;
Matthew Nga8f24262017-12-19 11:54:24 -080035import android.graphics.Canvas;
Jeff Browna8b9def2012-07-23 14:22:49 -070036import android.graphics.Point;
Daniel Sandler48852952011-12-01 14:34:23 -050037import android.graphics.Rect;
Mike Digmana48cf192018-02-12 17:52:48 -080038import android.graphics.drawable.AnimatedVectorDrawable;
Mike Digman1e28a5a2018-02-14 10:49:19 -080039import android.graphics.drawable.Drawable;
Matthew Ng44b14502018-05-04 11:10:14 -070040import android.os.Bundle;
Daniel Sandler0b69b592012-01-23 21:08:36 -050041import android.os.Handler;
42import android.os.Message;
Matthew Ng8f25fb962018-01-16 17:17:24 -080043import android.os.SystemProperties;
Mike Digman7d092772018-01-11 12:10:32 -080044import android.support.annotation.ColorInt;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040045import android.util.AttributeSet;
John Spurlockcd686b52013-06-05 10:13:46 -040046import android.util.Log;
Jason Monka2081822016-01-18 14:41:03 -050047import android.util.SparseArray;
Jorim Jaggi40db0292016-06-27 17:58:03 -070048import android.view.ContextThemeWrapper;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040049import android.view.Display;
Daniel Sandler1d4d30a2011-04-28 12:35:29 -040050import android.view.MotionEvent;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040051import android.view.Surface;
John Spurlockde84f0e2013-06-12 12:41:00 -040052import android.view.View;
John Spurlock1bbd49d2012-10-19 11:09:32 -040053import android.view.ViewGroup;
Adrian Roos7e58a082018-03-09 16:40:56 +010054import android.view.WindowInsets;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040055import android.view.WindowManager;
Matthew Ng44b14502018-05-04 11:10:14 -070056import android.view.accessibility.AccessibilityNodeInfo;
57import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
Jason Monkf1ff2092014-04-29 16:50:53 -040058import android.view.inputmethod.InputMethodManager;
Jason Monk86bc3312016-08-16 13:17:56 -040059import android.widget.FrameLayout;
Jason Monk67e6c802016-08-30 14:09:21 -040060
Jason Monk9a376bc2017-05-10 09:52:10 -040061import com.android.settingslib.Utils;
Jason Monkde850bb2017-02-01 19:26:30 -050062import com.android.systemui.Dependency;
Jason Monkf85fc962017-04-19 17:13:41 -040063import com.android.systemui.DockedStackExistsListener;
Matthew Ng7d05e772017-11-09 14:41:07 -080064import com.android.systemui.OverviewProxyService;
Daniel Sandler8956dbb2011-04-22 07:55:02 -040065import com.android.systemui.R;
Jorim Jaggidd98d412015-11-18 15:57:38 -080066import com.android.systemui.RecentsComponent;
Matthew Ng44b14502018-05-04 11:10:14 -070067import com.android.systemui.SysUiServiceProvider;
Jason Monk67e6c802016-08-30 14:09:21 -040068import com.android.systemui.plugins.PluginListener;
69import com.android.systemui.plugins.PluginManager;
70import com.android.systemui.plugins.statusbar.phone.NavGesture;
71import com.android.systemui.plugins.statusbar.phone.NavGesture.GestureHelper;
Matthew Ng44b14502018-05-04 11:10:14 -070072import com.android.systemui.recents.Recents;
Tony Wickham05c1f852018-02-06 12:32:54 -080073import com.android.systemui.recents.RecentsOnboarding;
Matthew Ng44b14502018-05-04 11:10:14 -070074import com.android.systemui.shared.recents.IOverviewProxy;
Matthew Ng87cbf342018-02-15 12:21:18 -080075import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chungc4e06202018-02-13 10:37:35 -080076import com.android.systemui.shared.system.NavigationBarCompat;
Matthew Ng84db1612018-04-17 16:48:21 -070077import com.android.systemui.shared.system.WindowManagerWrapper;
Jorim Jaggidd98d412015-11-18 15:57:38 -080078import com.android.systemui.stackdivider.Divider;
Daniel Sandlerc26185b2012-08-29 15:49:53 -040079import com.android.systemui.statusbar.policy.DeadZone;
Jorim Jaggi40db0292016-06-27 17:58:03 -070080import com.android.systemui.statusbar.policy.KeyButtonDrawable;
Tony Wickhamfb63fe82018-01-16 12:14:06 -080081import com.android.systemui.statusbar.policy.TintedKeyButtonDrawable;
Jorim Jaggi2fdeeab2015-04-01 15:13:03 -070082
John Spurlockde84f0e2013-06-12 12:41:00 -040083import java.io.FileDescriptor;
84import java.io.PrintWriter;
Jason Monk32e3bb52017-07-27 12:35:41 -040085import java.util.function.Consumer;
John Spurlockde84f0e2013-06-12 12:41:00 -040086
Matthew Ng8f25fb962018-01-16 17:17:24 -080087import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_DISABLE_QUICK_SCRUB;
Matthew Ng8f25fb962018-01-16 17:17:24 -080088import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
Matthew Ng8a8c89c2018-03-01 13:21:43 -080089import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_OVERVIEW;
Winson Chung8079af72018-05-10 11:12:55 -070090import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
Matthew Ng8f25fb962018-01-16 17:17:24 -080091
Jason Monk67e6c802016-08-30 14:09:21 -040092public class NavigationBarView extends FrameLayout implements PluginListener<NavGesture> {
Daniel Sandler60ee2562011-07-22 12:34:33 -040093 final static boolean DEBUG = false;
Adrian Roosa98b32c2016-08-11 10:41:08 -070094 final static String TAG = "StatusBar/NavBarView";
Daniel Sandler60ee2562011-07-22 12:34:33 -040095
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040096 // slippery nav bar when everything is disabled, e.g. during setup
John Spurlock7edfbca2013-09-14 11:58:55 -040097 final static boolean SLIPPERY_WHEN_DISABLED = true;
Daniel Sandlerc3fc3222012-10-25 13:28:33 -040098
Justin Paupore01915a12016-09-28 17:41:26 -070099 final static boolean ALTERNATE_CAR_MODE_UI = false;
100
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400101 final Display mDisplay;
Daniel Sandler5c8da942011-06-28 00:29:04 -0400102 View mCurrentView = null;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400103 View[] mRotatedViews = new View[4];
Daniel Sandler60ee2562011-07-22 12:34:33 -0400104
Daniel Sandler60ee2562011-07-22 12:34:33 -0400105 boolean mVertical;
Adrian Roos090b7d82016-08-02 18:36:12 -0700106 private int mCurrentRotation = -1;
Daniel Sandler60ee2562011-07-22 12:34:33 -0400107
John Spurlock7edfbca2013-09-14 11:58:55 -0400108 boolean mShowMenu;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800109 boolean mShowAccessibilityButton;
110 boolean mLongClickableAccessibilityButton;
Mike Digmana48cf192018-02-12 17:52:48 -0800111 boolean mShowRotateButton;
Daniel Sandler6da2b762011-09-14 16:04:59 -0400112 int mDisabledFlags = 0;
Daniel Sandler328310c2011-09-23 15:56:52 -0400113 int mNavigationIconHints = 0;
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400114
Winson Chungc4e06202018-02-13 10:37:35 -0800115 private @NavigationBarCompat.HitTarget int mDownHitTarget = HIT_TARGET_NONE;
116 private Rect mHomeButtonBounds = new Rect();
117 private Rect mBackButtonBounds = new Rect();
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800118 private Rect mRecentsButtonBounds = new Rect();
Winson Chung8079af72018-05-10 11:12:55 -0700119 private Rect mRotationButtonBounds = new Rect();
Winson Chungc4e06202018-02-13 10:37:35 -0800120 private int[] mTmpPosition = new int[2];
Winson Chung661d5f92018-05-21 18:41:39 -0700121 private Rect mTmpRect = new Rect();
Winson Chungc4e06202018-02-13 10:37:35 -0800122
Matthew Ngeb5ce832018-05-15 17:50:37 -0700123 private KeyButtonDrawable mBackIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700124 private KeyButtonDrawable mBackCarModeIcon, mBackLandCarModeIcon;
125 private KeyButtonDrawable mBackAltCarModeIcon, mBackAltLandCarModeIcon;
126 private KeyButtonDrawable mHomeDefaultIcon, mHomeCarModeIcon;
127 private KeyButtonDrawable mRecentIcon;
128 private KeyButtonDrawable mDockedIcon;
129 private KeyButtonDrawable mImeIcon;
130 private KeyButtonDrawable mMenuIcon;
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800131 private KeyButtonDrawable mAccessibilityIcon;
Mike Digmanc8217582018-03-06 13:08:33 -0800132 private TintedKeyButtonDrawable mRotateSuggestionIcon;
Fabrice Di Meglio18d98242013-01-17 10:57:40 -0800133
Jason Monk67e6c802016-08-30 14:09:21 -0400134 private GestureHelper mGestureHelper;
Matthew Ng603b3292018-03-30 17:15:39 -0700135 private final DeadZone mDeadZone;
Matthew Ng1e14e962018-05-03 12:51:43 -0700136 private boolean mDeadZoneConsuming = false;
John Spurlock89835dd2013-08-16 15:06:51 -0400137 private final NavigationBarTransitions mBarTransitions;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800138 private final OverviewProxyService mOverviewProxyService;
Jim Millere898ac52012-04-06 17:10:57 -0700139
Daniel Sandler0b69b592012-01-23 21:08:36 -0500140 // workaround for LayoutTransitions leaving the nav buttons in a weird state (bug 5549288)
141 final static boolean WORKAROUND_INVALID_LAYOUT = true;
142 final static int MSG_CHECK_INVALID_LAYOUT = 8686;
143
John Spurlock56d007b2013-10-28 18:40:56 -0400144 // performs manual animation in sync with layout transitions
145 private final NavTransitionListener mTransitionListener = new NavTransitionListener();
146
Jorim Jaggif4797922014-08-04 22:49:41 +0200147 private OnVerticalChangedListener mOnVerticalChangedListener;
Jorim Jaggi37c11802015-08-18 20:27:54 -0700148 private boolean mLayoutTransitionsEnabled = true;
149 private boolean mWakeAndUnlocking;
Justin Paupore01915a12016-09-28 17:41:26 -0700150 private boolean mUseCarModeUi = false;
151 private boolean mInCarMode = false;
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800152 private boolean mDockedStackExists;
Jorim Jaggif4797922014-08-04 22:49:41 +0200153
Felipe Leme15f915c2016-10-31 12:47:15 -0700154 private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
Winsonfde2e6a2016-03-22 16:03:10 -0700155 private Configuration mConfiguration;
Jason Monka2081822016-01-18 14:41:03 -0500156
Adrian Roosdb12b152016-07-12 15:38:55 -0700157 private NavigationBarInflaterView mNavigationInflaterView;
Jason Monk67e6c802016-08-30 14:09:21 -0400158 private RecentsComponent mRecentsComponent;
159 private Divider mDivider;
Tony Wickham05c1f852018-02-06 12:32:54 -0800160 private RecentsOnboarding mRecentsOnboarding;
Matthew Ng78f88d12018-01-23 12:39:55 -0800161 private NotificationPanelView mPanelView;
Adrian Roosdb12b152016-07-12 15:38:55 -0700162
Mike Digman1e28a5a2018-02-14 10:49:19 -0800163 private int mRotateBtnStyle = R.style.RotateButtonCCWStart90;
Mike Digmana48cf192018-02-12 17:52:48 -0800164
John Spurlock56d007b2013-10-28 18:40:56 -0400165 private class NavTransitionListener implements TransitionListener {
166 private boolean mBackTransitioning;
167 private boolean mHomeAppearing;
168 private long mStartDelay;
169 private long mDuration;
170 private TimeInterpolator mInterpolator;
171
172 @Override
173 public void startTransition(LayoutTransition transition, ViewGroup container,
174 View view, int transitionType) {
175 if (view.getId() == R.id.back) {
176 mBackTransitioning = true;
177 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
178 mHomeAppearing = true;
179 mStartDelay = transition.getStartDelay(transitionType);
180 mDuration = transition.getDuration(transitionType);
181 mInterpolator = transition.getInterpolator(transitionType);
182 }
183 }
184
185 @Override
186 public void endTransition(LayoutTransition transition, ViewGroup container,
187 View view, int transitionType) {
188 if (view.getId() == R.id.back) {
189 mBackTransitioning = false;
190 } else if (view.getId() == R.id.home && transitionType == LayoutTransition.APPEARING) {
191 mHomeAppearing = false;
192 }
193 }
194
195 public void onBackAltCleared() {
Jason Monka2081822016-01-18 14:41:03 -0500196 ButtonDispatcher backButton = getBackButton();
Anthony Chenada13042016-01-19 16:57:20 -0800197
John Spurlock56d007b2013-10-28 18:40:56 -0400198 // When dismissing ime during unlock, force the back button to run the same appearance
199 // animation as home (if we catch this condition early enough).
Jason Monka2081822016-01-18 14:41:03 -0500200 if (!mBackTransitioning && backButton.getVisibility() == VISIBLE
201 && mHomeAppearing && getHomeButton().getAlpha() == 0) {
John Spurlock56d007b2013-10-28 18:40:56 -0400202 getBackButton().setAlpha(0);
Anthony Chenada13042016-01-19 16:57:20 -0800203 ValueAnimator a = ObjectAnimator.ofFloat(backButton, "alpha", 0, 1);
John Spurlock56d007b2013-10-28 18:40:56 -0400204 a.setStartDelay(mStartDelay);
205 a.setDuration(mDuration);
206 a.setInterpolator(mInterpolator);
207 a.start();
208 }
209 }
210 }
211
Jason Monkf1ff2092014-04-29 16:50:53 -0400212 private final OnClickListener mImeSwitcherClickListener = new OnClickListener() {
213 @Override
214 public void onClick(View view) {
Yohei Yukawa777ef952015-11-25 20:32:24 -0800215 mContext.getSystemService(InputMethodManager.class)
Seigo Nonaka14e13912015-05-06 21:04:13 -0700216 .showInputMethodPicker(true /* showAuxiliarySubtypes */);
Jason Monkf1ff2092014-04-29 16:50:53 -0400217 }
218 };
219
Daniel Sandler0b69b592012-01-23 21:08:36 -0500220 private class H extends Handler {
221 public void handleMessage(Message m) {
222 switch (m.what) {
223 case MSG_CHECK_INVALID_LAYOUT:
224 final String how = "" + m.obj;
225 final int w = getWidth();
226 final int h = getHeight();
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800227 final int vw = getCurrentView().getWidth();
228 final int vh = getCurrentView().getHeight();
Daniel Sandler0b69b592012-01-23 21:08:36 -0500229
230 if (h != vh || w != vw) {
John Spurlockcd686b52013-06-05 10:13:46 -0400231 Log.w(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -0500232 "*** Invalid layout in navigation bar (%s this=%dx%d cur=%dx%d)",
233 how, w, h, vw, vh));
234 if (WORKAROUND_INVALID_LAYOUT) {
235 requestLayout();
236 }
237 }
238 break;
239 }
240 }
241 }
242
Matthew Ng44b14502018-05-04 11:10:14 -0700243 private final AccessibilityDelegate mQuickStepAccessibilityDelegate
244 = new AccessibilityDelegate() {
245 private AccessibilityAction mToggleOverviewAction;
246
247 @Override
248 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
249 super.onInitializeAccessibilityNodeInfo(host, info);
250 if (mToggleOverviewAction == null) {
251 mToggleOverviewAction = new AccessibilityAction(R.id.action_toggle_overview,
252 getContext().getString(R.string.quick_step_accessibility_toggle_overview));
253 }
254 info.addAction(mToggleOverviewAction);
255 }
256
257 @Override
258 public boolean performAccessibilityAction(View host, int action, Bundle args) {
259 switch (action) {
260 case R.id.action_toggle_overview:
261 SysUiServiceProvider.getComponent(getContext(), Recents.class)
262 .toggleRecentApps();
263 break;
264 default:
265 return super.performAccessibilityAction(host, action, args);
266 }
267 return true;
268 }
269 };
270
John Spurlocke932e302013-08-12 10:16:29 -0400271 public NavigationBarView(Context context, AttributeSet attrs) {
272 super(context, attrs);
273
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800274 mDisplay = ((WindowManager) context.getSystemService(
John Spurlocke932e302013-08-12 10:16:29 -0400275 Context.WINDOW_SERVICE)).getDefaultDisplay();
John Spurlocke932e302013-08-12 10:16:29 -0400276
John Spurlocke932e302013-08-12 10:16:29 -0400277 mVertical = false;
278 mShowMenu = false;
John Spurlocke932e302013-08-12 10:16:29 -0400279
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800280 mShowAccessibilityButton = false;
281 mLongClickableAccessibilityButton = false;
282
Matthew Ngf2946542018-02-12 14:13:18 -0800283 mOverviewProxyService = Dependency.get(OverviewProxyService.class);
284 mRecentsOnboarding = new RecentsOnboarding(context, mOverviewProxyService);
285
Winsonfde2e6a2016-03-22 16:03:10 -0700286 mConfiguration = new Configuration();
287 mConfiguration.updateFrom(context.getResources().getConfiguration());
Matthew Ngd0a73e72018-03-02 15:16:03 -0800288 reloadNavIcons();
John Spurlocke932e302013-08-12 10:16:29 -0400289
John Spurlock7edfbca2013-09-14 11:58:55 -0400290 mBarTransitions = new NavigationBarTransitions(this);
Jason Monka2081822016-01-18 14:41:03 -0500291
Felipe Leme15f915c2016-10-31 12:47:15 -0700292 mButtonDispatchers.put(R.id.back, new ButtonDispatcher(R.id.back));
293 mButtonDispatchers.put(R.id.home, new ButtonDispatcher(R.id.home));
294 mButtonDispatchers.put(R.id.recent_apps, new ButtonDispatcher(R.id.recent_apps));
295 mButtonDispatchers.put(R.id.menu, new ButtonDispatcher(R.id.menu));
296 mButtonDispatchers.put(R.id.ime_switcher, new ButtonDispatcher(R.id.ime_switcher));
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800297 mButtonDispatchers.put(R.id.accessibility_button,
298 new ButtonDispatcher(R.id.accessibility_button));
Mike Digman7d092772018-01-11 12:10:32 -0800299 mButtonDispatchers.put(R.id.rotate_suggestion,
300 new ButtonDispatcher(R.id.rotate_suggestion));
Matthew Ng6607c3d2018-04-26 15:23:27 -0700301 mButtonDispatchers.put(R.id.menu_container,
302 new ButtonDispatcher(R.id.menu_container));
Matthew Ng603b3292018-03-30 17:15:39 -0700303 mDeadZone = new DeadZone(this);
John Spurlocke932e302013-08-12 10:16:29 -0400304 }
305
306 public BarTransitions getBarTransitions() {
307 return mBarTransitions;
308 }
309
Jorim Jaggi40db0292016-06-27 17:58:03 -0700310 public LightBarTransitionsController getLightTransitionsController() {
311 return mBarTransitions.getLightTransitionsController();
312 }
313
Matthew Ng78f88d12018-01-23 12:39:55 -0800314 public void setComponents(RecentsComponent recentsComponent, Divider divider,
315 NotificationPanelView panel) {
Jason Monk67e6c802016-08-30 14:09:21 -0400316 mRecentsComponent = recentsComponent;
317 mDivider = divider;
Matthew Ng78f88d12018-01-23 12:39:55 -0800318 mPanelView = panel;
Jason Monk67e6c802016-08-30 14:09:21 -0400319 if (mGestureHelper instanceof NavigationBarGestureHelper) {
320 ((NavigationBarGestureHelper) mGestureHelper).setComponents(
321 recentsComponent, divider, this);
322 }
Jim Millere898ac52012-04-06 17:10:57 -0700323 }
324
Jorim Jaggif4797922014-08-04 22:49:41 +0200325 public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
326 mOnVerticalChangedListener = onVerticalChangedListener;
Selim Cinek92d892c2014-09-11 15:11:00 +0200327 notifyVerticalChangedListener(mVertical);
Jorim Jaggif4797922014-08-04 22:49:41 +0200328 }
329
Jim Millere898ac52012-04-06 17:10:57 -0700330 @Override
331 public boolean onInterceptTouchEvent(MotionEvent event) {
Matthew Ng472d3e42018-06-14 15:16:55 -0700332 final boolean deadZoneConsumed = shouldDeadZoneConsumeTouchEvents(event);
Winson Chungc4e06202018-02-13 10:37:35 -0800333 switch (event.getActionMasked()) {
334 case ACTION_DOWN:
335 int x = (int) event.getX();
336 int y = (int) event.getY();
337 mDownHitTarget = HIT_TARGET_NONE;
Matthew Ng472d3e42018-06-14 15:16:55 -0700338 if (deadZoneConsumed) {
339 mDownHitTarget = HIT_TARGET_DEAD_ZONE;
340 } else if (getBackButton().isVisible() && mBackButtonBounds.contains(x, y)) {
Winson Chungc4e06202018-02-13 10:37:35 -0800341 mDownHitTarget = HIT_TARGET_BACK;
Winson Chungc6c9d402018-05-25 18:25:52 -0700342 } else if (getHomeButton().isVisible() && mHomeButtonBounds.contains(x, y)) {
Winson Chungc4e06202018-02-13 10:37:35 -0800343 mDownHitTarget = HIT_TARGET_HOME;
Winson Chungc6c9d402018-05-25 18:25:52 -0700344 } else if (getRecentsButton().isVisible() && mRecentsButtonBounds.contains(x, y)) {
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800345 mDownHitTarget = HIT_TARGET_OVERVIEW;
Winson Chungc6c9d402018-05-25 18:25:52 -0700346 } else if (getRotateSuggestionButton().isVisible()
347 && mRotationButtonBounds.contains(x, y)) {
Winson Chung8079af72018-05-10 11:12:55 -0700348 mDownHitTarget = HIT_TARGET_ROTATION;
Winson Chungc4e06202018-02-13 10:37:35 -0800349 }
350 break;
351 }
Winson Chung49658842018-02-08 12:52:21 -0800352 return mGestureHelper.onInterceptTouchEvent(event);
Jim Millere898ac52012-04-06 17:10:57 -0700353 }
354
Winson Chung4faf38a2018-02-06 08:53:37 -0800355 @Override
356 public boolean onTouchEvent(MotionEvent event) {
Matthew Ng472d3e42018-06-14 15:16:55 -0700357 shouldDeadZoneConsumeTouchEvents(event);
Winson Chung4faf38a2018-02-06 08:53:37 -0800358 if (mGestureHelper.onTouchEvent(event)) {
359 return true;
360 }
Winson Chung49658842018-02-08 12:52:21 -0800361 return super.onTouchEvent(event);
Winson Chung4faf38a2018-02-06 08:53:37 -0800362 }
363
Matthew Ng1e14e962018-05-03 12:51:43 -0700364 private boolean shouldDeadZoneConsumeTouchEvents(MotionEvent event) {
365 if (mDeadZone.onTouchEvent(event) || mDeadZoneConsuming) {
366 switch (event.getActionMasked()) {
367 case MotionEvent.ACTION_DOWN:
368 // Allow gestures starting in the deadzone to be slippery
369 setSlippery(true);
370 mDeadZoneConsuming = true;
371 break;
372 case MotionEvent.ACTION_CANCEL:
373 case MotionEvent.ACTION_UP:
374 // When a gesture started in the deadzone is finished, restore slippery state
375 updateSlippery();
376 mDeadZoneConsuming = false;
377 break;
378 }
379 return true;
380 }
381 return false;
382 }
383
Winson Chungc4e06202018-02-13 10:37:35 -0800384 public @NavigationBarCompat.HitTarget int getDownHitTarget() {
385 return mDownHitTarget;
386 }
387
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700388 public void abortCurrentGesture() {
Jason Monka2081822016-01-18 14:41:03 -0500389 getHomeButton().abortCurrentGesture();
Xiyuan Xiaee7dd052015-05-15 09:46:27 -0700390 }
391
Daniel Sandler0b69b592012-01-23 21:08:36 -0500392 private H mHandler = new H();
393
John Spurlock7edfbca2013-09-14 11:58:55 -0400394 public View getCurrentView() {
395 return mCurrentView;
396 }
397
Xiaohui Chen10942302015-12-16 16:38:13 -0800398 public View[] getAllViews() {
399 return mRotatedViews;
400 }
401
Jason Monka2081822016-01-18 14:41:03 -0500402 public ButtonDispatcher getRecentsButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700403 return mButtonDispatchers.get(R.id.recent_apps);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400404 }
405
Jason Monka2081822016-01-18 14:41:03 -0500406 public ButtonDispatcher getMenuButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700407 return mButtonDispatchers.get(R.id.menu);
Daniel Sandler5c8da942011-06-28 00:29:04 -0400408 }
409
Jason Monka2081822016-01-18 14:41:03 -0500410 public ButtonDispatcher getBackButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700411 return mButtonDispatchers.get(R.id.back);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400412 }
413
Jason Monka2081822016-01-18 14:41:03 -0500414 public ButtonDispatcher getHomeButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700415 return mButtonDispatchers.get(R.id.home);
Mike Lockwoode3646dd2011-09-01 12:46:28 -0400416 }
417
Jason Monka2081822016-01-18 14:41:03 -0500418 public ButtonDispatcher getImeSwitchButton() {
Felipe Leme15f915c2016-10-31 12:47:15 -0700419 return mButtonDispatchers.get(R.id.ime_switcher);
Jason Monkf1ff2092014-04-29 16:50:53 -0400420 }
421
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800422 public ButtonDispatcher getAccessibilityButton() {
423 return mButtonDispatchers.get(R.id.accessibility_button);
424 }
425
Mike Digman7d092772018-01-11 12:10:32 -0800426 public ButtonDispatcher getRotateSuggestionButton() {
427 return mButtonDispatchers.get(R.id.rotate_suggestion);
428 }
429
Matthew Ng6607c3d2018-04-26 15:23:27 -0700430 public ButtonDispatcher getMenuContainer() {
431 return mButtonDispatchers.get(R.id.menu_container);
432 }
433
Jorim Jaggi40db0292016-06-27 17:58:03 -0700434 public SparseArray<ButtonDispatcher> getButtonDispatchers() {
435 return mButtonDispatchers;
436 }
437
Matthew Ng9c3bce52018-02-01 22:00:31 +0000438 public boolean isRecentsButtonVisible() {
439 return getRecentsButton().getVisibility() == View.VISIBLE;
440 }
441
Matthew Ng6ff33b72018-02-27 13:47:38 -0800442 public boolean isOverviewEnabled() {
443 return (mDisabledFlags & View.STATUS_BAR_DISABLE_RECENT) == 0;
444 }
445
Matthew Ng8f25fb962018-01-16 17:17:24 -0800446 public boolean isQuickStepSwipeUpEnabled() {
Matthew Ngc1a97b12018-03-28 14:02:00 -0700447 return mOverviewProxyService.shouldShowSwipeUpUI() && isOverviewEnabled();
Matthew Ng8f25fb962018-01-16 17:17:24 -0800448 }
449
450 public boolean isQuickScrubEnabled() {
451 return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", true)
Winson Chungd95a2252018-04-04 17:02:29 +0000452 && mOverviewProxyService.isEnabled() && isOverviewEnabled()
Matthew Ngc1a97b12018-03-28 14:02:00 -0700453 && ((mOverviewProxyService.getInteractionFlags() & FLAG_DISABLE_QUICK_SCRUB) == 0);
Matthew Ng8f25fb962018-01-16 17:17:24 -0800454 }
455
Matthew Ngeb5ce832018-05-15 17:50:37 -0700456 // TODO(b/80003212): change car mode icons to vector icons.
Winsonfde2e6a2016-03-22 16:03:10 -0700457 private void updateCarModeIcons(Context ctx) {
Jorim Jaggi40db0292016-06-27 17:58:03 -0700458 mBackCarModeIcon = getDrawable(ctx,
459 R.drawable.ic_sysbar_back_carmode, R.drawable.ic_sysbar_back_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800460 mBackLandCarModeIcon = mBackCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700461 mBackAltCarModeIcon = getDrawable(ctx,
462 R.drawable.ic_sysbar_back_ime_carmode, R.drawable.ic_sysbar_back_ime_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800463 mBackAltLandCarModeIcon = mBackAltCarModeIcon;
Jorim Jaggi40db0292016-06-27 17:58:03 -0700464 mHomeCarModeIcon = getDrawable(ctx,
465 R.drawable.ic_sysbar_home_carmode, R.drawable.ic_sysbar_home_carmode);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800466 }
467
Matthew Ngd0a73e72018-03-02 15:16:03 -0800468 private void reloadNavIcons() {
469 updateIcons(mContext, Configuration.EMPTY, mConfiguration);
470 }
471
Winsonfde2e6a2016-03-22 16:03:10 -0700472 private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700473 int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
474 int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
475 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
476 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
477
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700478 if (oldConfig.orientation != newConfig.orientation
479 || oldConfig.densityDpi != newConfig.densityDpi) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700480 mDockedIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_docked);
481 mHomeDefaultIcon = getHomeDrawable(lightContext, darkContext);
Winsonfde2e6a2016-03-22 16:03:10 -0700482 }
Jason Monk1f785d42017-07-25 15:46:33 -0400483 if (oldConfig.densityDpi != newConfig.densityDpi
484 || oldConfig.getLayoutDirection() != newConfig.getLayoutDirection()) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700485 mBackIcon = getBackDrawable(lightContext, darkContext);
486 mRecentIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_recent);
487 mMenuIcon = getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_menu);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700488
Matthew Ngeb5ce832018-05-15 17:50:37 -0700489 mAccessibilityIcon = getDrawable(lightContext, darkContext,
490 R.drawable.ic_sysbar_accessibility_button, false /* hasShadow */);
Mike Digmane3909de2018-03-30 11:22:05 -0700491
Matthew Ngeb5ce832018-05-15 17:50:37 -0700492 mImeIcon = getDrawable(lightContext, darkContext, R.drawable.ic_ime_switcher_default,
493 false /* hasShadow */);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700494
Mike Digman1e28a5a2018-02-14 10:49:19 -0800495 updateRotateSuggestionButtonStyle(mRotateBtnStyle, false);
Mike Digman7d092772018-01-11 12:10:32 -0800496
Justin Paupore01915a12016-09-28 17:41:26 -0700497 if (ALTERNATE_CAR_MODE_UI) {
498 updateCarModeIcons(ctx);
499 }
Winsonfde2e6a2016-03-22 16:03:10 -0700500 }
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700501 }
502
Matthew Ngeb5ce832018-05-15 17:50:37 -0700503 public KeyButtonDrawable getBackDrawable(Context lightContext, Context darkContext) {
504 KeyButtonDrawable drawable = chooseNavigationIconDrawable(lightContext, darkContext,
505 R.drawable.ic_sysbar_back, R.drawable.ic_sysbar_back_quick_step);
506 orientBackButton(drawable);
507 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800508 }
509
Matthew Ngeb5ce832018-05-15 17:50:37 -0700510 public KeyButtonDrawable getHomeDrawable(Context lightContext, Context darkContext) {
511 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
512 KeyButtonDrawable drawable = quickStepEnabled
513 ? getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home_quick_step)
514 : getDrawable(lightContext, darkContext, R.drawable.ic_sysbar_home,
515 false /* hasShadow */);
516 orientHomeButton(drawable);
517 return drawable;
Matthew Ng87cbf342018-02-15 12:21:18 -0800518 }
519
Matthew Ngeb5ce832018-05-15 17:50:37 -0700520 private void orientBackButton(KeyButtonDrawable drawable) {
521 final boolean useAltBack =
522 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
523 drawable.setRotation(useAltBack
524 ? -90 : (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) ? 180 : 0);
Matthew Ng87cbf342018-02-15 12:21:18 -0800525 }
526
Matthew Ngeb5ce832018-05-15 17:50:37 -0700527 private void orientHomeButton(KeyButtonDrawable drawable) {
528 drawable.setRotation(mVertical ? 90 : 0);
529 }
530
531 private KeyButtonDrawable chooseNavigationIconDrawable(Context lightContext,
532 Context darkContext, @DrawableRes int icon, @DrawableRes int quickStepIcon) {
Matthew Ngc1a97b12018-03-28 14:02:00 -0700533 final boolean quickStepEnabled = mOverviewProxyService.shouldShowSwipeUpUI();
Matthew Ng87cbf342018-02-15 12:21:18 -0800534 return quickStepEnabled
Matthew Ngeb5ce832018-05-15 17:50:37 -0700535 ? getDrawable(lightContext, darkContext, quickStepIcon)
536 : getDrawable(lightContext, darkContext, icon);
537 }
538
539 private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
540 @DrawableRes int icon) {
541 return getDrawable(lightContext, darkContext, icon, true /* hasShadow */);
542 }
543
544 private KeyButtonDrawable getDrawable(Context lightContext, Context darkContext,
545 @DrawableRes int icon, boolean hasShadow) {
546 return KeyButtonDrawable.create(lightContext, lightContext.getDrawable(icon),
547 darkContext.getDrawable(icon), hasShadow);
Matthew Ng87cbf342018-02-15 12:21:18 -0800548 }
549
Jorim Jaggi40db0292016-06-27 17:58:03 -0700550 private KeyButtonDrawable getDrawable(Context ctx, @DrawableRes int lightIcon,
551 @DrawableRes int darkIcon) {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700552 // Legacy image icons using separate light and dark images will not support shadows
553 return KeyButtonDrawable.create(ctx, ctx.getDrawable(lightIcon),
554 ctx.getDrawable(darkIcon), false /* hasShadow */);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700555 }
556
Mike Digmanc8217582018-03-06 13:08:33 -0800557 private TintedKeyButtonDrawable getDrawable(Context ctx, @DrawableRes int icon,
Mike Digman7d092772018-01-11 12:10:32 -0800558 @ColorInt int lightColor, @ColorInt int darkColor) {
559 return TintedKeyButtonDrawable.create(ctx.getDrawable(icon), lightColor, darkColor);
560 }
561
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700562 @Override
563 public void setLayoutDirection(int layoutDirection) {
Matthew Ngd0a73e72018-03-02 15:16:03 -0800564 reloadNavIcons();
Fabrice Di Meglio8afcd142012-07-27 18:27:11 -0700565
566 super.setLayoutDirection(layoutDirection);
Daniel Sandler1d4d30a2011-04-28 12:35:29 -0400567 }
568
Jorim Jaggi40db0292016-06-27 17:58:03 -0700569 private KeyButtonDrawable getBackIconWithAlt(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800570 return landscape
Matthew Ngeb5ce832018-05-15 17:50:37 -0700571 ? carMode ? mBackAltLandCarModeIcon : mBackIcon
572 : carMode ? mBackAltCarModeIcon : mBackIcon;
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800573 }
574
Jorim Jaggi40db0292016-06-27 17:58:03 -0700575 private KeyButtonDrawable getBackIcon(boolean carMode, boolean landscape) {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800576 return landscape
Matthew Ngeb5ce832018-05-15 17:50:37 -0700577 ? carMode ? mBackLandCarModeIcon : mBackIcon
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800578 : carMode ? mBackCarModeIcon : mBackIcon;
579 }
580
Matthew Ngd0a73e72018-03-02 15:16:03 -0800581 public void setNavigationIconHints(int hints) {
582 if (hints == mNavigationIconHints) return;
John Spurlock56d007b2013-10-28 18:40:56 -0400583 final boolean backAlt = (hints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
584 if ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0 && !backAlt) {
585 mTransitionListener.onBackAltCleared();
586 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400587 if (DEBUG) {
John Spurlock01534782014-01-13 11:59:22 -0500588 android.widget.Toast.makeText(getContext(),
Daniel Sandler328310c2011-09-23 15:56:52 -0400589 "Navigation icon hints = " + hints,
590 500).show();
591 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400592 mNavigationIconHints = hints;
Matthew Ngd0a73e72018-03-02 15:16:03 -0800593 updateNavButtonIcons();
594 }
Daniel Sandler328310c2011-09-23 15:56:52 -0400595
Matthew Ngd0a73e72018-03-02 15:16:03 -0800596 public void setDisabledFlags(int disabledFlags) {
597 if (mDisabledFlags == disabledFlags) return;
598
599 final boolean overviewEnabledBefore = isOverviewEnabled();
600 mDisabledFlags = disabledFlags;
601
602 // Update icons if overview was just enabled to ensure the correct icons are present
603 if (!overviewEnabledBefore && isOverviewEnabled()) {
604 reloadNavIcons();
605 }
606
607 updateNavButtonIcons();
Winson Chung1be4c7e2018-05-23 18:24:13 -0700608 updateSlippery();
Tracy Zhou98140912018-06-05 12:09:14 -0700609 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ngd0a73e72018-03-02 15:16:03 -0800610 }
611
612 public void updateNavButtonIcons() {
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800613 // We have to replace or restore the back and home button icons when exiting or entering
614 // carmode, respectively. Recents are not available in CarMode in nav bar so change
615 // to recent icon is not required.
Matthew Ngeb5ce832018-05-15 17:50:37 -0700616 final boolean useAltBack =
617 (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
618 KeyButtonDrawable backIcon = useAltBack
619 ? getBackIconWithAlt(mUseCarModeUi, mVertical)
620 : getBackIcon(mUseCarModeUi, mVertical);
621 KeyButtonDrawable homeIcon = mUseCarModeUi ? mHomeCarModeIcon : mHomeDefaultIcon;
622 if (!mUseCarModeUi) {
623 orientBackButton(backIcon);
624 orientHomeButton(homeIcon);
625 }
626 getHomeButton().setImageDrawable(homeIcon);
Jason Monka2081822016-01-18 14:41:03 -0500627 getBackButton().setImageDrawable(backIcon);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800628
Jorim Jaggid30d95d2016-02-17 20:27:22 -0800629 updateRecentsIcon();
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -0800630
Mike Digmana48cf192018-02-12 17:52:48 -0800631 // Update IME button visibility, a11y and rotate button always overrides the appearance
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700632 final boolean showImeButton =
Mike Digmana48cf192018-02-12 17:52:48 -0800633 !mShowAccessibilityButton &&
Matthew Ngd0a73e72018-03-02 15:16:03 -0800634 !mShowRotateButton &&
635 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) != 0);
Jason Monka2081822016-01-18 14:41:03 -0500636 getImeSwitchButton().setVisibility(showImeButton ? View.VISIBLE : View.INVISIBLE);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700637 getImeSwitchButton().setImageDrawable(mImeIcon);
Anthony Chenada13042016-01-19 16:57:20 -0800638
Mike Digmana48cf192018-02-12 17:52:48 -0800639 // Update menu button, visibility logic in method
Jason Monkf1ff2092014-04-29 16:50:53 -0400640 setMenuVisibility(mShowMenu, true);
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700641 getMenuButton().setImageDrawable(mMenuIcon);
Jason Monkf1ff2092014-04-29 16:50:53 -0400642
Mike Digmana48cf192018-02-12 17:52:48 -0800643 // Update rotate button, visibility altered by a11y button logic
644 getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
645
646 // Update a11y button, visibility logic in state method
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800647 setAccessibilityButtonState(mShowAccessibilityButton, mLongClickableAccessibilityButton);
648 getAccessibilityButton().setImageDrawable(mAccessibilityIcon);
649
Jorim Jaggi40db0292016-06-27 17:58:03 -0700650 mBarTransitions.reapplyDarkIntensity();
Daniel Sandler328310c2011-09-23 15:56:52 -0400651
Matthew Ngd0a73e72018-03-02 15:16:03 -0800652 boolean disableHome = ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
Sriram Viswanathan469caae2016-03-22 13:11:50 -0700653
Justin Paupore01915a12016-09-28 17:41:26 -0700654 // Always disable recents when alternate car mode UI is active.
Matthew Ng6ff33b72018-02-27 13:47:38 -0800655 boolean disableRecent = mUseCarModeUi || !isOverviewEnabled();
Charles Hee57ff812017-10-26 10:01:35 +0100656
Matthew Ngeb5ce832018-05-15 17:50:37 -0700657 boolean disableBack = ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack;
Daniel Sandler029d5872011-09-12 00:58:58 -0400658
Matthew Ng87cbf342018-02-15 12:21:18 -0800659 // When screen pinning, don't hide back and home when connected service or back and
660 // recents buttons when disconnected from launcher service in screen pinning mode,
661 // as they are used for exiting.
Matthew Ng6ff33b72018-02-27 13:47:38 -0800662 final boolean pinningActive = ActivityManagerWrapper.getInstance().isScreenPinningActive();
Winson Chungd95a2252018-04-04 17:02:29 +0000663 if (mOverviewProxyService.isEnabled()) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800664 // Use interaction flags to show/hide navigation buttons but will be shown if required
665 // to exit screen pinning.
Matthew Ng8f25fb962018-01-16 17:17:24 -0800666 final int flags = mOverviewProxyService.getInteractionFlags();
667 disableRecent |= (flags & FLAG_SHOW_OVERVIEW_BUTTON) == 0;
Matthew Ng6ff33b72018-02-27 13:47:38 -0800668 if (pinningActive) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800669 disableBack = disableHome = false;
Matthew Ng87cbf342018-02-15 12:21:18 -0800670 }
Matthew Ng6ff33b72018-02-27 13:47:38 -0800671 } else if (pinningActive) {
Matthew Ng87cbf342018-02-15 12:21:18 -0800672 disableBack = disableRecent = false;
Matthew Ngdc79e5c2017-12-14 17:37:35 -0800673 }
Charles Hee57ff812017-10-26 10:01:35 +0100674
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800675 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
John Spurlock56d007b2013-10-28 18:40:56 -0400676 if (navButtons != null) {
677 LayoutTransition lt = navButtons.getLayoutTransition();
John Spurlock1bbd49d2012-10-19 11:09:32 -0400678 if (lt != null) {
John Spurlock56d007b2013-10-28 18:40:56 -0400679 if (!lt.getTransitionListeners().contains(mTransitionListener)) {
680 lt.addTransitionListener(mTransitionListener);
681 }
John Spurlock1bbd49d2012-10-19 11:09:32 -0400682 }
683 }
684
Jason Monka2081822016-01-18 14:41:03 -0500685 getBackButton().setVisibility(disableBack ? View.INVISIBLE : View.VISIBLE);
Jason Monk188908f2016-01-22 10:23:51 -0500686 getHomeButton().setVisibility(disableHome ? View.INVISIBLE : View.VISIBLE);
Jason Monka2081822016-01-18 14:41:03 -0500687 getRecentsButton().setVisibility(disableRecent ? View.INVISIBLE : View.VISIBLE);
John Spurlock56d007b2013-10-28 18:40:56 -0400688 }
689
Matthew Ng87cbf342018-02-15 12:21:18 -0800690 public boolean inScreenPinning() {
Matthew Ng6ff33b72018-02-27 13:47:38 -0800691 return ActivityManagerWrapper.getInstance().isScreenPinningActive();
Jason Monk17488b92014-11-06 11:26:14 -0500692 }
693
Jorim Jaggi37c11802015-08-18 20:27:54 -0700694 public void setLayoutTransitionsEnabled(boolean enabled) {
695 mLayoutTransitionsEnabled = enabled;
696 updateLayoutTransitionsEnabled();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700697 }
698
Jorim Jaggi37c11802015-08-18 20:27:54 -0700699 public void setWakeAndUnlocking(boolean wakeAndUnlocking) {
700 setUseFadingAnimations(wakeAndUnlocking);
701 mWakeAndUnlocking = wakeAndUnlocking;
702 updateLayoutTransitionsEnabled();
703 }
704
705 private void updateLayoutTransitionsEnabled() {
706 boolean enabled = !mWakeAndUnlocking && mLayoutTransitionsEnabled;
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800707 ViewGroup navButtons = (ViewGroup) getCurrentView().findViewById(R.id.nav_buttons);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700708 LayoutTransition lt = navButtons.getLayoutTransition();
Julia Reynolds8478aba2015-07-31 09:17:20 -0400709 if (lt != null) {
710 if (enabled) {
711 lt.enableTransitionType(LayoutTransition.APPEARING);
712 lt.enableTransitionType(LayoutTransition.DISAPPEARING);
713 lt.enableTransitionType(LayoutTransition.CHANGE_APPEARING);
714 lt.enableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
715 } else {
716 lt.disableTransitionType(LayoutTransition.APPEARING);
717 lt.disableTransitionType(LayoutTransition.DISAPPEARING);
718 lt.disableTransitionType(LayoutTransition.CHANGE_APPEARING);
719 lt.disableTransitionType(LayoutTransition.CHANGE_DISAPPEARING);
720 }
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700721 }
722 }
723
724 private void setUseFadingAnimations(boolean useFadingAnimations) {
Jason Monk49fa0162017-01-11 09:21:56 -0500725 WindowManager.LayoutParams lp = (WindowManager.LayoutParams) ((ViewGroup) getParent())
726 .getLayoutParams();
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700727 if (lp != null) {
728 boolean old = lp.windowAnimations != 0;
729 if (!old && useFadingAnimations) {
730 lp.windowAnimations = R.style.Animation_NavigationBarFadeIn;
731 } else if (old && !useFadingAnimations) {
732 lp.windowAnimations = 0;
733 } else {
734 return;
735 }
736 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
Jason Monk49fa0162017-01-11 09:21:56 -0500737 wm.updateViewLayout((View) getParent(), lp);
Jorim Jaggi0d210f62015-07-10 14:24:44 -0700738 }
739 }
740
Matthew Ng2ea93b72018-03-14 19:43:18 +0000741 public void onNavigationButtonLongPress(View v) {
742 mGestureHelper.onNavigationButtonLongPress(v);
743 }
744
Matthew Ng78f88d12018-01-23 12:39:55 -0800745 public void onPanelExpandedChange(boolean expanded) {
746 updateSlippery();
747 }
748
Matthew Ng8f25fb962018-01-16 17:17:24 -0800749 public void updateStates() {
Matthew Ng44b14502018-05-04 11:10:14 -0700750 final boolean showSwipeUpUI = mOverviewProxyService.shouldShowSwipeUpUI();
Mike Digmanf77fb912018-05-21 11:21:30 -0700751
752 if (mNavigationInflaterView != null) {
753 // Reinflate the navbar if needed, no-op unless the swipe up state changes
754 mNavigationInflaterView.onLikelyDefaultLayoutChange();
755 }
756
Matthew Ng8f25fb962018-01-16 17:17:24 -0800757 updateSlippery();
Winson Chung770d7e92018-03-20 17:51:39 -0700758 reloadNavIcons();
Matthew Ngd0a73e72018-03-02 15:16:03 -0800759 updateNavButtonIcons();
Winson Chungf9e30272018-03-26 17:25:36 -0700760 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Matthew Ng44b14502018-05-04 11:10:14 -0700761 WindowManagerWrapper.getInstance().setNavBarVirtualKeyHapticFeedbackEnabled(!showSwipeUpUI);
762 getHomeButton().setAccessibilityDelegate(
763 showSwipeUpUI ? mQuickStepAccessibilityDelegate : null);
Matthew Ng8f25fb962018-01-16 17:17:24 -0800764 }
765
Matthew Ng472d3e42018-06-14 15:16:55 -0700766 public void updateSlippery() {
Winson Chung770d7e92018-03-20 17:51:39 -0700767 setSlippery(!isQuickStepSwipeUpEnabled() || mPanelView.isFullyExpanded());
Matthew Ng78f88d12018-01-23 12:39:55 -0800768 }
769
Matthew Ng7d05e772017-11-09 14:41:07 -0800770 private void setSlippery(boolean slippery) {
771 boolean changed = false;
772 final ViewGroup navbarView = ((ViewGroup) getParent());
773 final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) navbarView
774 .getLayoutParams();
Matthew Ng9c3bce52018-02-01 22:00:31 +0000775 if (lp == null) {
776 return;
777 }
Matthew Ng7d05e772017-11-09 14:41:07 -0800778 if (slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) == 0) {
779 lp.flags |= WindowManager.LayoutParams.FLAG_SLIPPERY;
780 changed = true;
781 } else if (!slippery && (lp.flags & WindowManager.LayoutParams.FLAG_SLIPPERY) != 0) {
782 lp.flags &= ~WindowManager.LayoutParams.FLAG_SLIPPERY;
783 changed = true;
784 }
785 if (changed) {
786 WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE);
787 wm.updateViewLayout(navbarView, lp);
788 }
789 }
790
Daniel Sandler56598cd2011-09-15 16:02:56 -0400791 public void setMenuVisibility(final boolean show) {
792 setMenuVisibility(show, false);
793 }
794
795 public void setMenuVisibility(final boolean show, final boolean force) {
796 if (!force && mShowMenu == show) return;
797
798 mShowMenu = show;
799
Mike Digmana48cf192018-02-12 17:52:48 -0800800 // Only show Menu if IME switcher, rotate and Accessibility buttons are not shown.
801 final boolean shouldShow = mShowMenu &&
802 !mShowAccessibilityButton &&
803 !mShowRotateButton &&
Jason Monkf1ff2092014-04-29 16:50:53 -0400804 ((mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_IME_SHOWN) == 0);
Anthony Chenada13042016-01-19 16:57:20 -0800805
Jason Monka2081822016-01-18 14:41:03 -0500806 getMenuButton().setVisibility(shouldShow ? View.VISIBLE : View.INVISIBLE);
Daniel Sandler029d5872011-09-12 00:58:58 -0400807 }
808
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800809 public void setAccessibilityButtonState(final boolean visible, final boolean longClickable) {
810 mShowAccessibilityButton = visible;
811 mLongClickableAccessibilityButton = longClickable;
812 if (visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800813 // Accessibility button overrides Menu, IME switcher and rotate buttons.
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800814 setMenuVisibility(false, true);
Casey Burkhardt2464dc92017-03-28 15:52:12 -0700815 getImeSwitchButton().setVisibility(View.INVISIBLE);
Mike Digman1e28a5a2018-02-14 10:49:19 -0800816 setRotateButtonVisibility(false);
Casey Burkhardt048c2bc2016-12-08 16:09:20 -0800817 }
818
819 getAccessibilityButton().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
820 getAccessibilityButton().setLongClickable(longClickable);
821 }
822
Mike Digman1e28a5a2018-02-14 10:49:19 -0800823 public void updateRotateSuggestionButtonStyle(@StyleRes int style, boolean setIcon) {
824 mRotateBtnStyle = style;
825 final Context ctx = getContext();
826
827 // Extract the dark and light tints
828 final int dualToneDarkTheme = Utils.getThemeAttr(ctx, R.attr.darkIconTheme);
829 final int dualToneLightTheme = Utils.getThemeAttr(ctx, R.attr.lightIconTheme);
830 Context darkContext = new ContextThemeWrapper(ctx, dualToneDarkTheme);
831 Context lightContext = new ContextThemeWrapper(ctx, dualToneLightTheme);
832 final int lightColor = Utils.getColorAttr(lightContext, R.attr.singleToneColor);
833 final int darkColor = Utils.getColorAttr(darkContext, R.attr.singleToneColor);
834
835 // Use the supplied style to set the icon's rotation parameters
836 Context rotateContext = new ContextThemeWrapper(ctx, style);
837
838 // Recreate the icon and set it if needed
Mike Digmanc8217582018-03-06 13:08:33 -0800839 TintedKeyButtonDrawable priorIcon = mRotateSuggestionIcon;
Mike Digman1e28a5a2018-02-14 10:49:19 -0800840 mRotateSuggestionIcon = getDrawable(rotateContext, R.drawable.ic_sysbar_rotate_button,
841 lightColor, darkColor);
Mike Digmanc8217582018-03-06 13:08:33 -0800842
843 // Apply any prior set dark intensity
844 if (priorIcon != null && priorIcon.isDarkIntensitySet()) {
845 mRotateSuggestionIcon.setDarkIntensity(priorIcon.getDarkIntensity());
846 }
847
Mike Digman1e28a5a2018-02-14 10:49:19 -0800848 if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
Mike Digmana48cf192018-02-12 17:52:48 -0800849 }
850
Mike Digman9b50b762018-04-19 10:50:35 -0700851 public int setRotateButtonVisibility(final boolean visible) {
Mike Digmana48cf192018-02-12 17:52:48 -0800852 // Never show if a11y is visible
853 final boolean adjVisible = visible && !mShowAccessibilityButton;
854 final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
855
Mike Digman1e28a5a2018-02-14 10:49:19 -0800856 // No need to do anything if the request matches the current state
Mike Digman9b50b762018-04-19 10:50:35 -0700857 if (vis == getRotateSuggestionButton().getVisibility()) return vis;
Mike Digman1e28a5a2018-02-14 10:49:19 -0800858
Mike Digmana48cf192018-02-12 17:52:48 -0800859 getRotateSuggestionButton().setVisibility(vis);
860 mShowRotateButton = visible;
861
Mike Digman1e28a5a2018-02-14 10:49:19 -0800862 // Stop any active animations if hidden
863 if (!visible) {
864 Drawable d = mRotateSuggestionIcon.getDrawable(0);
865 if (d instanceof AnimatedVectorDrawable) {
866 AnimatedVectorDrawable avd = (AnimatedVectorDrawable) d;
867 avd.clearAnimationCallbacks();
868 avd.reset();
869 }
870 }
871
Mike Digmana48cf192018-02-12 17:52:48 -0800872 // Hide/restore other button visibility, if necessary
Matthew Ngd0a73e72018-03-02 15:16:03 -0800873 updateNavButtonIcons();
Mike Digman9b50b762018-04-19 10:50:35 -0700874
875 // Return applied visibility
876 return vis;
Mike Digmana48cf192018-02-12 17:52:48 -0800877 }
878
Mike Digman1e28a5a2018-02-14 10:49:19 -0800879 public boolean isRotateButtonVisible() { return mShowRotateButton; }
880
Winson Chung661d5f92018-05-21 18:41:39 -0700881 /**
882 * @return the button at the given {@param x} and {@param y}.
883 */
884 ButtonDispatcher getButtonAtPosition(int x, int y) {
885 for (int i = 0; i < mButtonDispatchers.size(); i++) {
886 ButtonDispatcher button = mButtonDispatchers.valueAt(i);
887 View buttonView = button.getCurrentView();
888 if (buttonView != null) {
889 buttonView.getHitRect(mTmpRect);
890 offsetDescendantRectToMyCoords(buttonView, mTmpRect);
891 if (mTmpRect.contains(x, y)) {
892 return button;
893 }
894 }
895 }
896 return null;
Matthew Ng6607c3d2018-04-26 15:23:27 -0700897 }
898
Jim Miller960892c2012-05-23 15:50:04 -0700899 @Override
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400900 public void onFinishInflate() {
Winson Chung661d5f92018-05-21 18:41:39 -0700901 mNavigationInflaterView = findViewById(R.id.navigation_inflater);
Felipe Leme15f915c2016-10-31 12:47:15 -0700902 mNavigationInflaterView.setButtonDispatchers(mButtonDispatchers);
Jason Monka2081822016-01-18 14:41:03 -0500903
904 getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
Selim Cinek17a327a2014-08-25 15:03:48 +0200905
Jason Monk32e3bb52017-07-27 12:35:41 -0400906 DockedStackExistsListener.register(mDockedListener);
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700907 updateRotatedViews();
Jorim Jaggia6c934e2015-12-21 13:22:31 +0100908 }
909
Matthew Nga8f24262017-12-19 11:54:24 -0800910 public void onDarkIntensityChange(float intensity) {
911 if (mGestureHelper != null) {
912 mGestureHelper.onDarkIntensityChange(intensity);
913 }
914 }
915
916 @Override
917 protected void onDraw(Canvas canvas) {
918 mGestureHelper.onDraw(canvas);
Matthew Ng603b3292018-03-30 17:15:39 -0700919 mDeadZone.onDraw(canvas);
Matthew Nga8f24262017-12-19 11:54:24 -0800920 super.onDraw(canvas);
921 }
922
923 @Override
924 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
925 super.onLayout(changed, left, top, right, bottom);
Winson Chungc4e06202018-02-13 10:37:35 -0800926 updateButtonLocationOnScreen(getBackButton(), mBackButtonBounds);
927 updateButtonLocationOnScreen(getHomeButton(), mHomeButtonBounds);
Matthew Ng8a8c89c2018-03-01 13:21:43 -0800928 updateButtonLocationOnScreen(getRecentsButton(), mRecentsButtonBounds);
Winson Chung8079af72018-05-10 11:12:55 -0700929 updateButtonLocationOnScreen(getRotateSuggestionButton(), mRotationButtonBounds);
Matthew Nga8f24262017-12-19 11:54:24 -0800930 mGestureHelper.onLayout(changed, left, top, right, bottom);
Tracy Zhou559d97c2018-04-07 23:54:46 -0700931 mRecentsOnboarding.setNavBarHeight(getMeasuredHeight());
Matthew Nga8f24262017-12-19 11:54:24 -0800932 }
933
Winson Chungc4e06202018-02-13 10:37:35 -0800934 private void updateButtonLocationOnScreen(ButtonDispatcher button, Rect buttonBounds) {
935 View view = button.getCurrentView();
936 if (view == null) {
937 buttonBounds.setEmpty();
938 return;
939 }
Matthew Ng3b7e3902018-03-22 16:06:09 -0700940 // Temporarily reset the translation back to origin to get the position in window
941 final float posX = view.getTranslationX();
942 final float posY = view.getTranslationY();
943 view.setTranslationX(0);
944 view.setTranslationY(0);
Winson Chungc4e06202018-02-13 10:37:35 -0800945 view.getLocationInWindow(mTmpPosition);
946 buttonBounds.set(mTmpPosition[0], mTmpPosition[1],
947 mTmpPosition[0] + view.getMeasuredWidth(),
948 mTmpPosition[1] + view.getMeasuredHeight());
Matthew Ng3b7e3902018-03-22 16:06:09 -0700949 view.setTranslationX(posX);
950 view.setTranslationY(posY);
Winson Chungc4e06202018-02-13 10:37:35 -0800951 }
952
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700953 private void updateRotatedViews() {
Jason Monk9a6552d2016-05-20 11:21:59 -0400954 mRotatedViews[Surface.ROTATION_0] =
955 mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
956 mRotatedViews[Surface.ROTATION_270] =
957 mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
958
Jason Monk199a2d02017-07-28 11:08:27 -0400959 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400960 }
961
Adrian Roosa98b32c2016-08-11 10:41:08 -0700962 public boolean needsReorient(int rotation) {
963 return mCurrentRotation != rotation;
Adrian Roos090b7d82016-08-02 18:36:12 -0700964 }
965
Jason Monk199a2d02017-07-28 11:08:27 -0400966 private void updateCurrentView() {
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400967 final int rot = mDisplay.getRotation();
968 for (int i=0; i<4; i++) {
969 mRotatedViews[i].setVisibility(View.GONE);
970 }
Daniel Sandler5c8da942011-06-28 00:29:04 -0400971 mCurrentView = mRotatedViews[rot];
972 mCurrentView.setVisibility(View.VISIBLE);
Adrian Roosdb12b152016-07-12 15:38:55 -0700973 mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
Matthew Ng1efc9c32018-04-11 18:13:56 -0700974 mNavigationInflaterView.updateButtonDispatchersCurrentView();
Jorim Jaggi37c11802015-08-18 20:27:54 -0700975 updateLayoutTransitionsEnabled();
Adrian Roos090b7d82016-08-02 18:36:12 -0700976 mCurrentRotation = rot;
Jason Monk9a6552d2016-05-20 11:21:59 -0400977 }
978
979 private void updateRecentsIcon() {
Matthew Ngeb5ce832018-05-15 17:50:37 -0700980 mDockedIcon.setRotation(mDockedStackExists && mVertical ? 90 : 0);
Jason Monk9a6552d2016-05-20 11:21:59 -0400981 getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
Jorim Jaggi40db0292016-06-27 17:58:03 -0700982 mBarTransitions.reapplyDarkIntensity();
Jason Monk9a6552d2016-05-20 11:21:59 -0400983 }
984
985 public boolean isVertical() {
986 return mVertical;
987 }
988
989 public void reorient() {
Jason Monk199a2d02017-07-28 11:08:27 -0400990 updateCurrentView();
Daniel Sandler8956dbb2011-04-22 07:55:02 -0400991
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -0700992 ((NavigationBarFrame) getRootView()).setDeadZone(mDeadZone);
Matthew Ng603b3292018-03-30 17:15:39 -0700993 mDeadZone.onConfigurationChanged(mCurrentRotation);
Daniel Sandlerc26185b2012-08-29 15:49:53 -0400994
Daniel Sandler6da2b762011-09-14 16:04:59 -0400995 // force the low profile & disabled states into compliance
Adrian Roos8a8ffd42015-05-26 18:30:37 -0700996 mBarTransitions.init();
Daniel Sandler56598cd2011-09-15 16:02:56 -0400997 setMenuVisibility(mShowMenu, true /* force */);
Daniel Sandler6da2b762011-09-14 16:04:59 -0400998
Daniel Sandler60ee2562011-07-22 12:34:33 -0400999 if (DEBUG) {
Adrian Roosa98b32c2016-08-11 10:41:08 -07001000 Log.d(TAG, "reorient(): rot=" + mCurrentRotation);
Daniel Sandler60ee2562011-07-22 12:34:33 -04001001 }
Michael Jurkaa5d0ddb2012-03-09 17:41:41 -08001002
Matthew Ng5fd80412018-02-14 14:40:31 -08001003 // Resolve layout direction if not resolved since components changing layout direction such
1004 // as changing languages will recreate this view and the direction will be resolved later
1005 if (!isLayoutDirectionResolved()) {
1006 resolveLayoutDirection();
1007 }
Selim Cinek92d892c2014-09-11 15:11:00 +02001008 updateTaskSwitchHelper();
Matthew Ngd0a73e72018-03-02 15:16:03 -08001009 updateNavButtonIcons();
Xiaohui Chen9efa5de2016-11-22 10:34:38 -08001010
Xiaohui Chen40e978e2016-11-29 15:10:04 -08001011 getHomeButton().setVertical(mVertical);
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001012 }
Daniel Sandler48852952011-12-01 14:34:23 -05001013
Selim Cinek92d892c2014-09-11 15:11:00 +02001014 private void updateTaskSwitchHelper() {
Jason Monkde850bb2017-02-01 19:26:30 -05001015 if (mGestureHelper == null) return;
Selim Cinek92d892c2014-09-11 15:11:00 +02001016 boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
Jorim Jaggidd98d412015-11-18 15:57:38 -08001017 mGestureHelper.setBarState(mVertical, isRtl);
Selim Cinek92d892c2014-09-11 15:11:00 +02001018 }
1019
Daniel Sandler0b69b592012-01-23 21:08:36 -05001020 @Override
1021 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
John Spurlockcd686b52013-06-05 10:13:46 -04001022 if (DEBUG) Log.d(TAG, String.format(
Daniel Sandler0b69b592012-01-23 21:08:36 -05001023 "onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
Daniel Sandlere03bc952012-04-27 16:11:22 -04001024
1025 final boolean newVertical = w > 0 && h > w;
1026 if (newVertical != mVertical) {
1027 mVertical = newVertical;
John Spurlockcd686b52013-06-05 10:13:46 -04001028 //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
Daniel Sandlere03bc952012-04-27 16:11:22 -04001029 reorient();
Selim Cinek92d892c2014-09-11 15:11:00 +02001030 notifyVerticalChangedListener(newVertical);
Daniel Sandlere03bc952012-04-27 16:11:22 -04001031 }
1032
Daniel Sandler0b69b592012-01-23 21:08:36 -05001033 postCheckForInvalidLayout("sizeChanged");
1034 super.onSizeChanged(w, h, oldw, oldh);
1035 }
1036
Selim Cinek92d892c2014-09-11 15:11:00 +02001037 private void notifyVerticalChangedListener(boolean newVertical) {
1038 if (mOnVerticalChangedListener != null) {
1039 mOnVerticalChangedListener.onVerticalChanged(newVertical);
1040 }
1041 }
1042
Selim Cinek17a327a2014-08-25 15:03:48 +02001043 @Override
1044 protected void onConfigurationChanged(Configuration newConfig) {
1045 super.onConfigurationChanged(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001046 boolean uiCarModeChanged = updateCarMode(newConfig);
Selim Cinek92d892c2014-09-11 15:11:00 +02001047 updateTaskSwitchHelper();
Winsonfde2e6a2016-03-22 16:03:10 -07001048 updateIcons(getContext(), mConfiguration, newConfig);
1049 updateRecentsIcon();
Tony Wickham05c1f852018-02-06 12:32:54 -08001050 mRecentsOnboarding.onConfigurationChanged(newConfig);
Jason Monk1f785d42017-07-25 15:46:33 -04001051 if (uiCarModeChanged || mConfiguration.densityDpi != newConfig.densityDpi
1052 || mConfiguration.getLayoutDirection() != newConfig.getLayoutDirection()) {
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001053 // If car mode or density changes, we need to reset the icons.
Matthew Ngd0a73e72018-03-02 15:16:03 -08001054 updateNavButtonIcons();
Jorim Jaggi11c62e12016-04-05 20:41:21 -07001055 }
Winsonfde2e6a2016-03-22 16:03:10 -07001056 mConfiguration.updateFrom(newConfig);
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001057 }
1058
1059 /**
1060 * If the configuration changed, update the carmode and return that it was updated.
1061 */
1062 private boolean updateCarMode(Configuration newConfig) {
1063 boolean uiCarModeChanged = false;
1064 if (newConfig != null) {
1065 int uiMode = newConfig.uiMode & Configuration.UI_MODE_TYPE_MASK;
Justin Paupore01915a12016-09-28 17:41:26 -07001066 final boolean isCarMode = (uiMode == Configuration.UI_MODE_TYPE_CAR);
1067
1068 if (isCarMode != mInCarMode) {
1069 mInCarMode = isCarMode;
Justin Paupore01915a12016-09-28 17:41:26 -07001070 if (ALTERNATE_CAR_MODE_UI) {
1071 mUseCarModeUi = isCarMode;
1072 uiCarModeChanged = true;
1073 } else {
1074 // Don't use car mode behavior if ALTERNATE_CAR_MODE_UI not set.
1075 mUseCarModeUi = false;
1076 }
Sriram Viswanathan9ebbe6a2015-11-16 17:59:22 -08001077 }
1078 }
1079 return uiCarModeChanged;
Selim Cinek17a327a2014-08-25 15:03:48 +02001080 }
1081
Daniel Sandler0b69b592012-01-23 21:08:36 -05001082 /*
1083 @Override
1084 protected void onLayout (boolean changed, int left, int top, int right, int bottom) {
John Spurlockcd686b52013-06-05 10:13:46 -04001085 if (DEBUG) Log.d(TAG, String.format(
John Spurlock209bede2013-07-17 12:23:27 -04001086 "onLayout: %s (%d,%d,%d,%d)",
Daniel Sandler0b69b592012-01-23 21:08:36 -05001087 changed?"changed":"notchanged", left, top, right, bottom));
1088 super.onLayout(changed, left, top, right, bottom);
1089 }
1090
1091 // uncomment this for extra defensiveness in WORKAROUND_INVALID_LAYOUT situations: if all else
1092 // fails, any touch on the display will fix the layout.
1093 @Override
1094 public boolean onInterceptTouchEvent(MotionEvent ev) {
John Spurlockcd686b52013-06-05 10:13:46 -04001095 if (DEBUG) Log.d(TAG, "onInterceptTouchEvent: " + ev.toString());
Daniel Sandler0b69b592012-01-23 21:08:36 -05001096 if (ev.getAction() == MotionEvent.ACTION_DOWN) {
1097 postCheckForInvalidLayout("touch");
1098 }
1099 return super.onInterceptTouchEvent(ev);
1100 }
1101 */
John Spurlock209bede2013-07-17 12:23:27 -04001102
Daniel Sandler0b69b592012-01-23 21:08:36 -05001103
Daniel Sandler48852952011-12-01 14:34:23 -05001104 private String getResourceName(int resId) {
1105 if (resId != 0) {
John Spurlock01534782014-01-13 11:59:22 -05001106 final android.content.res.Resources res = getContext().getResources();
Daniel Sandler48852952011-12-01 14:34:23 -05001107 try {
1108 return res.getResourceName(resId);
1109 } catch (android.content.res.Resources.NotFoundException ex) {
1110 return "(unknown)";
1111 }
1112 } else {
1113 return "(null)";
1114 }
1115 }
1116
Daniel Sandler0b69b592012-01-23 21:08:36 -05001117 private void postCheckForInvalidLayout(final String how) {
1118 mHandler.obtainMessage(MSG_CHECK_INVALID_LAYOUT, 0, 0, how).sendToTarget();
1119 }
1120
Daniel Sandler48852952011-12-01 14:34:23 -05001121 private static String visibilityToString(int vis) {
1122 switch (vis) {
1123 case View.INVISIBLE:
1124 return "INVISIBLE";
1125 case View.GONE:
1126 return "GONE";
1127 default:
1128 return "VISIBLE";
1129 }
1130 }
1131
Jason Monk67e6c802016-08-30 14:09:21 -04001132 @Override
1133 protected void onAttachedToWindow() {
1134 super.onAttachedToWindow();
Adrian Roos7e58a082018-03-09 16:40:56 +01001135 requestApplyInsets();
Siarhei Vishniakoufdb42772017-06-29 10:32:11 -07001136 reorient();
Jason Monkde850bb2017-02-01 19:26:30 -05001137 onPluginDisconnected(null); // Create default gesture helper
Jason Monk5bec68f2017-02-08 20:45:10 -08001138 Dependency.get(PluginManager.class).addPluginListener(this,
1139 NavGesture.class, false /* Only one */);
Winson Chungf9e30272018-03-26 17:25:36 -07001140 setUpSwipeUpOnboarding(isQuickStepSwipeUpEnabled());
Jason Monk67e6c802016-08-30 14:09:21 -04001141 }
1142
1143 @Override
1144 protected void onDetachedFromWindow() {
1145 super.onDetachedFromWindow();
Jason Monkde850bb2017-02-01 19:26:30 -05001146 Dependency.get(PluginManager.class).removePluginListener(this);
1147 if (mGestureHelper != null) {
1148 mGestureHelper.destroy();
1149 }
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001150 setUpSwipeUpOnboarding(false);
1151 }
1152
1153 private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
1154 if (connectedToOverviewProxy) {
Tony Wickham05c1f852018-02-06 12:32:54 -08001155 mRecentsOnboarding.onConnectedToLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001156 } else {
Tony Wickham05c1f852018-02-06 12:32:54 -08001157 mRecentsOnboarding.onDisconnectedFromLauncher();
Tony Wickhamfb63fe82018-01-16 12:14:06 -08001158 }
Jason Monk67e6c802016-08-30 14:09:21 -04001159 }
1160
1161 @Override
Jason Monk20ff3f92017-01-09 15:13:23 -05001162 public void onPluginConnected(NavGesture plugin, Context context) {
Jason Monk67e6c802016-08-30 14:09:21 -04001163 mGestureHelper = plugin.getGestureHelper();
1164 updateTaskSwitchHelper();
1165 }
1166
1167 @Override
1168 public void onPluginDisconnected(NavGesture plugin) {
1169 NavigationBarGestureHelper defaultHelper = new NavigationBarGestureHelper(getContext());
1170 defaultHelper.setComponents(mRecentsComponent, mDivider, this);
Jason Monkde850bb2017-02-01 19:26:30 -05001171 if (mGestureHelper != null) {
1172 mGestureHelper.destroy();
1173 }
Jason Monk67e6c802016-08-30 14:09:21 -04001174 mGestureHelper = defaultHelper;
1175 updateTaskSwitchHelper();
1176 }
1177
Daniel Sandler48852952011-12-01 14:34:23 -05001178 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1179 pw.println("NavigationBarView {");
1180 final Rect r = new Rect();
Jeff Browna8b9def2012-07-23 14:22:49 -07001181 final Point size = new Point();
1182 mDisplay.getRealSize(size);
Daniel Sandler48852952011-12-01 14:34:23 -05001183
Jason Monk2a6ea9c2017-01-26 11:14:51 -05001184 pw.println(String.format(" this: " + StatusBar.viewInfo(this)
Daniel Sandler48852952011-12-01 14:34:23 -05001185 + " " + visibilityToString(getVisibility())));
1186
1187 getWindowVisibleDisplayFrame(r);
Jeff Browna8b9def2012-07-23 14:22:49 -07001188 final boolean offscreen = r.right > size.x || r.bottom > size.y;
John Spurlock209bede2013-07-17 12:23:27 -04001189 pw.println(" window: "
Daniel Sandler48852952011-12-01 14:34:23 -05001190 + r.toShortString()
1191 + " " + visibilityToString(getWindowVisibility())
1192 + (offscreen ? " OFFSCREEN!" : ""));
1193
Winson Chung661d5f92018-05-21 18:41:39 -07001194 pw.println(String.format(" mCurrentView: id=%s (%dx%d) %s %f",
Rakesh Iyerf51fe4e2016-02-09 10:51:50 -08001195 getResourceName(getCurrentView().getId()),
1196 getCurrentView().getWidth(), getCurrentView().getHeight(),
Winson Chung661d5f92018-05-21 18:41:39 -07001197 visibilityToString(getCurrentView().getVisibility()),
1198 getCurrentView().getAlpha()));
Daniel Sandler48852952011-12-01 14:34:23 -05001199
John Spurlock41c1e352013-09-16 13:57:13 -04001200 pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s",
Daniel Sandler48852952011-12-01 14:34:23 -05001201 mDisabledFlags,
1202 mVertical ? "true" : "false",
Daniel Sandler48852952011-12-01 14:34:23 -05001203 mShowMenu ? "true" : "false"));
1204
John Spurlock56d007b2013-10-28 18:40:56 -04001205 dumpButton(pw, "back", getBackButton());
1206 dumpButton(pw, "home", getHomeButton());
1207 dumpButton(pw, "rcnt", getRecentsButton());
1208 dumpButton(pw, "menu", getMenuButton());
Casey Burkhardt048c2bc2016-12-08 16:09:20 -08001209 dumpButton(pw, "a11y", getAccessibilityButton());
Daniel Sandler48852952011-12-01 14:34:23 -05001210
Tracy Zhou66efefd2018-05-16 15:03:09 -07001211 mRecentsOnboarding.dump(pw);
1212
Daniel Sandler48852952011-12-01 14:34:23 -05001213 pw.println(" }");
1214 }
Jim Millere898ac52012-04-06 17:10:57 -07001215
Adrian Roos7e58a082018-03-09 16:40:56 +01001216 @Override
1217 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
1218 setPadding(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
1219 insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
1220 return super.onApplyWindowInsets(insets);
1221 }
1222
Jason Monka2081822016-01-18 14:41:03 -05001223 private static void dumpButton(PrintWriter pw, String caption, ButtonDispatcher button) {
John Spurlock56d007b2013-10-28 18:40:56 -04001224 pw.print(" " + caption + ": ");
1225 if (button == null) {
1226 pw.print("null");
1227 } else {
Jason Monka2081822016-01-18 14:41:03 -05001228 pw.print(visibilityToString(button.getVisibility())
John Spurlock56d007b2013-10-28 18:40:56 -04001229 + " alpha=" + button.getAlpha()
1230 );
John Spurlock56d007b2013-10-28 18:40:56 -04001231 }
1232 pw.println();
1233 }
1234
Jorim Jaggif4797922014-08-04 22:49:41 +02001235 public interface OnVerticalChangedListener {
1236 void onVerticalChanged(boolean isVertical);
1237 }
Jason Monka2081822016-01-18 14:41:03 -05001238
Jason Monk32e3bb52017-07-27 12:35:41 -04001239 private final Consumer<Boolean> mDockedListener = exists -> mHandler.post(() -> {
1240 mDockedStackExists = exists;
1241 updateRecentsIcon();
1242 });
Daniel Sandler8956dbb2011-04-22 07:55:02 -04001243}