blob: 369bb9fdd9ddce1e84ff766bb47b6759d53817f7 [file] [log] [blame]
Rakesh Iyer1186faa2015-12-07 16:48:46 -08001/*
Brad Stenning8d1a51c2018-11-20 17:34:16 -08002 * Copyright (C) 2018 The Android Open Source Project
Rakesh Iyer1186faa2015-12-07 16:48:46 -08003 *
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.car;
18
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070019import android.app.ActivityTaskManager;
jovanakedba98c2018-09-14 15:46:24 -070020import android.car.drivingstate.CarDrivingStateEvent;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080021import android.graphics.PixelFormat;
Anthony Chene658cc22017-04-27 11:17:35 -070022import android.graphics.drawable.Drawable;
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080023import android.util.Log;
Brad Stenning078235b2017-12-18 08:25:10 -080024import android.view.Gravity;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080025import android.view.View;
Anthony Chen0801a5c2017-03-22 09:54:37 -070026import android.view.ViewGroup;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080027import android.view.ViewGroup.LayoutParams;
28import android.view.WindowManager;
Anthony Chene658cc22017-04-27 11:17:35 -070029
Winson Chung2db35572017-10-09 15:08:30 -070030import com.android.keyguard.KeyguardUpdateMonitor;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070031import com.android.systemui.BatteryMeterView;
Jason Monk27d01a622018-12-10 15:57:09 -050032import com.android.systemui.CarSystemUIFactory;
Jason Monk9c7844c2017-01-18 15:21:53 -050033import com.android.systemui.Dependency;
Winson Chung2db35572017-10-09 15:08:30 -070034import com.android.systemui.Prefs;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080035import com.android.systemui.R;
Jason Monk27d01a622018-12-10 15:57:09 -050036import com.android.systemui.SystemUIFactory;
Winson Chung2db35572017-10-09 15:08:30 -070037import com.android.systemui.classifier.FalsingLog;
38import com.android.systemui.classifier.FalsingManager;
Jason Monkaa573e92017-01-27 17:00:29 -050039import com.android.systemui.fragments.FragmentHostManager;
Brad Stenning19f236a2018-12-11 14:12:30 -080040import com.android.systemui.notifications.NotificationsUI;
Brad Stenning8d1a51c2018-11-20 17:34:16 -080041import com.android.systemui.plugins.qs.QS;
42import com.android.systemui.qs.car.CarQSFragment;
Winson Chungb05b3982017-11-01 18:02:43 -070043import com.android.systemui.shared.system.ActivityManagerWrapper;
Winson Chung67f5c8b2018-09-24 12:09:19 -070044import com.android.systemui.shared.system.TaskStackChangeListener;
Rakesh Iyer2790a372016-01-22 15:33:39 -080045import com.android.systemui.statusbar.StatusBarState;
Brad Stenning38b46f82018-03-27 13:57:29 -070046import com.android.systemui.statusbar.car.hvac.HvacController;
Brad Stenningf084d882018-08-08 13:34:21 -070047import com.android.systemui.statusbar.car.hvac.TemperatureView;
Jason Monkaa573e92017-01-27 17:00:29 -050048import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050049import com.android.systemui.statusbar.phone.StatusBar;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070050import com.android.systemui.statusbar.policy.BatteryController;
Brad Stenning224b5b32018-03-28 21:26:57 -070051import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Jason Monk9c7844c2017-01-18 15:21:53 -050052import com.android.systemui.statusbar.policy.UserSwitcherController;
Rakesh Iyer1186faa2015-12-07 16:48:46 -080053
Qiming Shib9dfb922017-04-13 16:23:18 +080054import java.io.FileDescriptor;
55import java.io.PrintWriter;
56import java.util.Map;
davidln54739152018-07-02 13:25:44 -070057
Rakesh Iyer1186faa2015-12-07 16:48:46 -080058/**
59 * A status bar (and navigation bar) tailored for the automotive use case.
60 */
Jason Monk2a6ea9c2017-01-26 11:14:51 -050061public class CarStatusBar extends StatusBar implements
Anthony Chenda62fdcd52016-04-06 16:15:14 -070062 CarBatteryController.BatteryViewHandler {
Rakesh Iyer74ebabe2016-03-11 10:10:43 -080063 private static final String TAG = "CarStatusBar";
64
Victor Chan1c6d0582016-01-09 16:26:37 -080065 private TaskStackListenerImpl mTaskStackListener;
Victor Chan1c6d0582016-01-09 16:26:37 -080066
Rakesh Iyer2790a372016-01-22 15:33:39 -080067 private FullscreenUserSwitcher mFullscreenUserSwitcher;
Victor Chan1c6d0582016-01-09 16:26:37 -080068
Anthony Chenda62fdcd52016-04-06 16:15:14 -070069 private CarBatteryController mCarBatteryController;
70 private BatteryMeterView mBatteryMeterView;
Anthony Chene658cc22017-04-27 11:17:35 -070071 private Drawable mNotificationPanelBackground;
Anthony Chenda62fdcd52016-04-06 16:15:14 -070072
Anthony Chen1c59e9f2016-04-11 11:05:48 -070073 private ConnectedDeviceSignalController mConnectedDeviceSignalController;
Scott Randolphf4085822017-06-27 15:23:01 -070074 private ViewGroup mNavigationBarWindow;
Brad Stenning078235b2017-12-18 08:25:10 -080075 private ViewGroup mLeftNavigationBarWindow;
76 private ViewGroup mRightNavigationBarWindow;
Jason Monk49fa0162017-01-11 09:21:56 -050077 private CarNavigationBarView mNavigationBarView;
Brad Stenning078235b2017-12-18 08:25:10 -080078 private CarNavigationBarView mLeftNavigationBarView;
79 private CarNavigationBarView mRightNavigationBarView;
Anthony Chen1c59e9f2016-04-11 11:05:48 -070080
Qiming Shib9dfb922017-04-13 16:23:18 +080081 private final Object mQueueLock = new Object();
Brad Stenning078235b2017-12-18 08:25:10 -080082 private boolean mShowLeft;
83 private boolean mShowRight;
84 private boolean mShowBottom;
85 private CarFacetButtonController mCarFacetButtonController;
Brad Stenning224b5b32018-03-28 21:26:57 -070086 private ActivityManagerWrapper mActivityManagerWrapper;
87 private DeviceProvisionedController mDeviceProvisionedController;
88 private boolean mDeviceIsProvisioned = true;
Brad Stenningf084d882018-08-08 13:34:21 -070089 private HvacController mHvacController;
jovanakedba98c2018-09-14 15:46:24 -070090 private DrivingStateHelper mDrivingStateHelper;
91 private SwitchToGuestTimer mSwitchToGuestTimer;
Brad Stenning078235b2017-12-18 08:25:10 -080092
Victor Chan1c6d0582016-01-09 16:26:37 -080093 @Override
94 public void start() {
95 super.start();
Jaewan Kim938a50b2016-03-14 17:35:43 +090096 mTaskStackListener = new TaskStackListenerImpl();
Brad Stenning224b5b32018-03-28 21:26:57 -070097 mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
98 mActivityManagerWrapper.registerTaskStackListener(mTaskStackListener);
Anthony Chenda62fdcd52016-04-06 16:15:14 -070099
Jason Monke59dc402018-08-16 12:05:01 -0400100 mNotificationPanel.setScrollingEnabled(true);
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800101
Rakesh Iyer545e47d2017-01-23 18:10:21 -0800102 createBatteryController();
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700103 mCarBatteryController.startListening();
Brad Stenning38b46f82018-03-27 13:57:29 -0700104
Brad Stenningf084d882018-08-08 13:34:21 -0700105 mHvacController.connectToCarService();
davidln54739152018-07-02 13:25:44 -0700106
Jason Monk27d01a622018-12-10 15:57:09 -0500107 CarSystemUIFactory factory = SystemUIFactory.getInstance();
Brad Stenning224b5b32018-03-28 21:26:57 -0700108 mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
109 mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
110 if (!mDeviceIsProvisioned) {
111 mDeviceProvisionedController.addCallback(
112 new DeviceProvisionedController.DeviceProvisionedListener() {
113 @Override
114 public void onDeviceProvisionedChanged() {
Brad Stenninga2d87d82019-01-24 12:33:10 -0800115 mHandler.post(() -> {
116 // on initial boot we are getting a call even though the value
117 // is the same so we are confirming the reset is needed
118 boolean deviceProvisioned =
119 mDeviceProvisionedController.isDeviceProvisioned();
120 if (mDeviceIsProvisioned != deviceProvisioned) {
121 mDeviceIsProvisioned = deviceProvisioned;
122 restartNavBars();
123 }
124 });
Brad Stenning224b5b32018-03-28 21:26:57 -0700125 }
126 });
127 }
jovanakedba98c2018-09-14 15:46:24 -0700128
129 // Register a listener for driving state changes.
130 mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
131 mDrivingStateHelper.connectToCarService();
132
133 mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700134 }
135
Brad Stenning224b5b32018-03-28 21:26:57 -0700136 /**
137 * Remove all content from navbars and rebuild them. Used to allow for different nav bars
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800138 * before and after the device is provisioned. . Also for change of density and font size.
Brad Stenning224b5b32018-03-28 21:26:57 -0700139 */
140 private void restartNavBars() {
Brad Stenningf084d882018-08-08 13:34:21 -0700141 // remove and reattach all hvac components such that we don't keep a reference to unused
142 // ui elements
143 mHvacController.removeAllComponents();
144 addTemperatureViewToController(mStatusBarWindow);
Brad Stenning224b5b32018-03-28 21:26:57 -0700145 mCarFacetButtonController.removeAll();
Brad Stenning224b5b32018-03-28 21:26:57 -0700146 if (mNavigationBarWindow != null) {
147 mNavigationBarWindow.removeAllViews();
148 mNavigationBarView = null;
149 }
150
151 if (mLeftNavigationBarWindow != null) {
152 mLeftNavigationBarWindow.removeAllViews();
153 mLeftNavigationBarView = null;
154 }
155
156 if (mRightNavigationBarWindow != null) {
157 mRightNavigationBarWindow.removeAllViews();
158 mRightNavigationBarView = null;
159 }
Brad Stenningf084d882018-08-08 13:34:21 -0700160
Brad Stenning224b5b32018-03-28 21:26:57 -0700161 buildNavBarContent();
162 }
163
Brad Stenningf084d882018-08-08 13:34:21 -0700164 private void addTemperatureViewToController(View v) {
165 if (v instanceof TemperatureView) {
166 Log.d(TAG, "addTemperatureViewToController: found ");
167 mHvacController.addHvacTextView((TemperatureView) v);
168 } else if (v instanceof ViewGroup) {
169 ViewGroup viewGroup = (ViewGroup) v;
170 for (int i = 0; i < viewGroup.getChildCount(); i++) {
171 addTemperatureViewToController(viewGroup.getChildAt(i));
172 }
173 }
174 }
175
Brad Stenning7e411812018-04-13 22:52:39 -0700176 /**
177 * Allows for showing or hiding just the navigation bars. This is indented to be used when
178 * the full screen user selector is shown.
179 */
davidln54739152018-07-02 13:25:44 -0700180 void setNavBarVisibility(@View.Visibility int visibility) {
Brad Stenning7e411812018-04-13 22:52:39 -0700181 if (mNavigationBarWindow != null) {
182 mNavigationBarWindow.setVisibility(visibility);
183 }
184 if (mLeftNavigationBarWindow != null) {
185 mLeftNavigationBarWindow.setVisibility(visibility);
186 }
187 if (mRightNavigationBarWindow != null) {
188 mRightNavigationBarWindow.setVisibility(visibility);
189 }
190 }
191
192
193 @Override
194 public boolean hideKeyguard() {
195 boolean result = super.hideKeyguard();
196 if (mNavigationBarView != null) {
197 mNavigationBarView.hideKeyguardButtons();
198 }
199 if (mLeftNavigationBarView != null) {
200 mLeftNavigationBarView.hideKeyguardButtons();
201 }
202 if (mRightNavigationBarView != null) {
203 mRightNavigationBarView.hideKeyguardButtons();
204 }
205 return result;
206 }
207
208
209 @Override
210 public void showKeyguard() {
211 super.showKeyguard();
Brad Stenningc622f1d2019-01-29 11:24:11 -0800212 getComponent(NotificationsUI.class).closeCarNotifications(0);
Brad Stenning7e411812018-04-13 22:52:39 -0700213 if (mNavigationBarView != null) {
214 mNavigationBarView.showKeyguardButtons();
215 }
216 if (mLeftNavigationBarView != null) {
217 mLeftNavigationBarView.showKeyguardButtons();
218 }
219 if (mRightNavigationBarView != null) {
220 mRightNavigationBarView.showKeyguardButtons();
221 }
222 }
Brad Stenning224b5b32018-03-28 21:26:57 -0700223
Brad Stenning224b5b32018-03-28 21:26:57 -0700224
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700225 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500226 protected void makeStatusBarView() {
227 super.makeStatusBarView();
Jason Monk27d01a622018-12-10 15:57:09 -0500228 mHvacController = new HvacController(mContext);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700229
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800230 CarSystemUIFactory factory = SystemUIFactory.getInstance();
231 mCarFacetButtonController = factory.getCarDependencyComponent()
232 .getCarFacetButtonController();
Anthony Chene658cc22017-04-27 11:17:35 -0700233 mNotificationPanelBackground = getDefaultWallpaper();
234 mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
235
Jason Monkaa573e92017-01-27 17:00:29 -0500236 FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow);
237 manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
Anthony Chene658cc22017-04-27 11:17:35 -0700238 mBatteryMeterView = fragment.getView().findViewById(R.id.battery);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700239
Jason Monkaa573e92017-01-27 17:00:29 -0500240 // By default, the BatteryMeterView should not be visible. It will be toggled
241 // when a device has connected by bluetooth.
242 mBatteryMeterView.setVisibility(View.GONE);
Jason Monkaa573e92017-01-27 17:00:29 -0500243 });
Brad Stenningf084d882018-08-08 13:34:21 -0700244 addTemperatureViewToController(mStatusBarWindow);
Brad Stenningc622f1d2019-01-29 11:24:11 -0800245 // The following are the ui elements that the user would call the status bar.
246 // This will set the status bar so it they can make call backs.
247 CarNavigationBarView topBar = mStatusBarWindow.findViewById(R.id.car_top_bar);
248 topBar.setStatusBar(this);
249 CarNavigationBarView qsTopBar = mStatusBarWindow.findViewById(R.id.qs_car_top_bar);
250 qsTopBar.setStatusBar(this);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700251 }
252
Brad Stenning8d1a51c2018-11-20 17:34:16 -0800253 @Override
254 protected QS createDefaultQSFragment() {
255 return new CarQSFragment();
256 }
257
Rakesh Iyer545e47d2017-01-23 18:10:21 -0800258 private BatteryController createBatteryController() {
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700259 mCarBatteryController = new CarBatteryController(mContext);
260 mCarBatteryController.addBatteryViewHandler(this);
261 return mCarBatteryController;
Victor Chan1c6d0582016-01-09 16:26:37 -0800262 }
263
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800264 @Override
Jason Monk49fa0162017-01-11 09:21:56 -0500265 protected void createNavigationBar() {
Brad Stenning078235b2017-12-18 08:25:10 -0800266 mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
Brad Stenning078235b2017-12-18 08:25:10 -0800267 mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
Brad Stenning078235b2017-12-18 08:25:10 -0800268 mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
269
Brad Stenning224b5b32018-03-28 21:26:57 -0700270 buildNavBarWindows();
271 buildNavBarContent();
272 attachNavBarWindows();
Andrii Kulian3ddd7de2018-10-10 00:33:19 -0700273
Charles Chen10ca70b2018-11-28 00:03:38 +0800274 // There has been a car customized nav bar on the default display, so just create nav bars
275 // on external displays.
276 mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */);
Brad Stenning224b5b32018-03-28 21:26:57 -0700277 }
278
279 private void buildNavBarContent() {
280 if (mShowBottom) {
281 buildBottomBar((mDeviceIsProvisioned) ? R.layout.car_navigation_bar :
282 R.layout.car_navigation_bar_unprovisioned);
283 }
284
285 if (mShowLeft) {
286 buildLeft((mDeviceIsProvisioned) ? R.layout.car_left_navigation_bar :
287 R.layout.car_left_navigation_bar_unprovisioned);
288 }
289
Brad Stenning078235b2017-12-18 08:25:10 -0800290 if (mShowRight) {
Brad Stenning224b5b32018-03-28 21:26:57 -0700291 buildRight((mDeviceIsProvisioned) ? R.layout.car_right_navigation_bar :
292 R.layout.car_right_navigation_bar_unprovisioned);
293 }
294 }
295
296 private void buildNavBarWindows() {
297 if (mShowBottom) {
davidln54739152018-07-02 13:25:44 -0700298 mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
Brad Stenning224b5b32018-03-28 21:26:57 -0700299 R.layout.navigation_bar_window, null);
300 }
301 if (mShowLeft) {
302 mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
davidln54739152018-07-02 13:25:44 -0700303 R.layout.navigation_bar_window, null);
Brad Stenning224b5b32018-03-28 21:26:57 -0700304 }
305 if (mShowRight) {
306 mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
307 R.layout.navigation_bar_window, null);
Brad Stenning078235b2017-12-18 08:25:10 -0800308 }
309
310 }
311
Brad Stenning224b5b32018-03-28 21:26:57 -0700312 private void attachNavBarWindows() {
Brad Stenning078235b2017-12-18 08:25:10 -0800313
Brad Stenning224b5b32018-03-28 21:26:57 -0700314 if (mShowBottom) {
315 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
316 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
317 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
318 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
319 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
320 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
321 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
322 PixelFormat.TRANSLUCENT);
323 lp.setTitle("CarNavigationBar");
324 lp.windowAnimations = 0;
325 mWindowManager.addView(mNavigationBarWindow, lp);
Brad Stenningc622f1d2019-01-29 11:24:11 -0800326 mNavigationBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
Brad Stenning224b5b32018-03-28 21:26:57 -0700327 }
328 if (mShowLeft) {
329 int width = mContext.getResources().getDimensionPixelSize(
330 R.dimen.car_left_navigation_bar_width);
331 WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
332 width, LayoutParams.MATCH_PARENT,
333 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
334 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
335 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
336 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
337 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
338 PixelFormat.TRANSLUCENT);
339 leftlp.setTitle("LeftCarNavigationBar");
340 leftlp.windowAnimations = 0;
341 leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
342 leftlp.gravity = Gravity.LEFT;
343 mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
344 }
345 if (mShowRight) {
346 int width = mContext.getResources().getDimensionPixelSize(
347 R.dimen.car_right_navigation_bar_width);
348 WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
349 width, LayoutParams.MATCH_PARENT,
350 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
351 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
352 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
353 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
354 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
355 PixelFormat.TRANSLUCENT);
356 rightlp.setTitle("RightCarNavigationBar");
357 rightlp.windowAnimations = 0;
358 rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
359 rightlp.gravity = Gravity.RIGHT;
360 mWindowManager.addView(mRightNavigationBarWindow, rightlp);
361 }
362
363 }
364
365 private void buildBottomBar(int layout) {
Anthony Chen0801a5c2017-03-22 09:54:37 -0700366 // SystemUI requires that the navigation bar view have a parent. Since the regular
367 // StatusBar inflates navigation_bar_window as this parent view, use the same view for the
368 // CarNavigationBarView.
Brad Stenning224b5b32018-03-28 21:26:57 -0700369 View.inflate(mContext, layout, mNavigationBarWindow);
Scott Randolphf4085822017-06-27 15:23:01 -0700370 mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
371 if (mNavigationBarView == null) {
372 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
Brad Stenning078235b2017-12-18 08:25:10 -0800373 throw new RuntimeException("Unable to build botom nav bar due to missing layout");
Scott Randolphf4085822017-06-27 15:23:01 -0700374 }
Brad Stenning078235b2017-12-18 08:25:10 -0800375 mNavigationBarView.setStatusBar(this);
Brad Stenningf084d882018-08-08 13:34:21 -0700376 addTemperatureViewToController(mNavigationBarView);
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800377 }
378
Brad Stenning224b5b32018-03-28 21:26:57 -0700379 private void buildLeft(int layout) {
380 View.inflate(mContext, layout, mLeftNavigationBarWindow);
Brad Stenning078235b2017-12-18 08:25:10 -0800381 mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
382 if (mLeftNavigationBarView == null) {
383 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
384 throw new RuntimeException("Unable to build left nav bar due to missing layout");
385 }
386 mLeftNavigationBarView.setStatusBar(this);
Brad Stenningf084d882018-08-08 13:34:21 -0700387 addTemperatureViewToController(mLeftNavigationBarView);
Brad Stenning078235b2017-12-18 08:25:10 -0800388 }
389
390
Brad Stenning224b5b32018-03-28 21:26:57 -0700391 private void buildRight(int layout) {
392 View.inflate(mContext, layout, mRightNavigationBarWindow);
Brad Stenning078235b2017-12-18 08:25:10 -0800393 mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
394 if (mRightNavigationBarView == null) {
395 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
396 throw new RuntimeException("Unable to build right nav bar due to missing layout");
397 }
Brad Stenningf084d882018-08-08 13:34:21 -0700398 mRightNavigationBarView.setStatusBar(this);
399 addTemperatureViewToController(mRightNavigationBarView);
Brad Stenning078235b2017-12-18 08:25:10 -0800400 }
401
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800402 @Override
Qiming Shib9dfb922017-04-13 16:23:18 +0800403 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
404 //When executing dump() funciton simultaneously, we need to serialize them
405 //to get mStackScroller's position correctly.
406 synchronized (mQueueLock) {
407 pw.println(" mStackScroller: " + viewInfo(mStackScroller));
408 pw.println(" mStackScroller: " + viewInfo(mStackScroller)
409 + " scroll " + mStackScroller.getScrollX()
410 + "," + mStackScroller.getScrollY());
411 }
412
davidln54739152018-07-02 13:25:44 -0700413 pw.print(" mTaskStackListener=");
414 pw.println(mTaskStackListener);
Brad Stenning078235b2017-12-18 08:25:10 -0800415 pw.print(" mCarFacetButtonController=");
416 pw.println(mCarFacetButtonController);
davidln54739152018-07-02 13:25:44 -0700417 pw.print(" mFullscreenUserSwitcher=");
418 pw.println(mFullscreenUserSwitcher);
Qiming Shib9dfb922017-04-13 16:23:18 +0800419 pw.print(" mCarBatteryController=");
420 pw.println(mCarBatteryController);
421 pw.print(" mBatteryMeterView=");
422 pw.println(mBatteryMeterView);
423 pw.print(" mConnectedDeviceSignalController=");
424 pw.println(mConnectedDeviceSignalController);
425 pw.print(" mNavigationBarView=");
426 pw.println(mNavigationBarView);
427
428 if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
429 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
430 }
431
432 FalsingManager.getInstance(mContext).dump(pw);
433 FalsingLog.dump(pw);
434
435 pw.println("SharedPreferences:");
436 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
davidln54739152018-07-02 13:25:44 -0700437 pw.print(" ");
438 pw.print(entry.getKey());
439 pw.print("=");
440 pw.println(entry.getValue());
Qiming Shib9dfb922017-04-13 16:23:18 +0800441 }
442 }
443
Scott Randolphf4085822017-06-27 15:23:01 -0700444 @Override
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800445 protected View.OnTouchListener getStatusBarWindowTouchListener() {
Brad Stenningc622f1d2019-01-29 11:24:11 -0800446 // Gets the car specific notification touch listener
447 return getComponent(NotificationsUI.class).getDragDownListener();
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800448 }
449
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800450 @Override
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700451 public void showBatteryView() {
452 if (Log.isLoggable(TAG, Log.DEBUG)) {
453 Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
454 }
455
456 if (mBatteryMeterView != null) {
457 mBatteryMeterView.setVisibility(View.VISIBLE);
458 }
459 }
460
461 @Override
462 public void hideBatteryView() {
463 if (Log.isLoggable(TAG, Log.DEBUG)) {
464 Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
465 }
466
467 if (mBatteryMeterView != null) {
468 mBatteryMeterView.setVisibility(View.GONE);
469 }
470 }
471
Victor Chan1c6d0582016-01-09 16:26:37 -0800472 /**
Winson Chung67f5c8b2018-09-24 12:09:19 -0700473 * An implementation of TaskStackChangeListener, that listens for changes in the system
davidln54739152018-07-02 13:25:44 -0700474 * task stack and notifies the navigation bar.
Victor Chan1c6d0582016-01-09 16:26:37 -0800475 */
Winson Chung67f5c8b2018-09-24 12:09:19 -0700476 private class TaskStackListenerImpl extends TaskStackChangeListener {
Wale Ogunwale480dca02016-02-06 13:58:29 -0800477 @Override
Victor Chan1c6d0582016-01-09 16:26:37 -0800478 public void onTaskStackChanged() {
Brad Stenninga5e714c2018-04-12 19:23:39 -0700479 try {
480 mCarFacetButtonController.taskChanged(
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700481 ActivityTaskManager.getService().getAllStackInfos());
Brad Stenninga5e714c2018-04-12 19:23:39 -0700482 } catch (Exception e) {
483 Log.e(TAG, "Getting StackInfo from activity manager failed", e);
484 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800485 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800486 }
Rakesh Iyer2790a372016-01-22 15:33:39 -0800487
jovanakedba98c2018-09-14 15:46:24 -0700488 private void onDrivingStateChanged(CarDrivingStateEvent notUsed) {
489 // Check if we need to start the timer every time driving state changes.
490 startSwitchToGuestTimerIfDrivingOnKeyguard();
491 }
492
493 private void startSwitchToGuestTimerIfDrivingOnKeyguard() {
494 if (mDrivingStateHelper.isCurrentlyDriving() && mState != StatusBarState.SHADE) {
495 // We're driving while keyguard is up.
496 mSwitchToGuestTimer.start();
497 } else {
498 mSwitchToGuestTimer.cancel();
499 }
500 }
501
Rakesh Iyer2790a372016-01-22 15:33:39 -0800502 @Override
503 protected void createUserSwitcher() {
Jason Monk9c7844c2017-01-18 15:21:53 -0500504 UserSwitcherController userSwitcherController =
505 Dependency.get(UserSwitcherController.class);
506 if (userSwitcherController.useFullscreenUserSwitcher()) {
507 mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700508 mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
Rakesh Iyer2790a372016-01-22 15:33:39 -0800509 } else {
510 super.createUserSwitcher();
511 }
512 }
513
514 @Override
jovanak168dbdb2019-02-18 01:00:43 -0800515 public void setLockscreenUser(int newUserId) {
516 super.setLockscreenUser(newUserId);
517 // Try to dismiss the keyguard after every user switch.
518 dismissKeyguardWhenUserSwitcherNotDisplayed();
519 }
520
521 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400522 public void onStateChanged(int newState) {
523 super.onStateChanged(newState);
jovanakedba98c2018-09-14 15:46:24 -0700524
525 startSwitchToGuestTimerIfDrivingOnKeyguard();
526
jovanak168dbdb2019-02-18 01:00:43 -0800527 if (newState != StatusBarState.FULLSCREEN_USER_SWITCHER) {
528 hideUserSwitcher();
jovanak604ad512018-08-14 18:41:27 -0700529 } else {
jovanak168dbdb2019-02-18 01:00:43 -0800530 dismissKeyguardWhenUserSwitcherNotDisplayed();
531 }
532 }
533
534 /** Makes the full screen user switcher visible, if applicable. */
535 public void showUserSwitcher() {
536 if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
537 mFullscreenUserSwitcher.show(); // Makes the switcher visible.
538 }
539 }
540
541 private void hideUserSwitcher() {
542 if (mFullscreenUserSwitcher != null) {
jovanak604ad512018-08-14 18:41:27 -0700543 mFullscreenUserSwitcher.hide();
Aarthi Balachander0a427ef2018-07-13 15:00:58 -0700544 }
545 }
546
jovanak168dbdb2019-02-18 01:00:43 -0800547 // We automatically dismiss keyguard unless user switcher is being shown on the keyguard.
548 private void dismissKeyguardWhenUserSwitcherNotDisplayed() {
549 if (mFullscreenUserSwitcher == null) {
550 return; // Not using the full screen user switcher.
551 }
552
553 if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER
554 && !mFullscreenUserSwitcher.isVisible()) {
555 // Current execution path continues to set state after this, thus we deffer the
556 // dismissal to the next execution cycle.
557 postDismissKeyguard(); // Dismiss the keyguard if switcher is not visible.
Rakesh Iyer2790a372016-01-22 15:33:39 -0800558 }
559 }
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800560
jovanak604ad512018-08-14 18:41:27 -0700561 public void postDismissKeyguard() {
562 mHandler.post(this::dismissKeyguard);
563 }
564
565 /**
566 * Dismisses the keyguard and shows bouncer if authentication is necessary.
567 */
568 public void dismissKeyguard() {
569 executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
Brad Stenning8d1a51c2018-11-20 17:34:16 -0800570 true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
jovanak604ad512018-08-14 18:41:27 -0700571 }
572
Victor Chanc87554c2016-08-24 14:58:14 -0700573 @Override
Anthony Chene658cc22017-04-27 11:17:35 -0700574 public void animateExpandNotificationsPanel() {
575 // Because space is usually constrained in the auto use-case, there should not be a
576 // pinned notification when the shade has been expanded. Ensure this by removing all heads-
577 // up notifications.
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900578 mHeadsUpManager.releaseAllImmediately();
Anthony Chene658cc22017-04-27 11:17:35 -0700579 super.animateExpandNotificationsPanel();
580 }
581
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800582 /**
583 * Ensures that relevant child views are appropriately recreated when the device's density
584 * changes.
585 */
586 @Override
Jason Monk9cac5ff2017-06-02 11:35:50 -0400587 public void onDensityOrFontScaleChanged() {
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800588 super.onDensityOrFontScaleChanged();
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800589 restartNavBars();
Anthony Chene658cc22017-04-27 11:17:35 -0700590 // Need to update the background on density changed in case the change was due to night
591 // mode.
592 mNotificationPanelBackground = getDefaultWallpaper();
593 mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
594 }
595
596 /**
597 * Returns the {@link Drawable} that represents the wallpaper that the user has currently set.
598 */
599 private Drawable getDefaultWallpaper() {
600 return mContext.getDrawable(com.android.internal.R.drawable.default_wallpaper);
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800601 }
Brad Stenning19f236a2018-12-11 14:12:30 -0800602
603 public void toggleCarNotifications() {
604 getComponent(NotificationsUI.class).toggleShowingCarNotifications();
605 }
606
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800607}