blob: 8e114142972c4c4b8313323efc371944ed39d282 [file] [log] [blame]
Heemin Seog1a39dea2019-10-16 15:58:21 -07001/*
Heemin Seog9b078d32020-04-21 15:07:32 -07002 * Copyright (C) 2020 The Android Open Source Project
Heemin Seog1a39dea2019-10-16 15:58:21 -07003 *
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
Heemin Seog9b078d32020-04-21 15:07:32 -070017package com.android.systemui.car.navigationbar;
Heemin Seog1a39dea2019-10-16 15:58:21 -070018
Heemin Seoge67cefea2020-01-28 12:02:50 -080019import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
Heemin Seog29ecf612020-04-14 22:47:01 -070020import static android.view.InsetsState.ITYPE_STATUS_BAR;
Heemin Seoge67cefea2020-01-28 12:02:50 -080021import static android.view.InsetsState.containsType;
JianYang Liu0e3c4782020-05-07 19:15:37 -070022import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
Heemin Seoge67cefea2020-01-28 12:02:50 -080023
24import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
25import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
26
Heemin Seog1a39dea2019-10-16 15:58:21 -070027import android.content.Context;
Heemin Seog29ecf612020-04-14 22:47:01 -070028import android.content.res.Resources;
Heemin Seog1a39dea2019-10-16 15:58:21 -070029import android.graphics.PixelFormat;
30import android.inputmethodservice.InputMethodService;
31import android.os.Handler;
32import android.os.IBinder;
33import android.os.RemoteException;
Heemin Seog1a39dea2019-10-16 15:58:21 -070034import android.view.Display;
35import android.view.Gravity;
Heemin Seog8d6ec6a72019-10-25 14:34:11 -070036import android.view.View;
Heemin Seog1a39dea2019-10-16 15:58:21 -070037import android.view.ViewGroup;
JianYang Liu0e3c4782020-05-07 19:15:37 -070038import android.view.WindowInsetsController;
Heemin Seog1a39dea2019-10-16 15:58:21 -070039import android.view.WindowManager;
40
Heemin Seog29ecf612020-04-14 22:47:01 -070041import androidx.annotation.VisibleForTesting;
42
Heemin Seog1a39dea2019-10-16 15:58:21 -070043import com.android.internal.statusbar.IStatusBarService;
44import com.android.internal.statusbar.RegisterStatusBarResult;
JianYang Liu0e3c4782020-05-07 19:15:37 -070045import com.android.internal.view.AppearanceRegion;
Heemin Seog1a39dea2019-10-16 15:58:21 -070046import com.android.systemui.R;
47import com.android.systemui.SystemUI;
Abhijoy Sahaee513692019-12-10 13:52:26 -080048import com.android.systemui.car.CarDeviceProvisionedController;
49import com.android.systemui.car.CarDeviceProvisionedListener;
Dave Mankoff00e8a2f2019-12-18 16:59:49 -050050import com.android.systemui.dagger.qualifiers.Main;
Heemin Seog4860f802020-05-05 00:22:42 -070051import com.android.systemui.dagger.qualifiers.UiBackground;
JianYang Liu0e3c4782020-05-07 19:15:37 -070052import com.android.systemui.plugins.DarkIconDispatcher;
Heemin Seog1a39dea2019-10-16 15:58:21 -070053import com.android.systemui.shared.system.ActivityManagerWrapper;
Heemin Seoge67cefea2020-01-28 12:02:50 -080054import com.android.systemui.statusbar.AutoHideUiElement;
Heemin Seog1a39dea2019-10-16 15:58:21 -070055import com.android.systemui.statusbar.CommandQueue;
Heemin Seoge67cefea2020-01-28 12:02:50 -080056import com.android.systemui.statusbar.phone.AutoHideController;
57import com.android.systemui.statusbar.phone.BarTransitions;
JianYang Liu0e3c4782020-05-07 19:15:37 -070058import com.android.systemui.statusbar.phone.LightBarController;
Heemin Seog29ecf612020-04-14 22:47:01 -070059import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
60import com.android.systemui.statusbar.phone.StatusBarIconController;
61import com.android.systemui.statusbar.phone.StatusBarSignalPolicy;
JianYang Liu0e3c4782020-05-07 19:15:37 -070062import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher;
Heemin Seog1a39dea2019-10-16 15:58:21 -070063import com.android.systemui.statusbar.policy.KeyguardStateController;
64
65import java.io.FileDescriptor;
66import java.io.PrintWriter;
Heemin Seog4860f802020-05-05 00:22:42 -070067import java.util.concurrent.Executor;
Heemin Seog1a39dea2019-10-16 15:58:21 -070068
69import javax.inject.Inject;
Heemin Seog1a39dea2019-10-16 15:58:21 -070070
71import dagger.Lazy;
72
73/** Navigation bars customized for the automotive use case. */
74public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks {
75
Heemin Seog29ecf612020-04-14 22:47:01 -070076 private final Resources mResources;
Heemin Seogfcccab72019-10-22 08:30:23 -070077 private final CarNavigationBarController mCarNavigationBarController;
JianYang Liu0e3c4782020-05-07 19:15:37 -070078 private final SysuiDarkIconDispatcher mStatusBarIconController;
Heemin Seog1a39dea2019-10-16 15:58:21 -070079 private final WindowManager mWindowManager;
Abhijoy Sahaee513692019-12-10 13:52:26 -080080 private final CarDeviceProvisionedController mCarDeviceProvisionedController;
Heemin Seog4a689482019-11-04 10:37:43 -080081 private final CommandQueue mCommandQueue;
Heemin Seoge67cefea2020-01-28 12:02:50 -080082 private final AutoHideController mAutoHideController;
kwaky77d81dc2019-12-12 16:23:59 -080083 private final ButtonSelectionStateListener mButtonSelectionStateListener;
Heemin Seog1a39dea2019-10-16 15:58:21 -070084 private final Handler mMainHandler;
Heemin Seog4860f802020-05-05 00:22:42 -070085 private final Executor mUiBgExecutor;
Heemin Seog23f18d02020-04-24 17:53:22 -070086 private final IStatusBarService mBarService;
Heemin Seogd59786b2019-11-08 09:20:26 -080087 private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy;
kwaky77d81dc2019-12-12 16:23:59 -080088 private final ButtonSelectionStateController mButtonSelectionStateController;
Heemin Seoga3d358f2020-04-28 22:31:03 -070089 private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy;
90 private final Lazy<StatusBarIconController> mIconControllerLazy;
Heemin Seog1a39dea2019-10-16 15:58:21 -070091
Heemin Seoge67cefea2020-01-28 12:02:50 -080092 private final int mDisplayId;
93
Heemin Seog29ecf612020-04-14 22:47:01 -070094 private StatusBarSignalPolicy mSignalPolicy;
Heemin Seog1a39dea2019-10-16 15:58:21 -070095 private ActivityManagerWrapper mActivityManagerWrapper;
96
97 // If the nav bar should be hidden when the soft keyboard is visible.
98 private boolean mHideNavBarForKeyboard;
99 private boolean mBottomNavBarVisible;
100
101 // Nav bar views.
Heemin Seogd59786b2019-11-08 09:20:26 -0800102 private ViewGroup mTopNavigationBarWindow;
103 private ViewGroup mBottomNavigationBarWindow;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700104 private ViewGroup mLeftNavigationBarWindow;
105 private ViewGroup mRightNavigationBarWindow;
Heemin Seogd59786b2019-11-08 09:20:26 -0800106 private CarNavigationBarView mTopNavigationBarView;
107 private CarNavigationBarView mBottomNavigationBarView;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700108 private CarNavigationBarView mLeftNavigationBarView;
109 private CarNavigationBarView mRightNavigationBarView;
110
111 // To be attached to the navigation bars such that they can close the notification panel if
112 // it's open.
113 private boolean mDeviceIsSetUpForUser = true;
Abhijoy Sahaee513692019-12-10 13:52:26 -0800114 private boolean mIsUserSetupInProgress = false;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700115
JianYang Liu0e3c4782020-05-07 19:15:37 -0700116 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
Heemin Seog4860f802020-05-05 00:22:42 -0700117 @BarTransitions.TransitionMode
118 private int mStatusBarMode;
119 @BarTransitions.TransitionMode
120 private int mNavigationBarMode;
Heemin Seog29ecf612020-04-14 22:47:01 -0700121 private boolean mStatusBarTransientShown;
122 private boolean mNavBarTransientShown;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800123
Heemin Seog1a39dea2019-10-16 15:58:21 -0700124 @Inject
125 public CarNavigationBar(Context context,
Heemin Seog29ecf612020-04-14 22:47:01 -0700126 @Main Resources resources,
Heemin Seogfcccab72019-10-22 08:30:23 -0700127 CarNavigationBarController carNavigationBarController,
JianYang Liu0e3c4782020-05-07 19:15:37 -0700128 // TODO(b/156052638): Should not need to inject LightBarController
129 LightBarController lightBarController,
130 DarkIconDispatcher darkIconDispatcher,
Heemin Seog1a39dea2019-10-16 15:58:21 -0700131 WindowManager windowManager,
Eric Berglund89edc872020-01-21 15:28:35 -0800132 CarDeviceProvisionedController deviceProvisionedController,
Heemin Seog4a689482019-11-04 10:37:43 -0800133 CommandQueue commandQueue,
Heemin Seoge67cefea2020-01-28 12:02:50 -0800134 AutoHideController autoHideController,
kwaky77d81dc2019-12-12 16:23:59 -0800135 ButtonSelectionStateListener buttonSelectionStateListener,
Dave Mankoff00e8a2f2019-12-18 16:59:49 -0500136 @Main Handler mainHandler,
Heemin Seog4860f802020-05-05 00:22:42 -0700137 @UiBackground Executor uiBgExecutor,
Heemin Seog23f18d02020-04-24 17:53:22 -0700138 IStatusBarService barService,
Heemin Seogd59786b2019-11-08 09:20:26 -0800139 Lazy<KeyguardStateController> keyguardStateControllerLazy,
Heemin Seog29ecf612020-04-14 22:47:01 -0700140 ButtonSelectionStateController buttonSelectionStateController,
Heemin Seoga3d358f2020-04-28 22:31:03 -0700141 Lazy<PhoneStatusBarPolicy> iconPolicyLazy,
142 Lazy<StatusBarIconController> iconControllerLazy
Heemin Seog29ecf612020-04-14 22:47:01 -0700143 ) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700144 super(context);
Heemin Seog29ecf612020-04-14 22:47:01 -0700145 mResources = resources;
Heemin Seogfcccab72019-10-22 08:30:23 -0700146 mCarNavigationBarController = carNavigationBarController;
JianYang Liu0e3c4782020-05-07 19:15:37 -0700147 mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700148 mWindowManager = windowManager;
Eric Berglund89edc872020-01-21 15:28:35 -0800149 mCarDeviceProvisionedController = deviceProvisionedController;
Heemin Seog4a689482019-11-04 10:37:43 -0800150 mCommandQueue = commandQueue;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800151 mAutoHideController = autoHideController;
kwaky77d81dc2019-12-12 16:23:59 -0800152 mButtonSelectionStateListener = buttonSelectionStateListener;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700153 mMainHandler = mainHandler;
Heemin Seog4860f802020-05-05 00:22:42 -0700154 mUiBgExecutor = uiBgExecutor;
Heemin Seog23f18d02020-04-24 17:53:22 -0700155 mBarService = barService;
Heemin Seogd59786b2019-11-08 09:20:26 -0800156 mKeyguardStateControllerLazy = keyguardStateControllerLazy;
kwaky77d81dc2019-12-12 16:23:59 -0800157 mButtonSelectionStateController = buttonSelectionStateController;
Heemin Seoga3d358f2020-04-28 22:31:03 -0700158 mIconPolicyLazy = iconPolicyLazy;
159 mIconControllerLazy = iconControllerLazy;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800160
Heemin Seog29ecf612020-04-14 22:47:01 -0700161 mDisplayId = context.getDisplayId();
Heemin Seog1a39dea2019-10-16 15:58:21 -0700162 }
163
164 @Override
165 public void start() {
166 // Set initial state.
Heemin Seog29ecf612020-04-14 22:47:01 -0700167 mHideNavBarForKeyboard = mResources.getBoolean(
Heemin Seog1a39dea2019-10-16 15:58:21 -0700168 com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
169 mBottomNavBarVisible = false;
170
Heemin Seog1a39dea2019-10-16 15:58:21 -0700171 // Connect into the status bar manager service
Heemin Seog1a39dea2019-10-16 15:58:21 -0700172 mCommandQueue.addCallback(this);
173
174 RegisterStatusBarResult result = null;
175 try {
176 result = mBarService.registerStatusBar(mCommandQueue);
177 } catch (RemoteException ex) {
178 ex.rethrowFromSystemServer();
179 }
180
JianYang Liu0e3c4782020-05-07 19:15:37 -0700181 onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
182 result.mNavbarColorManagedByIme);
183
Heemin Seog29ecf612020-04-14 22:47:01 -0700184 // StatusBarManagerService has a back up of IME token and it's restored here.
185 setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
186 result.mImeBackDisposition, result.mShowImeSwitcher);
187
188 // Set up the initial icon state
189 int numIcons = result.mIcons.size();
190 for (int i = 0; i < numIcons; i++) {
191 mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
192 }
193
194 mAutoHideController.setStatusBar(new AutoHideUiElement() {
195 @Override
196 public void synchronizeState() {
197 // No op.
198 }
199
200 @Override
201 public boolean isVisible() {
202 return mStatusBarTransientShown;
203 }
204
205 @Override
206 public void hide() {
207 clearTransient();
208 }
209 });
210
Heemin Seoga8983af2020-03-31 13:16:48 -0700211 mAutoHideController.setNavigationBar(new AutoHideUiElement() {
Heemin Seoge67cefea2020-01-28 12:02:50 -0800212 @Override
213 public void synchronizeState() {
214 // No op.
215 }
216
217 @Override
218 public boolean isVisible() {
Heemin Seog29ecf612020-04-14 22:47:01 -0700219 return mNavBarTransientShown;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800220 }
221
222 @Override
223 public void hide() {
224 clearTransient();
225 }
226 });
227
Abhijoy Sahaee513692019-12-10 13:52:26 -0800228 mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup();
229 mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
230 mCarDeviceProvisionedController.addCallback(
231 new CarDeviceProvisionedListener() {
232 @Override
233 public void onUserSetupInProgressChanged() {
234 mMainHandler.post(() -> restartNavBarsIfNecessary());
235 }
236
Heemin Seog1a39dea2019-10-16 15:58:21 -0700237 @Override
238 public void onUserSetupChanged() {
239 mMainHandler.post(() -> restartNavBarsIfNecessary());
240 }
241
242 @Override
243 public void onUserSwitched() {
244 mMainHandler.post(() -> restartNavBarsIfNecessary());
245 }
246 });
247
248 createNavigationBar(result);
249
250 mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
kwaky77d81dc2019-12-12 16:23:59 -0800251 mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700252
Heemin Seog4860f802020-05-05 00:22:42 -0700253 mUiBgExecutor.execute(mCarNavigationBarController::connectToHvac);
Heemin Seog29ecf612020-04-14 22:47:01 -0700254
255 // Lastly, call to the icon policy to install/update all the icons.
Heemin Seog23f18d02020-04-24 17:53:22 -0700256 // Must be called on the main thread due to the use of observeForever() in
257 // mIconPolicy.init().
258 mMainHandler.post(() -> {
Heemin Seoga3d358f2020-04-28 22:31:03 -0700259 mIconPolicyLazy.get().init();
260 mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconControllerLazy.get());
Heemin Seog23f18d02020-04-24 17:53:22 -0700261 });
Heemin Seog1a39dea2019-10-16 15:58:21 -0700262 }
263
264 private void restartNavBarsIfNecessary() {
Abhijoy Sahaee513692019-12-10 13:52:26 -0800265 boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup();
266 boolean currentUserSetupInProgress = mCarDeviceProvisionedController
267 .isCurrentUserSetupInProgress();
268 if (mIsUserSetupInProgress != currentUserSetupInProgress
269 || mDeviceIsSetUpForUser != currentUserSetup) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700270 mDeviceIsSetUpForUser = currentUserSetup;
Abhijoy Sahaee513692019-12-10 13:52:26 -0800271 mIsUserSetupInProgress = currentUserSetupInProgress;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700272 restartNavBars();
273 }
274 }
275
276 /**
277 * Remove all content from navbars and rebuild them. Used to allow for different nav bars
278 * before and after the device is provisioned. . Also for change of density and font size.
279 */
280 private void restartNavBars() {
281 // remove and reattach all hvac components such that we don't keep a reference to unused
282 // ui elements
Heemin Seogfcccab72019-10-22 08:30:23 -0700283 mCarNavigationBarController.removeAllFromHvac();
kwaky77d81dc2019-12-12 16:23:59 -0800284 mButtonSelectionStateController.removeAll();
Heemin Seog1a39dea2019-10-16 15:58:21 -0700285
Heemin Seogd59786b2019-11-08 09:20:26 -0800286 if (mTopNavigationBarWindow != null) {
287 mTopNavigationBarWindow.removeAllViews();
288 mTopNavigationBarView = null;
289 }
290
291 if (mBottomNavigationBarWindow != null) {
292 mBottomNavigationBarWindow.removeAllViews();
293 mBottomNavigationBarView = null;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700294 }
295
296 if (mLeftNavigationBarWindow != null) {
297 mLeftNavigationBarWindow.removeAllViews();
298 mLeftNavigationBarView = null;
299 }
300
301 if (mRightNavigationBarWindow != null) {
302 mRightNavigationBarWindow.removeAllViews();
303 mRightNavigationBarView = null;
304 }
305
306 buildNavBarContent();
JianYang Liu4fbd9812020-03-09 13:39:58 -0700307 // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need
308 // to correctly respect that state.
Heemin Seogd59786b2019-11-08 09:20:26 -0800309 if (mKeyguardStateControllerLazy.get().isShowing()) {
Abhijoy Sahaee513692019-12-10 13:52:26 -0800310 mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser());
JianYang Liu4fbd9812020-03-09 13:39:58 -0700311 } else {
312 mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser());
Heemin Seog1a39dea2019-10-16 15:58:21 -0700313 }
kwaky371e6212020-02-19 13:45:22 -0800314
315 // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the
316 // selection state that reflects the current task stack.
317 mButtonSelectionStateListener.onTaskStackChanged();
Heemin Seog1a39dea2019-10-16 15:58:21 -0700318 }
319
Abhijoy Sahaee513692019-12-10 13:52:26 -0800320 private boolean isDeviceSetupForUser() {
321 return mDeviceIsSetUpForUser && !mIsUserSetupInProgress;
322 }
323
Heemin Seog1a39dea2019-10-16 15:58:21 -0700324 private void createNavigationBar(RegisterStatusBarResult result) {
325 buildNavBarWindows();
326 buildNavBarContent();
327 attachNavBarWindows();
328
329 // Try setting up the initial state of the nav bar if applicable.
330 if (result != null) {
331 setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
332 result.mImeWindowVis, result.mImeBackDisposition,
333 result.mShowImeSwitcher);
334 }
Heemin Seog1a39dea2019-10-16 15:58:21 -0700335 }
336
337 private void buildNavBarWindows() {
Heemin Seog29ecf612020-04-14 22:47:01 -0700338 mTopNavigationBarWindow = mCarNavigationBarController.getTopWindow();
Heemin Seogd59786b2019-11-08 09:20:26 -0800339 mBottomNavigationBarWindow = mCarNavigationBarController.getBottomWindow();
Heemin Seogfcccab72019-10-22 08:30:23 -0700340 mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow();
341 mRightNavigationBarWindow = mCarNavigationBarController.getRightWindow();
Heemin Seog1a39dea2019-10-16 15:58:21 -0700342 }
343
344 private void buildNavBarContent() {
Abhijoy Sahaee513692019-12-10 13:52:26 -0800345 mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser());
Heemin Seogd59786b2019-11-08 09:20:26 -0800346 if (mTopNavigationBarView != null) {
347 mTopNavigationBarWindow.addView(mTopNavigationBarView);
348 }
349
Abhijoy Sahaee513692019-12-10 13:52:26 -0800350 mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser());
Heemin Seogd59786b2019-11-08 09:20:26 -0800351 if (mBottomNavigationBarView != null) {
352 mBottomNavigationBarWindow.addView(mBottomNavigationBarView);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700353 }
354
Abhijoy Sahaee513692019-12-10 13:52:26 -0800355 mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser());
Heemin Seogfcccab72019-10-22 08:30:23 -0700356 if (mLeftNavigationBarView != null) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700357 mLeftNavigationBarWindow.addView(mLeftNavigationBarView);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700358 }
359
Abhijoy Sahaee513692019-12-10 13:52:26 -0800360 mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser());
Heemin Seogfcccab72019-10-22 08:30:23 -0700361 if (mRightNavigationBarView != null) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700362 mRightNavigationBarWindow.addView(mRightNavigationBarView);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700363 }
364 }
365
366 private void attachNavBarWindows() {
Heemin Seog29ecf612020-04-14 22:47:01 -0700367 if (mTopNavigationBarWindow != null) {
368 int height = mResources.getDimensionPixelSize(
369 com.android.internal.R.dimen.status_bar_height);
370 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
371 ViewGroup.LayoutParams.MATCH_PARENT,
372 height,
Heemin Seog991711a2020-04-24 00:38:39 -0700373 WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
Heemin Seog29ecf612020-04-14 22:47:01 -0700374 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
Heemin Seog991711a2020-04-24 00:38:39 -0700375 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
376 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
377 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
Heemin Seog29ecf612020-04-14 22:47:01 -0700378 PixelFormat.TRANSLUCENT);
Heemin Seog29ecf612020-04-14 22:47:01 -0700379 lp.setTitle("TopCarNavigationBar");
Heemin Seog991711a2020-04-24 00:38:39 -0700380 lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR};
381 lp.setFitInsetsTypes(0);
382 lp.windowAnimations = 0;
383 lp.gravity = Gravity.TOP;
Heemin Seog29ecf612020-04-14 22:47:01 -0700384 mWindowManager.addView(mTopNavigationBarWindow, lp);
385 }
386
Heemin Seogd59786b2019-11-08 09:20:26 -0800387 if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700388 mBottomNavBarVisible = true;
Heemin Seog991711a2020-04-24 00:38:39 -0700389 int height = mResources.getDimensionPixelSize(
390 com.android.internal.R.dimen.navigation_bar_height);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700391
392 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
Heemin Seog991711a2020-04-24 00:38:39 -0700393 ViewGroup.LayoutParams.MATCH_PARENT,
394 height,
395 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
Heemin Seog1a39dea2019-10-16 15:58:21 -0700396 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
397 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
398 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
399 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
400 PixelFormat.TRANSLUCENT);
Heemin Seog29ecf612020-04-14 22:47:01 -0700401 lp.setTitle("BottomCarNavigationBar");
Heemin Seog991711a2020-04-24 00:38:39 -0700402 lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR};
Heemin Seog1a39dea2019-10-16 15:58:21 -0700403 lp.windowAnimations = 0;
Heemin Seog991711a2020-04-24 00:38:39 -0700404 lp.gravity = Gravity.BOTTOM;
Heemin Seogd59786b2019-11-08 09:20:26 -0800405 mWindowManager.addView(mBottomNavigationBarWindow, lp);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700406 }
407
Heemin Seogfcccab72019-10-22 08:30:23 -0700408 if (mLeftNavigationBarWindow != null) {
Heemin Seog29ecf612020-04-14 22:47:01 -0700409 int width = mResources.getDimensionPixelSize(
Heemin Seog1a39dea2019-10-16 15:58:21 -0700410 R.dimen.car_left_navigation_bar_width);
411 WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams(
412 width, ViewGroup.LayoutParams.MATCH_PARENT,
413 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
414 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
415 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
416 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
417 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
418 PixelFormat.TRANSLUCENT);
419 leftlp.setTitle("LeftCarNavigationBar");
420 leftlp.windowAnimations = 0;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700421 leftlp.gravity = Gravity.LEFT;
422 mWindowManager.addView(mLeftNavigationBarWindow, leftlp);
423 }
Heemin Seog991711a2020-04-24 00:38:39 -0700424
Heemin Seogfcccab72019-10-22 08:30:23 -0700425 if (mRightNavigationBarWindow != null) {
Heemin Seog29ecf612020-04-14 22:47:01 -0700426 int width = mResources.getDimensionPixelSize(
Heemin Seog1a39dea2019-10-16 15:58:21 -0700427 R.dimen.car_right_navigation_bar_width);
428 WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams(
429 width, ViewGroup.LayoutParams.MATCH_PARENT,
430 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
431 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
432 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
433 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
434 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
435 PixelFormat.TRANSLUCENT);
436 rightlp.setTitle("RightCarNavigationBar");
437 rightlp.windowAnimations = 0;
Heemin Seog1a39dea2019-10-16 15:58:21 -0700438 rightlp.gravity = Gravity.RIGHT;
439 mWindowManager.addView(mRightNavigationBarWindow, rightlp);
440 }
441 }
442
443 /**
444 * We register for soft keyboard visibility events such that we can hide the navigation bar
445 * giving more screen space to the IME. Note: this is optional and controlled by
446 * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}.
447 */
448 @Override
449 public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
450 boolean showImeSwitcher) {
451 if (!mHideNavBarForKeyboard) {
452 return;
453 }
454
Heemin Seog29ecf612020-04-14 22:47:01 -0700455 if (mContext.getDisplayId() != displayId) {
Heemin Seog1a39dea2019-10-16 15:58:21 -0700456 return;
457 }
458
459 boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
Heemin Seog8d6ec6a72019-10-25 14:34:11 -0700460 mCarNavigationBarController.setBottomWindowVisibility(
461 isKeyboardVisible ? View.GONE : View.VISIBLE);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700462 }
463
Heemin Seog1a39dea2019-10-16 15:58:21 -0700464 @Override
JianYang Liu0e3c4782020-05-07 19:15:37 -0700465 public void onSystemBarAppearanceChanged(
466 int displayId,
467 @WindowInsetsController.Appearance int appearance,
468 AppearanceRegion[] appearanceRegions,
469 boolean navbarColorManagedByIme) {
470 if (displayId != mDisplayId) {
471 return;
472 }
473 boolean barModeChanged = updateStatusBarMode(
474 mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
475 int numStacks = appearanceRegions.length;
476 boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
477 for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
478 stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
479 }
480 if (stackAppearancesChanged || barModeChanged) {
481 mAppearanceRegions = appearanceRegions;
482 updateStatusBarAppearance();
483 }
484 }
485
486 private void updateStatusBarAppearance() {
487 int numStacks = mAppearanceRegions.length;
488 int numLightStacks = 0;
489
490 // We can only have maximum one light stack.
491 int indexLightStack = -1;
492
493 for (int i = 0; i < numStacks; i++) {
494 if (isLight(mAppearanceRegions[i].getAppearance())) {
495 numLightStacks++;
496 indexLightStack = i;
497 }
498 }
499
500 // If all stacks are light, all icons become dark.
501 if (numLightStacks == numStacks) {
502 mStatusBarIconController.setIconsDarkArea(null);
503 mStatusBarIconController.getTransitionsController().setIconsDark(
504 /* dark= */ true, /* animate= */ false);
505 } else if (numLightStacks == 0) {
506 // If no one is light, all icons become white.
507 mStatusBarIconController.getTransitionsController().setIconsDark(
508 /* dark= */ false, /* animate= */ false);
509 } else {
510 // Not the same for every stack, update icons in area only.
511 mStatusBarIconController.setIconsDarkArea(
512 mAppearanceRegions[indexLightStack].getBounds());
513 mStatusBarIconController.getTransitionsController().setIconsDark(
514 /* dark= */ true, /* animate= */ false);
515 }
516 }
517
518 private static boolean isLight(int appearance) {
519 return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0;
520 }
521
522 @Override
Heemin Seoge67cefea2020-01-28 12:02:50 -0800523 public void showTransient(int displayId, int[] types) {
524 if (displayId != mDisplayId) {
525 return;
526 }
Heemin Seog29ecf612020-04-14 22:47:01 -0700527 if (containsType(types, ITYPE_STATUS_BAR)) {
528 if (!mStatusBarTransientShown) {
529 mStatusBarTransientShown = true;
530 handleTransientChanged();
531 }
Heemin Seoge67cefea2020-01-28 12:02:50 -0800532 }
Heemin Seog29ecf612020-04-14 22:47:01 -0700533 if (containsType(types, ITYPE_NAVIGATION_BAR)) {
534 if (!mNavBarTransientShown) {
535 mNavBarTransientShown = true;
536 handleTransientChanged();
537 }
Heemin Seoge67cefea2020-01-28 12:02:50 -0800538 }
539 }
540
541 @Override
542 public void abortTransient(int displayId, int[] types) {
543 if (displayId != mDisplayId) {
544 return;
545 }
Heemin Seog29ecf612020-04-14 22:47:01 -0700546 if (!containsType(types, ITYPE_STATUS_BAR) && !containsType(types, ITYPE_NAVIGATION_BAR)) {
Heemin Seoge67cefea2020-01-28 12:02:50 -0800547 return;
548 }
549 clearTransient();
550 }
551
552 private void clearTransient() {
Heemin Seog29ecf612020-04-14 22:47:01 -0700553 if (mStatusBarTransientShown) {
554 mStatusBarTransientShown = false;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800555 handleTransientChanged();
556 }
Heemin Seog29ecf612020-04-14 22:47:01 -0700557 if (mNavBarTransientShown) {
558 mNavBarTransientShown = false;
559 handleTransientChanged();
560 }
561 }
562
563 @VisibleForTesting
564 boolean isStatusBarTransientShown() {
565 return mStatusBarTransientShown;
566 }
567
568 @VisibleForTesting
569 boolean isNavBarTransientShown() {
570 return mNavBarTransientShown;
Heemin Seoge67cefea2020-01-28 12:02:50 -0800571 }
572
573 @Override
Heemin Seog1a39dea2019-10-16 15:58:21 -0700574 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
575 pw.print(" mTaskStackListener=");
kwaky77d81dc2019-12-12 16:23:59 -0800576 pw.println(mButtonSelectionStateListener);
Heemin Seogd59786b2019-11-08 09:20:26 -0800577 pw.print(" mBottomNavigationBarView=");
578 pw.println(mBottomNavigationBarView);
Heemin Seog1a39dea2019-10-16 15:58:21 -0700579 }
Heemin Seoge67cefea2020-01-28 12:02:50 -0800580
581 private void handleTransientChanged() {
Heemin Seog29ecf612020-04-14 22:47:01 -0700582 updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
583 updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
Heemin Seoge67cefea2020-01-28 12:02:50 -0800584 }
585
Heemin Seog29ecf612020-04-14 22:47:01 -0700586 // Returns true if the status bar mode has changed.
587 private boolean updateStatusBarMode(int barMode) {
588 if (mStatusBarMode != barMode) {
589 mStatusBarMode = barMode;
590 mAutoHideController.touchAutoHide();
591 return true;
592 }
593 return false;
594 }
595
596 // Returns true if the nav bar mode has changed.
597 private boolean updateNavBarMode(int barMode) {
Heemin Seoge67cefea2020-01-28 12:02:50 -0800598 if (mNavigationBarMode != barMode) {
599 mNavigationBarMode = barMode;
600 mAutoHideController.touchAutoHide();
601 return true;
602 }
603 return false;
604 }
Heemin Seog1a39dea2019-10-16 15:58:21 -0700605}