1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.car.navigationbar; 18 19 import static android.view.InsetsState.ITYPE_CLIMATE_BAR; 20 import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; 21 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; 22 import static android.view.InsetsState.ITYPE_STATUS_BAR; 23 import static android.view.InsetsState.containsType; 24 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; 25 26 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 27 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 28 29 import android.content.Context; 30 import android.content.res.Resources; 31 import android.graphics.PixelFormat; 32 import android.inputmethodservice.InputMethodService; 33 import android.os.Handler; 34 import android.os.IBinder; 35 import android.os.RemoteException; 36 import android.view.Display; 37 import android.view.Gravity; 38 import android.view.View; 39 import android.view.ViewGroup; 40 import android.view.WindowInsetsController; 41 import android.view.WindowManager; 42 43 import androidx.annotation.VisibleForTesting; 44 45 import com.android.internal.statusbar.IStatusBarService; 46 import com.android.internal.statusbar.RegisterStatusBarResult; 47 import com.android.internal.view.AppearanceRegion; 48 import com.android.systemui.R; 49 import com.android.systemui.SystemUI; 50 import com.android.systemui.car.CarDeviceProvisionedController; 51 import com.android.systemui.car.CarDeviceProvisionedListener; 52 import com.android.systemui.dagger.qualifiers.Main; 53 import com.android.systemui.dagger.qualifiers.UiBackground; 54 import com.android.systemui.plugins.DarkIconDispatcher; 55 import com.android.systemui.shared.system.ActivityManagerWrapper; 56 import com.android.systemui.statusbar.AutoHideUiElement; 57 import com.android.systemui.statusbar.CommandQueue; 58 import com.android.systemui.statusbar.phone.AutoHideController; 59 import com.android.systemui.statusbar.phone.BarTransitions; 60 import com.android.systemui.statusbar.phone.LightBarController; 61 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; 62 import com.android.systemui.statusbar.phone.StatusBarIconController; 63 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; 64 import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher; 65 import com.android.systemui.statusbar.policy.KeyguardStateController; 66 67 import java.io.FileDescriptor; 68 import java.io.PrintWriter; 69 import java.util.concurrent.Executor; 70 71 import javax.inject.Inject; 72 73 import dagger.Lazy; 74 75 /** Navigation bars customized for the automotive use case. */ 76 public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks { 77 78 private final Resources mResources; 79 private final CarNavigationBarController mCarNavigationBarController; 80 private final SysuiDarkIconDispatcher mStatusBarIconController; 81 private final WindowManager mWindowManager; 82 private final CarDeviceProvisionedController mCarDeviceProvisionedController; 83 private final CommandQueue mCommandQueue; 84 private final AutoHideController mAutoHideController; 85 private final ButtonSelectionStateListener mButtonSelectionStateListener; 86 private final Handler mMainHandler; 87 private final Executor mUiBgExecutor; 88 private final IStatusBarService mBarService; 89 private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy; 90 private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy; 91 private final Lazy<StatusBarIconController> mIconControllerLazy; 92 93 private final int mDisplayId; 94 95 private StatusBarSignalPolicy mSignalPolicy; 96 private ActivityManagerWrapper mActivityManagerWrapper; 97 98 // If the nav bar should be hidden when the soft keyboard is visible. 99 private boolean mHideNavBarForKeyboard; 100 private boolean mBottomNavBarVisible; 101 102 // Nav bar views. 103 private ViewGroup mTopNavigationBarWindow; 104 private ViewGroup mBottomNavigationBarWindow; 105 private ViewGroup mLeftNavigationBarWindow; 106 private ViewGroup mRightNavigationBarWindow; 107 private CarNavigationBarView mTopNavigationBarView; 108 private CarNavigationBarView mBottomNavigationBarView; 109 private CarNavigationBarView mLeftNavigationBarView; 110 private CarNavigationBarView mRightNavigationBarView; 111 112 // To be attached to the navigation bars such that they can close the notification panel if 113 // it's open. 114 private boolean mDeviceIsSetUpForUser = true; 115 private boolean mIsUserSetupInProgress = false; 116 117 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; 118 @BarTransitions.TransitionMode 119 private int mStatusBarMode; 120 @BarTransitions.TransitionMode 121 private int mNavigationBarMode; 122 private boolean mStatusBarTransientShown; 123 private boolean mNavBarTransientShown; 124 125 @Inject CarNavigationBar(Context context, @Main Resources resources, CarNavigationBarController carNavigationBarController, LightBarController lightBarController, DarkIconDispatcher darkIconDispatcher, WindowManager windowManager, CarDeviceProvisionedController deviceProvisionedController, CommandQueue commandQueue, AutoHideController autoHideController, ButtonSelectionStateListener buttonSelectionStateListener, @Main Handler mainHandler, @UiBackground Executor uiBgExecutor, IStatusBarService barService, Lazy<KeyguardStateController> keyguardStateControllerLazy, Lazy<PhoneStatusBarPolicy> iconPolicyLazy, Lazy<StatusBarIconController> iconControllerLazy )126 public CarNavigationBar(Context context, 127 @Main Resources resources, 128 CarNavigationBarController carNavigationBarController, 129 // TODO(b/156052638): Should not need to inject LightBarController 130 LightBarController lightBarController, 131 DarkIconDispatcher darkIconDispatcher, 132 WindowManager windowManager, 133 CarDeviceProvisionedController deviceProvisionedController, 134 CommandQueue commandQueue, 135 AutoHideController autoHideController, 136 ButtonSelectionStateListener buttonSelectionStateListener, 137 @Main Handler mainHandler, 138 @UiBackground Executor uiBgExecutor, 139 IStatusBarService barService, 140 Lazy<KeyguardStateController> keyguardStateControllerLazy, 141 Lazy<PhoneStatusBarPolicy> iconPolicyLazy, 142 Lazy<StatusBarIconController> iconControllerLazy 143 ) { 144 super(context); 145 mResources = resources; 146 mCarNavigationBarController = carNavigationBarController; 147 mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher; 148 mWindowManager = windowManager; 149 mCarDeviceProvisionedController = deviceProvisionedController; 150 mCommandQueue = commandQueue; 151 mAutoHideController = autoHideController; 152 mButtonSelectionStateListener = buttonSelectionStateListener; 153 mMainHandler = mainHandler; 154 mUiBgExecutor = uiBgExecutor; 155 mBarService = barService; 156 mKeyguardStateControllerLazy = keyguardStateControllerLazy; 157 mIconPolicyLazy = iconPolicyLazy; 158 mIconControllerLazy = iconControllerLazy; 159 160 mDisplayId = context.getDisplayId(); 161 } 162 163 @Override start()164 public void start() { 165 // Set initial state. 166 mHideNavBarForKeyboard = mResources.getBoolean( 167 com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard); 168 mBottomNavBarVisible = false; 169 170 // Connect into the status bar manager service 171 mCommandQueue.addCallback(this); 172 173 RegisterStatusBarResult result = null; 174 try { 175 result = mBarService.registerStatusBar(mCommandQueue); 176 } catch (RemoteException ex) { 177 ex.rethrowFromSystemServer(); 178 } 179 180 onSystemBarAppearanceChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions, 181 result.mNavbarColorManagedByIme); 182 183 // StatusBarManagerService has a back up of IME token and it's restored here. 184 setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis, 185 result.mImeBackDisposition, result.mShowImeSwitcher); 186 187 // Set up the initial icon state 188 int numIcons = result.mIcons.size(); 189 for (int i = 0; i < numIcons; i++) { 190 mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); 191 } 192 193 mAutoHideController.setStatusBar(new AutoHideUiElement() { 194 @Override 195 public void synchronizeState() { 196 // No op. 197 } 198 199 @Override 200 public boolean isVisible() { 201 return mStatusBarTransientShown; 202 } 203 204 @Override 205 public void hide() { 206 clearTransient(); 207 } 208 }); 209 210 mAutoHideController.setNavigationBar(new AutoHideUiElement() { 211 @Override 212 public void synchronizeState() { 213 // No op. 214 } 215 216 @Override 217 public boolean isVisible() { 218 return mNavBarTransientShown; 219 } 220 221 @Override 222 public void hide() { 223 clearTransient(); 224 } 225 }); 226 227 mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup(); 228 mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress(); 229 mCarDeviceProvisionedController.addCallback( 230 new CarDeviceProvisionedListener() { 231 @Override 232 public void onUserSetupInProgressChanged() { 233 mMainHandler.post(() -> restartNavBarsIfNecessary()); 234 } 235 236 @Override 237 public void onUserSetupChanged() { 238 mMainHandler.post(() -> restartNavBarsIfNecessary()); 239 } 240 241 @Override 242 public void onUserSwitched() { 243 mMainHandler.post(() -> restartNavBarsIfNecessary()); 244 } 245 }); 246 247 createNavigationBar(result); 248 249 mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); 250 mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener); 251 252 mUiBgExecutor.execute(mCarNavigationBarController::connectToHvac); 253 254 // Lastly, call to the icon policy to install/update all the icons. 255 // Must be called on the main thread due to the use of observeForever() in 256 // mIconPolicy.init(). 257 mMainHandler.post(() -> { 258 mIconPolicyLazy.get().init(); 259 mSignalPolicy = new StatusBarSignalPolicy(mContext, mIconControllerLazy.get()); 260 }); 261 } 262 restartNavBarsIfNecessary()263 private void restartNavBarsIfNecessary() { 264 boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup(); 265 boolean currentUserSetupInProgress = mCarDeviceProvisionedController 266 .isCurrentUserSetupInProgress(); 267 if (mIsUserSetupInProgress != currentUserSetupInProgress 268 || mDeviceIsSetUpForUser != currentUserSetup) { 269 mDeviceIsSetUpForUser = currentUserSetup; 270 mIsUserSetupInProgress = currentUserSetupInProgress; 271 restartNavBars(); 272 } 273 } 274 275 /** 276 * Remove all content from navbars and rebuild them. Used to allow for different nav bars 277 * before and after the device is provisioned. . Also for change of density and font size. 278 */ restartNavBars()279 private void restartNavBars() { 280 // remove and reattach all components such that we don't keep a reference to unused ui 281 // elements 282 mCarNavigationBarController.removeAll(); 283 284 if (mTopNavigationBarWindow != null) { 285 mTopNavigationBarWindow.removeAllViews(); 286 mTopNavigationBarView = null; 287 } 288 289 if (mBottomNavigationBarWindow != null) { 290 mBottomNavigationBarWindow.removeAllViews(); 291 mBottomNavigationBarView = null; 292 } 293 294 if (mLeftNavigationBarWindow != null) { 295 mLeftNavigationBarWindow.removeAllViews(); 296 mLeftNavigationBarView = null; 297 } 298 299 if (mRightNavigationBarWindow != null) { 300 mRightNavigationBarWindow.removeAllViews(); 301 mRightNavigationBarView = null; 302 } 303 304 buildNavBarContent(); 305 // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need 306 // to correctly respect that state. 307 if (mKeyguardStateControllerLazy.get().isShowing()) { 308 mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser()); 309 } else { 310 mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser()); 311 } 312 313 // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the 314 // selection state that reflects the current task stack. 315 mButtonSelectionStateListener.onTaskStackChanged(); 316 } 317 isDeviceSetupForUser()318 private boolean isDeviceSetupForUser() { 319 return mDeviceIsSetUpForUser && !mIsUserSetupInProgress; 320 } 321 createNavigationBar(RegisterStatusBarResult result)322 private void createNavigationBar(RegisterStatusBarResult result) { 323 buildNavBarWindows(); 324 buildNavBarContent(); 325 attachNavBarWindows(); 326 327 // Try setting up the initial state of the nav bar if applicable. 328 if (result != null) { 329 setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken, 330 result.mImeWindowVis, result.mImeBackDisposition, 331 result.mShowImeSwitcher); 332 } 333 } 334 buildNavBarWindows()335 private void buildNavBarWindows() { 336 mTopNavigationBarWindow = mCarNavigationBarController.getTopWindow(); 337 mBottomNavigationBarWindow = mCarNavigationBarController.getBottomWindow(); 338 mLeftNavigationBarWindow = mCarNavigationBarController.getLeftWindow(); 339 mRightNavigationBarWindow = mCarNavigationBarController.getRightWindow(); 340 } 341 buildNavBarContent()342 private void buildNavBarContent() { 343 mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser()); 344 if (mTopNavigationBarView != null) { 345 mTopNavigationBarWindow.addView(mTopNavigationBarView); 346 } 347 348 mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser()); 349 if (mBottomNavigationBarView != null) { 350 mBottomNavigationBarWindow.addView(mBottomNavigationBarView); 351 } 352 353 mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser()); 354 if (mLeftNavigationBarView != null) { 355 mLeftNavigationBarWindow.addView(mLeftNavigationBarView); 356 } 357 358 mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser()); 359 if (mRightNavigationBarView != null) { 360 mRightNavigationBarWindow.addView(mRightNavigationBarView); 361 } 362 } 363 attachNavBarWindows()364 private void attachNavBarWindows() { 365 if (mTopNavigationBarWindow != null) { 366 int height = mResources.getDimensionPixelSize( 367 com.android.internal.R.dimen.status_bar_height); 368 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 369 ViewGroup.LayoutParams.MATCH_PARENT, 370 height, 371 WindowManager.LayoutParams.TYPE_STATUS_BAR, 372 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 373 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 374 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 375 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 376 PixelFormat.TRANSLUCENT); 377 lp.setTitle("TopCarNavigationBar"); 378 lp.windowAnimations = 0; 379 lp.gravity = Gravity.TOP; 380 mWindowManager.addView(mTopNavigationBarWindow, lp); 381 } 382 383 if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { 384 mBottomNavBarVisible = true; 385 int height = mResources.getDimensionPixelSize( 386 com.android.internal.R.dimen.navigation_bar_height); 387 388 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 389 ViewGroup.LayoutParams.MATCH_PARENT, 390 height, 391 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR, 392 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 393 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 394 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 395 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 396 PixelFormat.TRANSLUCENT); 397 lp.setTitle("BottomCarNavigationBar"); 398 lp.windowAnimations = 0; 399 lp.gravity = Gravity.BOTTOM; 400 mWindowManager.addView(mBottomNavigationBarWindow, lp); 401 } 402 403 if (mLeftNavigationBarWindow != null) { 404 int width = mResources.getDimensionPixelSize( 405 R.dimen.car_left_navigation_bar_width); 406 WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams( 407 width, ViewGroup.LayoutParams.MATCH_PARENT, 408 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, 409 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 410 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 411 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 412 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 413 PixelFormat.TRANSLUCENT); 414 leftlp.setTitle("LeftCarNavigationBar"); 415 leftlp.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR}; 416 leftlp.setFitInsetsTypes(0); 417 leftlp.windowAnimations = 0; 418 leftlp.gravity = Gravity.LEFT; 419 mWindowManager.addView(mLeftNavigationBarWindow, leftlp); 420 } 421 422 if (mRightNavigationBarWindow != null) { 423 int width = mResources.getDimensionPixelSize( 424 R.dimen.car_right_navigation_bar_width); 425 WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams( 426 width, ViewGroup.LayoutParams.MATCH_PARENT, 427 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, 428 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 429 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 430 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 431 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 432 PixelFormat.TRANSLUCENT); 433 rightlp.setTitle("RightCarNavigationBar"); 434 rightlp.providesInsetsTypes = new int[]{ITYPE_EXTRA_NAVIGATION_BAR}; 435 rightlp.setFitInsetsTypes(0); 436 rightlp.windowAnimations = 0; 437 rightlp.gravity = Gravity.RIGHT; 438 mWindowManager.addView(mRightNavigationBarWindow, rightlp); 439 } 440 } 441 442 /** 443 * We register for soft keyboard visibility events such that we can hide the navigation bar 444 * giving more screen space to the IME. Note: this is optional and controlled by 445 * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}. 446 */ 447 @Override setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher)448 public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, 449 boolean showImeSwitcher) { 450 if (!mHideNavBarForKeyboard) { 451 return; 452 } 453 454 if (mContext.getDisplayId() != displayId) { 455 return; 456 } 457 458 boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; 459 mCarNavigationBarController.setBottomWindowVisibility( 460 isKeyboardVisible ? View.GONE : View.VISIBLE); 461 } 462 463 @Override onSystemBarAppearanceChanged( int displayId, @WindowInsetsController.Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme)464 public void onSystemBarAppearanceChanged( 465 int displayId, 466 @WindowInsetsController.Appearance int appearance, 467 AppearanceRegion[] appearanceRegions, 468 boolean navbarColorManagedByIme) { 469 if (displayId != mDisplayId) { 470 return; 471 } 472 boolean barModeChanged = updateStatusBarMode( 473 mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 474 int numStacks = appearanceRegions.length; 475 boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks; 476 for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) { 477 stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]); 478 } 479 if (stackAppearancesChanged || barModeChanged) { 480 mAppearanceRegions = appearanceRegions; 481 updateStatusBarAppearance(); 482 } 483 } 484 updateStatusBarAppearance()485 private void updateStatusBarAppearance() { 486 int numStacks = mAppearanceRegions.length; 487 int numLightStacks = 0; 488 489 // We can only have maximum one light stack. 490 int indexLightStack = -1; 491 492 for (int i = 0; i < numStacks; i++) { 493 if (isLight(mAppearanceRegions[i].getAppearance())) { 494 numLightStacks++; 495 indexLightStack = i; 496 } 497 } 498 499 // If all stacks are light, all icons become dark. 500 if (numLightStacks == numStacks) { 501 mStatusBarIconController.setIconsDarkArea(null); 502 mStatusBarIconController.getTransitionsController().setIconsDark( 503 /* dark= */ true, /* animate= */ false); 504 } else if (numLightStacks == 0) { 505 // If no one is light, all icons become white. 506 mStatusBarIconController.getTransitionsController().setIconsDark( 507 /* dark= */ false, /* animate= */ false); 508 } else { 509 // Not the same for every stack, update icons in area only. 510 mStatusBarIconController.setIconsDarkArea( 511 mAppearanceRegions[indexLightStack].getBounds()); 512 mStatusBarIconController.getTransitionsController().setIconsDark( 513 /* dark= */ true, /* animate= */ false); 514 } 515 } 516 isLight(int appearance)517 private static boolean isLight(int appearance) { 518 return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0; 519 } 520 521 @Override showTransient(int displayId, int[] types)522 public void showTransient(int displayId, int[] types) { 523 if (displayId != mDisplayId) { 524 return; 525 } 526 if (containsType(types, ITYPE_STATUS_BAR)) { 527 if (!mStatusBarTransientShown) { 528 mStatusBarTransientShown = true; 529 handleTransientChanged(); 530 } 531 } 532 if (containsType(types, ITYPE_NAVIGATION_BAR)) { 533 if (!mNavBarTransientShown) { 534 mNavBarTransientShown = true; 535 handleTransientChanged(); 536 } 537 } 538 } 539 540 @Override abortTransient(int displayId, int[] types)541 public void abortTransient(int displayId, int[] types) { 542 if (displayId != mDisplayId) { 543 return; 544 } 545 if (!containsType(types, ITYPE_STATUS_BAR) && !containsType(types, ITYPE_NAVIGATION_BAR)) { 546 return; 547 } 548 clearTransient(); 549 } 550 clearTransient()551 private void clearTransient() { 552 if (mStatusBarTransientShown) { 553 mStatusBarTransientShown = false; 554 handleTransientChanged(); 555 } 556 if (mNavBarTransientShown) { 557 mNavBarTransientShown = false; 558 handleTransientChanged(); 559 } 560 } 561 562 @VisibleForTesting isStatusBarTransientShown()563 boolean isStatusBarTransientShown() { 564 return mStatusBarTransientShown; 565 } 566 567 @VisibleForTesting isNavBarTransientShown()568 boolean isNavBarTransientShown() { 569 return mNavBarTransientShown; 570 } 571 572 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)573 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 574 pw.print(" mTaskStackListener="); 575 pw.println(mButtonSelectionStateListener); 576 pw.print(" mBottomNavigationBarView="); 577 pw.println(mBottomNavigationBarView); 578 } 579 handleTransientChanged()580 private void handleTransientChanged() { 581 updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 582 updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 583 } 584 585 // Returns true if the status bar mode has changed. updateStatusBarMode(int barMode)586 private boolean updateStatusBarMode(int barMode) { 587 if (mStatusBarMode != barMode) { 588 mStatusBarMode = barMode; 589 mAutoHideController.touchAutoHide(); 590 return true; 591 } 592 return false; 593 } 594 595 // Returns true if the nav bar mode has changed. updateNavBarMode(int barMode)596 private boolean updateNavBarMode(int barMode) { 597 if (mNavigationBarMode != barMode) { 598 mNavigationBarMode = barMode; 599 mAutoHideController.touchAutoHide(); 600 return true; 601 } 602 return false; 603 } 604 } 605