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.systembar; 18 19 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; 20 21 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; 22 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; 23 24 import android.app.StatusBarManager.Disable2Flags; 25 import android.app.StatusBarManager.DisableFlags; 26 import android.app.UiModeManager; 27 import android.content.Context; 28 import android.content.res.Configuration; 29 import android.graphics.Rect; 30 import android.inputmethodservice.InputMethodService; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.view.View; 34 import android.view.ViewGroup; 35 import android.view.WindowInsets; 36 import android.view.WindowInsets.Type.InsetsType; 37 import android.view.WindowInsetsController; 38 import android.view.WindowManager; 39 40 import androidx.annotation.VisibleForTesting; 41 42 import com.android.internal.statusbar.IStatusBarService; 43 import com.android.internal.statusbar.LetterboxDetails; 44 import com.android.internal.statusbar.RegisterStatusBarResult; 45 import com.android.internal.view.AppearanceRegion; 46 import com.android.systemui.CoreStartable; 47 import com.android.systemui.R; 48 import com.android.systemui.car.CarDeviceProvisionedController; 49 import com.android.systemui.car.CarDeviceProvisionedListener; 50 import com.android.systemui.car.hvac.HvacController; 51 import com.android.systemui.car.users.CarSystemUIUserUtil; 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.settings.DisplayTracker; 56 import com.android.systemui.shared.system.TaskStackChangeListener; 57 import com.android.systemui.shared.system.TaskStackChangeListeners; 58 import com.android.systemui.statusbar.AutoHideUiElement; 59 import com.android.systemui.statusbar.CommandQueue; 60 import com.android.systemui.statusbar.phone.AutoHideController; 61 import com.android.systemui.statusbar.phone.BarTransitions; 62 import com.android.systemui.statusbar.phone.LightBarController; 63 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; 64 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; 65 import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher; 66 import com.android.systemui.statusbar.policy.ConfigurationController; 67 import com.android.systemui.statusbar.policy.KeyguardStateController; 68 import com.android.systemui.util.concurrency.DelayableExecutor; 69 import com.android.systemui.wm.MDSystemBarsController; 70 71 import dagger.Lazy; 72 73 import java.io.PrintWriter; 74 import java.util.ArrayList; 75 import java.util.Optional; 76 import java.util.concurrent.Executor; 77 78 import javax.inject.Inject; 79 80 /** Navigation bars customized for the automotive use case. */ 81 public class CarSystemBar implements CoreStartable, CommandQueue.Callbacks, 82 ConfigurationController.ConfigurationListener, 83 MDSystemBarsController.Listener { 84 private final Context mContext; 85 private final CarSystemBarController mCarSystemBarController; 86 private final SysuiDarkIconDispatcher mStatusBarIconController; 87 private final WindowManager mWindowManager; 88 private final CarDeviceProvisionedController mCarDeviceProvisionedController; 89 private final CommandQueue mCommandQueue; 90 private final AutoHideController mAutoHideController; 91 private final ButtonSelectionStateListener mButtonSelectionStateListener; 92 private final DelayableExecutor mExecutor; 93 private final Executor mUiBgExecutor; 94 private final IStatusBarService mBarService; 95 private final DisplayTracker mDisplayTracker; 96 private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy; 97 private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy; 98 private final HvacController mHvacController; 99 100 private UiModeManager mUiModeManager; 101 102 private final int mDisplayId; 103 private final SystemBarConfigs mSystemBarConfigs; 104 105 private StatusBarSignalPolicy mSignalPolicy; 106 107 // If the nav bar should be hidden when the soft keyboard is visible. 108 private boolean mHideTopBarForKeyboard; 109 private boolean mHideLeftBarForKeyboard; 110 private boolean mHideRightBarForKeyboard; 111 private boolean mHideBottomBarForKeyboard; 112 113 private boolean mBottomNavBarVisible; 114 115 // Nav bar views. 116 private ViewGroup mTopSystemBarWindow; 117 private ViewGroup mBottomSystemBarWindow; 118 private ViewGroup mLeftSystemBarWindow; 119 private ViewGroup mRightSystemBarWindow; 120 private CarSystemBarView mTopSystemBarView; 121 private CarSystemBarView mBottomSystemBarView; 122 private CarSystemBarView mLeftSystemBarView; 123 private CarSystemBarView mRightSystemBarView; 124 125 // To be attached to the navigation bars such that they can close the notification panel if 126 // it's open. 127 private boolean mDeviceIsSetUpForUser = true; 128 private boolean mIsUserSetupInProgress = false; 129 130 private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; 131 @BarTransitions.TransitionMode 132 private int mStatusBarMode; 133 @BarTransitions.TransitionMode 134 private int mSystemBarMode; 135 private boolean mStatusBarTransientShown; 136 private boolean mNavBarTransientShown; 137 138 private boolean mIsUiModeNight = false; 139 private MDSystemBarsController mMDSystemBarsController; 140 141 @Inject CarSystemBar(Context context, CarSystemBarController carSystemBarController, LightBarController lightBarController, DarkIconDispatcher darkIconDispatcher, WindowManager windowManager, CarDeviceProvisionedController deviceProvisionedController, CommandQueue commandQueue, AutoHideController autoHideController, ButtonSelectionStateListener buttonSelectionStateListener, @Main DelayableExecutor mainExecutor, @UiBackground Executor uiBgExecutor, IStatusBarService barService, Lazy<KeyguardStateController> keyguardStateControllerLazy, Lazy<PhoneStatusBarPolicy> iconPolicyLazy, HvacController hvacController, StatusBarSignalPolicy signalPolicy, SystemBarConfigs systemBarConfigs, ConfigurationController configurationController, DisplayTracker displayTracker, Optional<MDSystemBarsController> mdSystemBarsController )142 public CarSystemBar(Context context, 143 CarSystemBarController carSystemBarController, 144 // TODO(b/156052638): Should not need to inject LightBarController 145 LightBarController lightBarController, 146 DarkIconDispatcher darkIconDispatcher, 147 WindowManager windowManager, 148 CarDeviceProvisionedController deviceProvisionedController, 149 CommandQueue commandQueue, 150 AutoHideController autoHideController, 151 ButtonSelectionStateListener buttonSelectionStateListener, 152 @Main DelayableExecutor mainExecutor, 153 @UiBackground Executor uiBgExecutor, 154 IStatusBarService barService, 155 Lazy<KeyguardStateController> keyguardStateControllerLazy, 156 Lazy<PhoneStatusBarPolicy> iconPolicyLazy, 157 HvacController hvacController, 158 StatusBarSignalPolicy signalPolicy, 159 SystemBarConfigs systemBarConfigs, 160 ConfigurationController configurationController, 161 DisplayTracker displayTracker, 162 Optional<MDSystemBarsController> mdSystemBarsController 163 ) { 164 mContext = context; 165 mCarSystemBarController = carSystemBarController; 166 mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher; 167 mWindowManager = windowManager; 168 mCarDeviceProvisionedController = deviceProvisionedController; 169 mCommandQueue = commandQueue; 170 mAutoHideController = autoHideController; 171 mButtonSelectionStateListener = buttonSelectionStateListener; 172 mExecutor = mainExecutor; 173 mUiBgExecutor = uiBgExecutor; 174 mBarService = barService; 175 mKeyguardStateControllerLazy = keyguardStateControllerLazy; 176 mIconPolicyLazy = iconPolicyLazy; 177 mHvacController = hvacController; 178 mSystemBarConfigs = systemBarConfigs; 179 mSignalPolicy = signalPolicy; 180 mDisplayId = context.getDisplayId(); 181 mUiModeManager = mContext.getSystemService(UiModeManager.class); 182 mDisplayTracker = displayTracker; 183 mIsUiModeNight = mContext.getResources().getConfiguration().isNightModeActive(); 184 configurationController.addCallback(this); 185 mMDSystemBarsController = mdSystemBarsController.orElse(null); 186 } 187 188 @Override start()189 public void start() { 190 // Set initial state. 191 mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP); 192 mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( 193 SystemBarConfigs.BOTTOM); 194 mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT); 195 mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( 196 SystemBarConfigs.RIGHT); 197 198 mBottomNavBarVisible = false; 199 200 // Connect into the status bar manager service 201 mCommandQueue.addCallback(this); 202 203 RegisterStatusBarResult result = null; 204 //Register only for Primary User. 205 if (!CarSystemUIUserUtil.isSecondaryMUMDSystemUI()) { 206 try { 207 result = mBarService.registerStatusBar(mCommandQueue); 208 } catch (RemoteException ex) { 209 ex.rethrowFromSystemServer(); 210 } 211 } else if (mMDSystemBarsController != null) { 212 mMDSystemBarsController.addListener(this); 213 } 214 215 if (result != null) { 216 onSystemBarAttributesChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions, 217 result.mNavbarColorManagedByIme, result.mBehavior, 218 result.mRequestedVisibleTypes, 219 result.mPackageName, result.mLetterboxDetails); 220 221 // StatusBarManagerService has a back up of IME token and it's restored here. 222 setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis, 223 result.mImeBackDisposition, result.mShowImeSwitcher); 224 225 // Set up the initial icon state 226 int numIcons = result.mIcons.size(); 227 for (int i = 0; i < numIcons; i++) { 228 mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); 229 } 230 } 231 232 mAutoHideController.setStatusBar(new AutoHideUiElement() { 233 @Override 234 public void synchronizeState() { 235 // No op. 236 } 237 238 @Override 239 public boolean isVisible() { 240 return mStatusBarTransientShown; 241 } 242 243 @Override 244 public void hide() { 245 clearTransient(); 246 } 247 }); 248 249 mAutoHideController.setNavigationBar(new AutoHideUiElement() { 250 @Override 251 public void synchronizeState() { 252 // No op. 253 } 254 255 @Override 256 public boolean isVisible() { 257 return mNavBarTransientShown; 258 } 259 260 @Override 261 public void hide() { 262 clearTransient(); 263 } 264 }); 265 266 mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup(); 267 mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress(); 268 mCarDeviceProvisionedController.addCallback( 269 new CarDeviceProvisionedListener() { 270 @Override 271 public void onUserSetupInProgressChanged() { 272 mExecutor.execute(() -> restartNavBarsIfNecessary()); 273 } 274 275 @Override 276 public void onUserSetupChanged() { 277 mExecutor.execute(() -> restartNavBarsIfNecessary()); 278 } 279 280 @Override 281 public void onUserSwitched() { 282 mExecutor.execute(() -> restartNavBarsIfNecessary()); 283 } 284 }); 285 286 createSystemBar(result); 287 288 TaskStackChangeListeners.getInstance().registerTaskStackListener( 289 mButtonSelectionStateListener); 290 TaskStackChangeListeners.getInstance().registerTaskStackListener( 291 new TaskStackChangeListener() { 292 @Override 293 public void onLockTaskModeChanged(int mode) { 294 mCarSystemBarController.refreshSystemBar(); 295 } 296 }); 297 298 // Lastly, call to the icon policy to install/update all the icons. 299 // Must be called on the main thread due to the use of observeForever() in 300 // mIconPolicy.init(). 301 mExecutor.execute(() -> { 302 mIconPolicyLazy.get().init(); 303 }); 304 } 305 restartNavBarsIfNecessary()306 private void restartNavBarsIfNecessary() { 307 boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup(); 308 boolean currentUserSetupInProgress = mCarDeviceProvisionedController 309 .isCurrentUserSetupInProgress(); 310 if (mIsUserSetupInProgress != currentUserSetupInProgress 311 || mDeviceIsSetUpForUser != currentUserSetup) { 312 mDeviceIsSetUpForUser = currentUserSetup; 313 mIsUserSetupInProgress = currentUserSetupInProgress; 314 restartNavBars(); 315 } 316 } 317 318 /** 319 * Remove all content from navbars and rebuild them. Used to allow for different nav bars 320 * before and after the device is provisioned. . Also for change of density and font size. 321 */ restartNavBars()322 private void restartNavBars() { 323 // remove and reattach all components such that we don't keep a reference to unused ui 324 // elements 325 mCarSystemBarController.removeAll(); 326 327 if (mTopSystemBarWindow != null) { 328 mTopSystemBarWindow.removeAllViews(); 329 mHvacController.unregisterViews(mTopSystemBarView); 330 mTopSystemBarView = null; 331 } 332 333 if (mBottomSystemBarWindow != null) { 334 mBottomSystemBarWindow.removeAllViews(); 335 mHvacController.unregisterViews(mBottomSystemBarView); 336 mBottomSystemBarView = null; 337 } 338 339 if (mLeftSystemBarWindow != null) { 340 mLeftSystemBarWindow.removeAllViews(); 341 mHvacController.unregisterViews(mLeftSystemBarView); 342 mLeftSystemBarView = null; 343 } 344 345 if (mRightSystemBarWindow != null) { 346 mRightSystemBarWindow.removeAllViews(); 347 mHvacController.unregisterViews(mRightSystemBarView); 348 mRightSystemBarView = null; 349 } 350 351 buildNavBarContent(); 352 // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need 353 // to correctly respect that state. 354 if (mKeyguardStateControllerLazy.get().isShowing()) { 355 mCarSystemBarController.showAllKeyguardButtons(isDeviceSetupForUser()); 356 } else { 357 mCarSystemBarController.showAllNavigationButtons(isDeviceSetupForUser()); 358 } 359 360 // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the 361 // selection state that reflects the current task stack. 362 mButtonSelectionStateListener.onTaskStackChanged(); 363 } 364 isDeviceSetupForUser()365 private boolean isDeviceSetupForUser() { 366 return mDeviceIsSetUpForUser && !mIsUserSetupInProgress; 367 } 368 createSystemBar(RegisterStatusBarResult result)369 private void createSystemBar(RegisterStatusBarResult result) { 370 buildNavBarWindows(); 371 buildNavBarContent(); 372 attachNavBarWindows(); 373 374 // Try setting up the initial state of the nav bar if applicable. 375 if (result != null) { 376 setImeWindowStatus(mDisplayTracker.getDefaultDisplayId(), result.mImeToken, 377 result.mImeWindowVis, result.mImeBackDisposition, 378 result.mShowImeSwitcher); 379 } 380 } 381 buildNavBarWindows()382 private void buildNavBarWindows() { 383 mTopSystemBarWindow = mCarSystemBarController.getTopWindow(); 384 mBottomSystemBarWindow = mCarSystemBarController.getBottomWindow(); 385 mLeftSystemBarWindow = mCarSystemBarController.getLeftWindow(); 386 mRightSystemBarWindow = mCarSystemBarController.getRightWindow(); 387 } 388 buildNavBarContent()389 private void buildNavBarContent() { 390 mTopSystemBarView = mCarSystemBarController.getTopBar(isDeviceSetupForUser()); 391 if (mTopSystemBarView != null) { 392 mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopSystemBarView); 393 mHvacController.registerHvacViews(mTopSystemBarView); 394 mTopSystemBarWindow.addView(mTopSystemBarView); 395 } 396 397 mBottomSystemBarView = mCarSystemBarController.getBottomBar(isDeviceSetupForUser()); 398 if (mBottomSystemBarView != null) { 399 mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomSystemBarView); 400 mHvacController.registerHvacViews(mBottomSystemBarView); 401 mBottomSystemBarWindow.addView(mBottomSystemBarView); 402 } 403 404 mLeftSystemBarView = mCarSystemBarController.getLeftBar(isDeviceSetupForUser()); 405 if (mLeftSystemBarView != null) { 406 mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftSystemBarView); 407 mHvacController.registerHvacViews(mLeftSystemBarView); 408 mLeftSystemBarWindow.addView(mLeftSystemBarView); 409 } 410 411 mRightSystemBarView = mCarSystemBarController.getRightBar(isDeviceSetupForUser()); 412 if (mRightSystemBarView != null) { 413 mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightSystemBarView); 414 mHvacController.registerHvacViews(mRightSystemBarView); 415 mRightSystemBarWindow.addView(mRightSystemBarView); 416 } 417 } 418 attachNavBarWindows()419 private void attachNavBarWindows() { 420 mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide); 421 } 422 attachNavBarBySide(int side)423 private void attachNavBarBySide(int side) { 424 switch (side) { 425 case SystemBarConfigs.TOP: 426 if (mTopSystemBarWindow != null) { 427 mWindowManager.addView(mTopSystemBarWindow, 428 mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP)); 429 } 430 break; 431 case SystemBarConfigs.BOTTOM: 432 if (mBottomSystemBarWindow != null && !mBottomNavBarVisible) { 433 mBottomNavBarVisible = true; 434 435 mWindowManager.addView(mBottomSystemBarWindow, 436 mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM)); 437 } 438 break; 439 case SystemBarConfigs.LEFT: 440 if (mLeftSystemBarWindow != null) { 441 mWindowManager.addView(mLeftSystemBarWindow, 442 mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT)); 443 } 444 break; 445 case SystemBarConfigs.RIGHT: 446 if (mRightSystemBarWindow != null) { 447 mWindowManager.addView(mRightSystemBarWindow, 448 mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT)); 449 } 450 break; 451 default: 452 return; 453 } 454 } 455 456 /** 457 * We register for soft keyboard visibility events such that we can hide the navigation bar 458 * giving more screen space to the IME. Note: this is optional and controlled by 459 * {@code com.android.internal.R.bool.config_hideNavBarForKeyboard}. 460 */ 461 @Override setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher)462 public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, 463 boolean showImeSwitcher) { 464 if (mContext.getDisplayId() != displayId) { 465 return; 466 } 467 468 boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; 469 470 updateKeyboardVisibility(isKeyboardVisible); 471 } 472 updateKeyboardVisibility(boolean isKeyboardVisible)473 private void updateKeyboardVisibility(boolean isKeyboardVisible) { 474 if (mHideTopBarForKeyboard) { 475 mCarSystemBarController.setTopWindowVisibility( 476 isKeyboardVisible ? View.GONE : View.VISIBLE); 477 } 478 479 if (mHideBottomBarForKeyboard) { 480 mCarSystemBarController.setBottomWindowVisibility( 481 isKeyboardVisible ? View.GONE : View.VISIBLE); 482 } 483 484 if (mHideLeftBarForKeyboard) { 485 mCarSystemBarController.setLeftWindowVisibility( 486 isKeyboardVisible ? View.GONE : View.VISIBLE); 487 } 488 if (mHideRightBarForKeyboard) { 489 mCarSystemBarController.setRightWindowVisibility( 490 isKeyboardVisible ? View.GONE : View.VISIBLE); 491 } 492 } 493 494 @Override onSystemBarAttributesChanged( int displayId, @WindowInsetsController.Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @WindowInsetsController.Behavior int behavior, @InsetsType int requestedVisibleTypes, String packageName, LetterboxDetails[] letterboxDetails)495 public void onSystemBarAttributesChanged( 496 int displayId, 497 @WindowInsetsController.Appearance int appearance, 498 AppearanceRegion[] appearanceRegions, 499 boolean navbarColorManagedByIme, 500 @WindowInsetsController.Behavior int behavior, 501 @InsetsType int requestedVisibleTypes, 502 String packageName, 503 LetterboxDetails[] letterboxDetails) { 504 if (displayId != mDisplayId) { 505 return; 506 } 507 boolean barModeChanged = updateStatusBarMode( 508 mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 509 int numStacks = appearanceRegions.length; 510 boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks; 511 for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) { 512 stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]); 513 } 514 if (stackAppearancesChanged || barModeChanged) { 515 mAppearanceRegions = appearanceRegions; 516 updateStatusBarAppearance(); 517 } 518 mCarSystemBarController.refreshSystemBar(); 519 } 520 521 @Override disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2, boolean animate)522 public void disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2, 523 boolean animate) { 524 if (displayId != mDisplayId) { 525 return; 526 } 527 mCarSystemBarController.setSystemBarStates(state1, state2); 528 } 529 updateStatusBarAppearance()530 private void updateStatusBarAppearance() { 531 int numStacks = mAppearanceRegions.length; 532 final ArrayList<Rect> lightBarBounds = new ArrayList<>(); 533 534 for (int i = 0; i < numStacks; i++) { 535 final AppearanceRegion ar = mAppearanceRegions[i]; 536 if (isLight(ar.getAppearance())) { 537 lightBarBounds.add(ar.getBounds()); 538 } 539 } 540 541 // If all stacks are light, all icons become dark. 542 if (lightBarBounds.size() == numStacks) { 543 mStatusBarIconController.setIconsDarkArea(null); 544 mStatusBarIconController.getTransitionsController().setIconsDark( 545 /* dark= */ true, /* animate= */ false); 546 } else if (lightBarBounds.isEmpty()) { 547 // If no one is light, all icons become white. 548 mStatusBarIconController.getTransitionsController().setIconsDark( 549 /* dark= */ false, /* animate= */ false); 550 } else { 551 // Not the same for every stack, update icons in area only. 552 mStatusBarIconController.setIconsDarkArea(lightBarBounds); 553 mStatusBarIconController.getTransitionsController().setIconsDark( 554 /* dark= */ true, /* animate= */ false); 555 } 556 } 557 isLight(int appearance)558 private static boolean isLight(int appearance) { 559 return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0; 560 } 561 562 @Override showTransient(int displayId, int types)563 public void showTransient(int displayId, int types) { 564 if (displayId != mDisplayId) { 565 return; 566 } 567 if ((types & WindowInsets.Type.statusBars()) != 0) { 568 if (!mStatusBarTransientShown) { 569 mStatusBarTransientShown = true; 570 handleTransientChanged(); 571 } 572 } 573 if ((types & WindowInsets.Type.navigationBars()) != 0) { 574 if (!mNavBarTransientShown) { 575 mNavBarTransientShown = true; 576 handleTransientChanged(); 577 } 578 } 579 } 580 581 @Override abortTransient(int displayId, int types)582 public void abortTransient(int displayId, int types) { 583 if (displayId != mDisplayId) { 584 return; 585 } 586 if ((types & (WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars())) == 0) { 587 return; 588 } 589 clearTransient(); 590 } 591 clearTransient()592 private void clearTransient() { 593 if (mStatusBarTransientShown) { 594 mStatusBarTransientShown = false; 595 handleTransientChanged(); 596 } 597 if (mNavBarTransientShown) { 598 mNavBarTransientShown = false; 599 handleTransientChanged(); 600 } 601 } 602 603 @VisibleForTesting isStatusBarTransientShown()604 boolean isStatusBarTransientShown() { 605 return mStatusBarTransientShown; 606 } 607 608 @VisibleForTesting isNavBarTransientShown()609 boolean isNavBarTransientShown() { 610 return mNavBarTransientShown; 611 } 612 613 @VisibleForTesting setSignalPolicy(StatusBarSignalPolicy signalPolicy)614 void setSignalPolicy(StatusBarSignalPolicy signalPolicy) { 615 mSignalPolicy = signalPolicy; 616 } 617 618 @Override dump(PrintWriter pw, String[] args)619 public void dump(PrintWriter pw, String[] args) { 620 pw.print(" mTaskStackListener="); 621 pw.println(mButtonSelectionStateListener); 622 pw.print(" mBottomSystemBarView="); 623 pw.println(mBottomSystemBarView); 624 } 625 handleTransientChanged()626 private void handleTransientChanged() { 627 updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 628 updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); 629 } 630 631 // Returns true if the status bar mode has changed. updateStatusBarMode(int barMode)632 private boolean updateStatusBarMode(int barMode) { 633 if (mStatusBarMode != barMode) { 634 mStatusBarMode = barMode; 635 mAutoHideController.touchAutoHide(); 636 return true; 637 } 638 return false; 639 } 640 641 // Returns true if the nav bar mode has changed. updateNavBarMode(int barMode)642 private boolean updateNavBarMode(int barMode) { 643 if (mSystemBarMode != barMode) { 644 mSystemBarMode = barMode; 645 mAutoHideController.touchAutoHide(); 646 return true; 647 } 648 return false; 649 } 650 651 @Override onConfigChanged(Configuration newConfig)652 public void onConfigChanged(Configuration newConfig) { 653 boolean isConfigNightMode = newConfig.isNightModeActive(); 654 // Only refresh UI on Night mode changes 655 if (isConfigNightMode != mIsUiModeNight) { 656 mIsUiModeNight = isConfigNightMode; 657 mUiModeManager.setNightModeActivated(mIsUiModeNight); 658 659 // cache the current state 660 // The focused view will be destroyed during re-layout, causing the framework to adjust 661 // the focus unexpectedly. To avoid that, move focus to a view that won't be 662 // destroyed during re-layout and has no focus highlight (the FocusParkingView), then 663 // move focus back to the previously focused view after re-layout. 664 mCarSystemBarController.cacheAndHideFocus(); 665 String selectedQuickControlsClsName = null; 666 View profilePickerView = null; 667 boolean isProfilePickerOpen = false; 668 if (mTopSystemBarView != null) { 669 profilePickerView = mTopSystemBarView.findViewById( 670 R.id.user_name); 671 } 672 if (profilePickerView != null) isProfilePickerOpen = profilePickerView.isSelected(); 673 if (isProfilePickerOpen) { 674 profilePickerView.callOnClick(); 675 } else { 676 selectedQuickControlsClsName = 677 mCarSystemBarController.getSelectedQuickControlsClassName(); 678 mCarSystemBarController.callQuickControlsOnClickFromClassName( 679 selectedQuickControlsClsName); 680 } 681 682 mCarSystemBarController.resetCache(); 683 restartNavBars(); 684 685 // retrieve the previous state 686 if (isProfilePickerOpen) { 687 if (mTopSystemBarView != null) { 688 profilePickerView = mTopSystemBarView.findViewById( 689 R.id.user_name); 690 } 691 if (profilePickerView != null) profilePickerView.callOnClick(); 692 } else { 693 mCarSystemBarController.callQuickControlsOnClickFromClassName( 694 selectedQuickControlsClsName); 695 } 696 mCarSystemBarController.restoreFocus(); 697 } 698 } 699 700 @VisibleForTesting setUiModeManager(UiModeManager uiModeManager)701 void setUiModeManager(UiModeManager uiModeManager) { 702 mUiModeManager = uiModeManager; 703 } 704 705 @Override onKeyboardVisibilityChanged(boolean show)706 public void onKeyboardVisibilityChanged(boolean show) { 707 updateKeyboardVisibility(show); 708 } 709 } 710