blob: bd0e0b846abfc2538e059567172a42279fcb93bc [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() {
Brad Stenningeb6051c2019-02-27 13:46:11 -080095 // get the provisioned state before calling the parent class since it's that flow that
96 // builds the nav bar
97 mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
98 mDeviceIsProvisioned = mDeviceProvisionedController.isDeviceProvisioned();
Victor Chan1c6d0582016-01-09 16:26:37 -080099 super.start();
Jaewan Kim938a50b2016-03-14 17:35:43 +0900100 mTaskStackListener = new TaskStackListenerImpl();
Brad Stenning224b5b32018-03-28 21:26:57 -0700101 mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
102 mActivityManagerWrapper.registerTaskStackListener(mTaskStackListener);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700103
Jason Monke59dc402018-08-16 12:05:01 -0400104 mNotificationPanel.setScrollingEnabled(true);
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800105
Rakesh Iyer545e47d2017-01-23 18:10:21 -0800106 createBatteryController();
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700107 mCarBatteryController.startListening();
Brad Stenning38b46f82018-03-27 13:57:29 -0700108
Brad Stenningf084d882018-08-08 13:34:21 -0700109 mHvacController.connectToCarService();
davidln54739152018-07-02 13:25:44 -0700110
Jason Monk27d01a622018-12-10 15:57:09 -0500111 CarSystemUIFactory factory = SystemUIFactory.getInstance();
Brad Stenning224b5b32018-03-28 21:26:57 -0700112 if (!mDeviceIsProvisioned) {
113 mDeviceProvisionedController.addCallback(
114 new DeviceProvisionedController.DeviceProvisionedListener() {
115 @Override
116 public void onDeviceProvisionedChanged() {
Brad Stenninga2d87d82019-01-24 12:33:10 -0800117 mHandler.post(() -> {
118 // on initial boot we are getting a call even though the value
119 // is the same so we are confirming the reset is needed
120 boolean deviceProvisioned =
121 mDeviceProvisionedController.isDeviceProvisioned();
122 if (mDeviceIsProvisioned != deviceProvisioned) {
123 mDeviceIsProvisioned = deviceProvisioned;
124 restartNavBars();
125 }
126 });
Brad Stenning224b5b32018-03-28 21:26:57 -0700127 }
128 });
129 }
jovanakedba98c2018-09-14 15:46:24 -0700130
131 // Register a listener for driving state changes.
132 mDrivingStateHelper = new DrivingStateHelper(mContext, this::onDrivingStateChanged);
133 mDrivingStateHelper.connectToCarService();
134
135 mSwitchToGuestTimer = new SwitchToGuestTimer(mContext);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700136 }
137
Brad Stenning224b5b32018-03-28 21:26:57 -0700138 /**
139 * Remove all content from navbars and rebuild them. Used to allow for different nav bars
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800140 * before and after the device is provisioned. . Also for change of density and font size.
Brad Stenning224b5b32018-03-28 21:26:57 -0700141 */
142 private void restartNavBars() {
Brad Stenningf084d882018-08-08 13:34:21 -0700143 // remove and reattach all hvac components such that we don't keep a reference to unused
144 // ui elements
145 mHvacController.removeAllComponents();
146 addTemperatureViewToController(mStatusBarWindow);
Brad Stenning224b5b32018-03-28 21:26:57 -0700147 mCarFacetButtonController.removeAll();
Brad Stenning224b5b32018-03-28 21:26:57 -0700148 if (mNavigationBarWindow != null) {
149 mNavigationBarWindow.removeAllViews();
150 mNavigationBarView = null;
151 }
152
153 if (mLeftNavigationBarWindow != null) {
154 mLeftNavigationBarWindow.removeAllViews();
155 mLeftNavigationBarView = null;
156 }
157
158 if (mRightNavigationBarWindow != null) {
159 mRightNavigationBarWindow.removeAllViews();
160 mRightNavigationBarView = null;
161 }
Brad Stenningf084d882018-08-08 13:34:21 -0700162
Brad Stenning224b5b32018-03-28 21:26:57 -0700163 buildNavBarContent();
164 }
165
Brad Stenningf084d882018-08-08 13:34:21 -0700166 private void addTemperatureViewToController(View v) {
167 if (v instanceof TemperatureView) {
168 Log.d(TAG, "addTemperatureViewToController: found ");
169 mHvacController.addHvacTextView((TemperatureView) v);
170 } else if (v instanceof ViewGroup) {
171 ViewGroup viewGroup = (ViewGroup) v;
172 for (int i = 0; i < viewGroup.getChildCount(); i++) {
173 addTemperatureViewToController(viewGroup.getChildAt(i));
174 }
175 }
176 }
177
Brad Stenning7e411812018-04-13 22:52:39 -0700178 /**
179 * Allows for showing or hiding just the navigation bars. This is indented to be used when
180 * the full screen user selector is shown.
181 */
davidln54739152018-07-02 13:25:44 -0700182 void setNavBarVisibility(@View.Visibility int visibility) {
Brad Stenning7e411812018-04-13 22:52:39 -0700183 if (mNavigationBarWindow != null) {
184 mNavigationBarWindow.setVisibility(visibility);
185 }
186 if (mLeftNavigationBarWindow != null) {
187 mLeftNavigationBarWindow.setVisibility(visibility);
188 }
189 if (mRightNavigationBarWindow != null) {
190 mRightNavigationBarWindow.setVisibility(visibility);
191 }
192 }
193
194
195 @Override
196 public boolean hideKeyguard() {
197 boolean result = super.hideKeyguard();
198 if (mNavigationBarView != null) {
199 mNavigationBarView.hideKeyguardButtons();
200 }
201 if (mLeftNavigationBarView != null) {
202 mLeftNavigationBarView.hideKeyguardButtons();
203 }
204 if (mRightNavigationBarView != null) {
205 mRightNavigationBarView.hideKeyguardButtons();
206 }
207 return result;
208 }
209
210
211 @Override
212 public void showKeyguard() {
213 super.showKeyguard();
Brad Stenningc622f1d2019-01-29 11:24:11 -0800214 getComponent(NotificationsUI.class).closeCarNotifications(0);
Brad Stenning7e411812018-04-13 22:52:39 -0700215 if (mNavigationBarView != null) {
216 mNavigationBarView.showKeyguardButtons();
217 }
218 if (mLeftNavigationBarView != null) {
219 mLeftNavigationBarView.showKeyguardButtons();
220 }
221 if (mRightNavigationBarView != null) {
222 mRightNavigationBarView.showKeyguardButtons();
223 }
224 }
Brad Stenning224b5b32018-03-28 21:26:57 -0700225
Brad Stenning224b5b32018-03-28 21:26:57 -0700226
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700227 @Override
Jason Monkaa573e92017-01-27 17:00:29 -0500228 protected void makeStatusBarView() {
229 super.makeStatusBarView();
Jason Monk27d01a622018-12-10 15:57:09 -0500230 mHvacController = new HvacController(mContext);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700231
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800232 CarSystemUIFactory factory = SystemUIFactory.getInstance();
233 mCarFacetButtonController = factory.getCarDependencyComponent()
234 .getCarFacetButtonController();
Anthony Chene658cc22017-04-27 11:17:35 -0700235 mNotificationPanelBackground = getDefaultWallpaper();
236 mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
237
Jason Monkaa573e92017-01-27 17:00:29 -0500238 FragmentHostManager manager = FragmentHostManager.get(mStatusBarWindow);
239 manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
Anthony Chene658cc22017-04-27 11:17:35 -0700240 mBatteryMeterView = fragment.getView().findViewById(R.id.battery);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700241
Jason Monkaa573e92017-01-27 17:00:29 -0500242 // By default, the BatteryMeterView should not be visible. It will be toggled
243 // when a device has connected by bluetooth.
244 mBatteryMeterView.setVisibility(View.GONE);
Jason Monkaa573e92017-01-27 17:00:29 -0500245 });
Brad Stenningf084d882018-08-08 13:34:21 -0700246 addTemperatureViewToController(mStatusBarWindow);
Brad Stenningc622f1d2019-01-29 11:24:11 -0800247 // The following are the ui elements that the user would call the status bar.
248 // This will set the status bar so it they can make call backs.
249 CarNavigationBarView topBar = mStatusBarWindow.findViewById(R.id.car_top_bar);
250 topBar.setStatusBar(this);
251 CarNavigationBarView qsTopBar = mStatusBarWindow.findViewById(R.id.qs_car_top_bar);
252 qsTopBar.setStatusBar(this);
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700253 }
254
Brad Stenning8d1a51c2018-11-20 17:34:16 -0800255 @Override
256 protected QS createDefaultQSFragment() {
257 return new CarQSFragment();
258 }
259
Rakesh Iyer545e47d2017-01-23 18:10:21 -0800260 private BatteryController createBatteryController() {
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700261 mCarBatteryController = new CarBatteryController(mContext);
262 mCarBatteryController.addBatteryViewHandler(this);
263 return mCarBatteryController;
Victor Chan1c6d0582016-01-09 16:26:37 -0800264 }
265
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800266 @Override
Jason Monk49fa0162017-01-11 09:21:56 -0500267 protected void createNavigationBar() {
Brad Stenning078235b2017-12-18 08:25:10 -0800268 mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar);
Brad Stenning078235b2017-12-18 08:25:10 -0800269 mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar);
Brad Stenning078235b2017-12-18 08:25:10 -0800270 mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar);
271
Brad Stenning224b5b32018-03-28 21:26:57 -0700272 buildNavBarWindows();
273 buildNavBarContent();
274 attachNavBarWindows();
Andrii Kulian3ddd7de2018-10-10 00:33:19 -0700275
Charles Chen10ca70b2018-11-28 00:03:38 +0800276 // There has been a car customized nav bar on the default display, so just create nav bars
277 // on external displays.
278 mNavigationBarController.createNavigationBars(false /* includeDefaultDisplay */);
Brad Stenning224b5b32018-03-28 21:26:57 -0700279 }
280
281 private void buildNavBarContent() {
282 if (mShowBottom) {
283 buildBottomBar((mDeviceIsProvisioned) ? R.layout.car_navigation_bar :
284 R.layout.car_navigation_bar_unprovisioned);
285 }
286
287 if (mShowLeft) {
288 buildLeft((mDeviceIsProvisioned) ? R.layout.car_left_navigation_bar :
289 R.layout.car_left_navigation_bar_unprovisioned);
290 }
291
Brad Stenning078235b2017-12-18 08:25:10 -0800292 if (mShowRight) {
Brad Stenning224b5b32018-03-28 21:26:57 -0700293 buildRight((mDeviceIsProvisioned) ? R.layout.car_right_navigation_bar :
294 R.layout.car_right_navigation_bar_unprovisioned);
295 }
296 }
297
298 private void buildNavBarWindows() {
299 if (mShowBottom) {
davidln54739152018-07-02 13:25:44 -0700300 mNavigationBarWindow = (ViewGroup) View.inflate(mContext,
Brad Stenning224b5b32018-03-28 21:26:57 -0700301 R.layout.navigation_bar_window, null);
302 }
303 if (mShowLeft) {
304 mLeftNavigationBarWindow = (ViewGroup) View.inflate(mContext,
davidln54739152018-07-02 13:25:44 -0700305 R.layout.navigation_bar_window, null);
Brad Stenning224b5b32018-03-28 21:26:57 -0700306 }
307 if (mShowRight) {
308 mRightNavigationBarWindow = (ViewGroup) View.inflate(mContext,
309 R.layout.navigation_bar_window, null);
Brad Stenning078235b2017-12-18 08:25:10 -0800310 }
311
312 }
313
Brad Stenning224b5b32018-03-28 21:26:57 -0700314 private void attachNavBarWindows() {
Brad Stenning078235b2017-12-18 08:25:10 -0800315
Brad Stenning224b5b32018-03-28 21:26:57 -0700316 if (mShowBottom) {
317 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
318 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
319 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
320 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
321 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
322 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
323 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
324 PixelFormat.TRANSLUCENT);
325 lp.setTitle("CarNavigationBar");
326 lp.windowAnimations = 0;
327 mWindowManager.addView(mNavigationBarWindow, lp);
Brad Stenningc622f1d2019-01-29 11:24:11 -0800328 mNavigationBarWindow.setOnTouchListener(getStatusBarWindowTouchListener());
Brad Stenning224b5b32018-03-28 21:26:57 -0700329 }
330 if (mShowLeft) {
331 int width = mContext.getResources().getDimensionPixelSize(
332 R.dimen.car_left_navigation_bar_width);
333 WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
334 width, LayoutParams.MATCH_PARENT,
335 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
336 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
337 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
338 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
339 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
340 PixelFormat.TRANSLUCENT);
341 leftlp.setTitle("LeftCarNavigationBar");
342 leftlp.windowAnimations = 0;
343 leftlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
344 leftlp.gravity = Gravity.LEFT;
345 mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
346 }
347 if (mShowRight) {
348 int width = mContext.getResources().getDimensionPixelSize(
349 R.dimen.car_right_navigation_bar_width);
350 WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
351 width, LayoutParams.MATCH_PARENT,
352 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
353 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
354 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
355 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
356 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
357 PixelFormat.TRANSLUCENT);
358 rightlp.setTitle("RightCarNavigationBar");
359 rightlp.windowAnimations = 0;
360 rightlp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
361 rightlp.gravity = Gravity.RIGHT;
362 mWindowManager.addView(mRightNavigationBarWindow, rightlp);
363 }
364
365 }
366
367 private void buildBottomBar(int layout) {
Anthony Chen0801a5c2017-03-22 09:54:37 -0700368 // SystemUI requires that the navigation bar view have a parent. Since the regular
369 // StatusBar inflates navigation_bar_window as this parent view, use the same view for the
370 // CarNavigationBarView.
Brad Stenning224b5b32018-03-28 21:26:57 -0700371 View.inflate(mContext, layout, mNavigationBarWindow);
Scott Randolphf4085822017-06-27 15:23:01 -0700372 mNavigationBarView = (CarNavigationBarView) mNavigationBarWindow.getChildAt(0);
373 if (mNavigationBarView == null) {
374 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
Brad Stenning078235b2017-12-18 08:25:10 -0800375 throw new RuntimeException("Unable to build botom nav bar due to missing layout");
Scott Randolphf4085822017-06-27 15:23:01 -0700376 }
Brad Stenning078235b2017-12-18 08:25:10 -0800377 mNavigationBarView.setStatusBar(this);
Brad Stenningf084d882018-08-08 13:34:21 -0700378 addTemperatureViewToController(mNavigationBarView);
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800379 }
380
Brad Stenning224b5b32018-03-28 21:26:57 -0700381 private void buildLeft(int layout) {
382 View.inflate(mContext, layout, mLeftNavigationBarWindow);
Brad Stenning078235b2017-12-18 08:25:10 -0800383 mLeftNavigationBarView = (CarNavigationBarView) mLeftNavigationBarWindow.getChildAt(0);
384 if (mLeftNavigationBarView == null) {
385 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
386 throw new RuntimeException("Unable to build left nav bar due to missing layout");
387 }
388 mLeftNavigationBarView.setStatusBar(this);
Brad Stenningf084d882018-08-08 13:34:21 -0700389 addTemperatureViewToController(mLeftNavigationBarView);
Brad Stenning078235b2017-12-18 08:25:10 -0800390 }
391
392
Brad Stenning224b5b32018-03-28 21:26:57 -0700393 private void buildRight(int layout) {
394 View.inflate(mContext, layout, mRightNavigationBarWindow);
Brad Stenning078235b2017-12-18 08:25:10 -0800395 mRightNavigationBarView = (CarNavigationBarView) mRightNavigationBarWindow.getChildAt(0);
396 if (mRightNavigationBarView == null) {
397 Log.e(TAG, "CarStatusBar failed inflate for R.layout.car_navigation_bar");
398 throw new RuntimeException("Unable to build right nav bar due to missing layout");
399 }
Brad Stenningf084d882018-08-08 13:34:21 -0700400 mRightNavigationBarView.setStatusBar(this);
401 addTemperatureViewToController(mRightNavigationBarView);
Brad Stenning078235b2017-12-18 08:25:10 -0800402 }
403
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800404 @Override
Qiming Shib9dfb922017-04-13 16:23:18 +0800405 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
406 //When executing dump() funciton simultaneously, we need to serialize them
407 //to get mStackScroller's position correctly.
408 synchronized (mQueueLock) {
409 pw.println(" mStackScroller: " + viewInfo(mStackScroller));
410 pw.println(" mStackScroller: " + viewInfo(mStackScroller)
411 + " scroll " + mStackScroller.getScrollX()
412 + "," + mStackScroller.getScrollY());
413 }
414
davidln54739152018-07-02 13:25:44 -0700415 pw.print(" mTaskStackListener=");
416 pw.println(mTaskStackListener);
Brad Stenning078235b2017-12-18 08:25:10 -0800417 pw.print(" mCarFacetButtonController=");
418 pw.println(mCarFacetButtonController);
davidln54739152018-07-02 13:25:44 -0700419 pw.print(" mFullscreenUserSwitcher=");
420 pw.println(mFullscreenUserSwitcher);
Qiming Shib9dfb922017-04-13 16:23:18 +0800421 pw.print(" mCarBatteryController=");
422 pw.println(mCarBatteryController);
423 pw.print(" mBatteryMeterView=");
424 pw.println(mBatteryMeterView);
425 pw.print(" mConnectedDeviceSignalController=");
426 pw.println(mConnectedDeviceSignalController);
427 pw.print(" mNavigationBarView=");
428 pw.println(mNavigationBarView);
429
430 if (KeyguardUpdateMonitor.getInstance(mContext) != null) {
431 KeyguardUpdateMonitor.getInstance(mContext).dump(fd, pw, args);
432 }
433
434 FalsingManager.getInstance(mContext).dump(pw);
435 FalsingLog.dump(pw);
436
437 pw.println("SharedPreferences:");
438 for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
davidln54739152018-07-02 13:25:44 -0700439 pw.print(" ");
440 pw.print(entry.getKey());
441 pw.print("=");
442 pw.println(entry.getValue());
Qiming Shib9dfb922017-04-13 16:23:18 +0800443 }
444 }
445
Scott Randolphf4085822017-06-27 15:23:01 -0700446 @Override
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800447 protected View.OnTouchListener getStatusBarWindowTouchListener() {
Brad Stenningc622f1d2019-01-29 11:24:11 -0800448 // Gets the car specific notification touch listener
449 return getComponent(NotificationsUI.class).getDragDownListener();
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800450 }
451
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800452 @Override
Anthony Chenda62fdcd52016-04-06 16:15:14 -0700453 public void showBatteryView() {
454 if (Log.isLoggable(TAG, Log.DEBUG)) {
455 Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
456 }
457
458 if (mBatteryMeterView != null) {
459 mBatteryMeterView.setVisibility(View.VISIBLE);
460 }
461 }
462
463 @Override
464 public void hideBatteryView() {
465 if (Log.isLoggable(TAG, Log.DEBUG)) {
466 Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
467 }
468
469 if (mBatteryMeterView != null) {
470 mBatteryMeterView.setVisibility(View.GONE);
471 }
472 }
473
Victor Chan1c6d0582016-01-09 16:26:37 -0800474 /**
Winson Chung67f5c8b2018-09-24 12:09:19 -0700475 * An implementation of TaskStackChangeListener, that listens for changes in the system
davidln54739152018-07-02 13:25:44 -0700476 * task stack and notifies the navigation bar.
Victor Chan1c6d0582016-01-09 16:26:37 -0800477 */
Winson Chung67f5c8b2018-09-24 12:09:19 -0700478 private class TaskStackListenerImpl extends TaskStackChangeListener {
Wale Ogunwale480dca02016-02-06 13:58:29 -0800479 @Override
Victor Chan1c6d0582016-01-09 16:26:37 -0800480 public void onTaskStackChanged() {
Brad Stenninga5e714c2018-04-12 19:23:39 -0700481 try {
482 mCarFacetButtonController.taskChanged(
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700483 ActivityTaskManager.getService().getAllStackInfos());
Brad Stenninga5e714c2018-04-12 19:23:39 -0700484 } catch (Exception e) {
485 Log.e(TAG, "Getting StackInfo from activity manager failed", e);
486 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800487 }
Victor Chan1c6d0582016-01-09 16:26:37 -0800488 }
Rakesh Iyer2790a372016-01-22 15:33:39 -0800489
jovanakedba98c2018-09-14 15:46:24 -0700490 private void onDrivingStateChanged(CarDrivingStateEvent notUsed) {
491 // Check if we need to start the timer every time driving state changes.
492 startSwitchToGuestTimerIfDrivingOnKeyguard();
493 }
494
495 private void startSwitchToGuestTimerIfDrivingOnKeyguard() {
496 if (mDrivingStateHelper.isCurrentlyDriving() && mState != StatusBarState.SHADE) {
497 // We're driving while keyguard is up.
498 mSwitchToGuestTimer.start();
499 } else {
500 mSwitchToGuestTimer.cancel();
501 }
502 }
503
Rakesh Iyer2790a372016-01-22 15:33:39 -0800504 @Override
505 protected void createUserSwitcher() {
Jason Monk9c7844c2017-01-18 15:21:53 -0500506 UserSwitcherController userSwitcherController =
507 Dependency.get(UserSwitcherController.class);
508 if (userSwitcherController.useFullscreenUserSwitcher()) {
509 mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
Aarthi Balachanderd8bf2492018-03-30 11:15:59 -0700510 mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
Rakesh Iyer2790a372016-01-22 15:33:39 -0800511 } else {
512 super.createUserSwitcher();
513 }
514 }
515
516 @Override
jovanak168dbdb2019-02-18 01:00:43 -0800517 public void setLockscreenUser(int newUserId) {
518 super.setLockscreenUser(newUserId);
519 // Try to dismiss the keyguard after every user switch.
520 dismissKeyguardWhenUserSwitcherNotDisplayed();
521 }
522
523 @Override
Jason Monk1fd3fc32018-08-14 17:20:09 -0400524 public void onStateChanged(int newState) {
525 super.onStateChanged(newState);
jovanakedba98c2018-09-14 15:46:24 -0700526
527 startSwitchToGuestTimerIfDrivingOnKeyguard();
528
jovanak168dbdb2019-02-18 01:00:43 -0800529 if (newState != StatusBarState.FULLSCREEN_USER_SWITCHER) {
530 hideUserSwitcher();
jovanak604ad512018-08-14 18:41:27 -0700531 } else {
jovanak168dbdb2019-02-18 01:00:43 -0800532 dismissKeyguardWhenUserSwitcherNotDisplayed();
533 }
534 }
535
536 /** Makes the full screen user switcher visible, if applicable. */
537 public void showUserSwitcher() {
538 if (mFullscreenUserSwitcher != null && mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
539 mFullscreenUserSwitcher.show(); // Makes the switcher visible.
540 }
541 }
542
543 private void hideUserSwitcher() {
544 if (mFullscreenUserSwitcher != null) {
jovanak604ad512018-08-14 18:41:27 -0700545 mFullscreenUserSwitcher.hide();
Aarthi Balachander0a427ef2018-07-13 15:00:58 -0700546 }
547 }
548
jovanak168dbdb2019-02-18 01:00:43 -0800549 // We automatically dismiss keyguard unless user switcher is being shown on the keyguard.
550 private void dismissKeyguardWhenUserSwitcherNotDisplayed() {
551 if (mFullscreenUserSwitcher == null) {
552 return; // Not using the full screen user switcher.
553 }
554
555 if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER
556 && !mFullscreenUserSwitcher.isVisible()) {
557 // Current execution path continues to set state after this, thus we deffer the
558 // dismissal to the next execution cycle.
559 postDismissKeyguard(); // Dismiss the keyguard if switcher is not visible.
Rakesh Iyer2790a372016-01-22 15:33:39 -0800560 }
561 }
Rakesh Iyer74ebabe2016-03-11 10:10:43 -0800562
jovanak604ad512018-08-14 18:41:27 -0700563 public void postDismissKeyguard() {
564 mHandler.post(this::dismissKeyguard);
565 }
566
567 /**
568 * Dismisses the keyguard and shows bouncer if authentication is necessary.
569 */
570 public void dismissKeyguard() {
571 executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
Brad Stenning8d1a51c2018-11-20 17:34:16 -0800572 true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
jovanak604ad512018-08-14 18:41:27 -0700573 }
574
Victor Chanc87554c2016-08-24 14:58:14 -0700575 @Override
Anthony Chene658cc22017-04-27 11:17:35 -0700576 public void animateExpandNotificationsPanel() {
577 // Because space is usually constrained in the auto use-case, there should not be a
578 // pinned notification when the shade has been expanded. Ensure this by removing all heads-
579 // up notifications.
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900580 mHeadsUpManager.releaseAllImmediately();
Anthony Chene658cc22017-04-27 11:17:35 -0700581 super.animateExpandNotificationsPanel();
582 }
583
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800584 /**
585 * Ensures that relevant child views are appropriately recreated when the device's density
586 * changes.
587 */
588 @Override
Jason Monk9cac5ff2017-06-02 11:35:50 -0400589 public void onDensityOrFontScaleChanged() {
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800590 super.onDensityOrFontScaleChanged();
Guobin Zhangeef0e0c2019-02-01 11:54:24 -0800591 restartNavBars();
Anthony Chene658cc22017-04-27 11:17:35 -0700592 // Need to update the background on density changed in case the change was due to night
593 // mode.
594 mNotificationPanelBackground = getDefaultWallpaper();
595 mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
596 }
597
598 /**
599 * Returns the {@link Drawable} that represents the wallpaper that the user has currently set.
600 */
601 private Drawable getDefaultWallpaper() {
602 return mContext.getDrawable(com.android.internal.R.drawable.default_wallpaper);
Anthony Chen3cb3ad92016-12-01 10:58:47 -0800603 }
Brad Stenning19f236a2018-12-11 14:12:30 -0800604
605 public void toggleCarNotifications() {
606 getComponent(NotificationsUI.class).toggleShowingCarNotifications();
607 }
608
Rakesh Iyer1186faa2015-12-07 16:48:46 -0800609}