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.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 20 21 import static com.android.systemui.car.systembar.CarSystemBar.DEBUG; 22 23 import android.annotation.IntDef; 24 import android.content.res.Resources; 25 import android.graphics.PixelFormat; 26 import android.os.Binder; 27 import android.util.ArrayMap; 28 import android.util.ArraySet; 29 import android.util.Log; 30 import android.view.Gravity; 31 import android.view.InsetsFrameProvider; 32 import android.view.ViewGroup; 33 import android.view.WindowInsets; 34 import android.view.WindowManager; 35 36 import com.android.car.dockutil.Flags; 37 import com.android.internal.annotations.VisibleForTesting; 38 import com.android.systemui.R; 39 import com.android.systemui.car.notification.BottomNotificationPanelViewMediator; 40 import com.android.systemui.car.notification.TopNotificationPanelViewMediator; 41 import com.android.systemui.dagger.SysUISingleton; 42 import com.android.systemui.dagger.qualifiers.Main; 43 44 import java.lang.annotation.ElementType; 45 import java.lang.annotation.Target; 46 import java.util.ArrayList; 47 import java.util.Arrays; 48 import java.util.Comparator; 49 import java.util.List; 50 import java.util.Map; 51 import java.util.Set; 52 53 import javax.inject.Inject; 54 55 /** 56 * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the 57 * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration. 58 */ 59 @SysUISingleton 60 public class SystemBarConfigs { 61 62 private static final String TAG = SystemBarConfigs.class.getSimpleName(); 63 // The z-order from which system bars will start to appear on top of HUN's. 64 private static final int HUN_ZORDER = 10; 65 66 @IntDef(value = {TOP, BOTTOM, LEFT, RIGHT}) 67 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 68 private @interface SystemBarSide { 69 } 70 71 public static final int TOP = 0; 72 public static final int BOTTOM = 1; 73 public static final int LEFT = 2; 74 public static final int RIGHT = 3; 75 76 private static final Binder INSETS_OWNER = new Binder(); 77 78 /* 79 NOTE: The elements' order in the map below must be preserved as-is since the correct 80 corresponding values are obtained by the index. 81 */ 82 public static final InsetsFrameProvider[] BAR_PROVIDER_MAP = { 83 new InsetsFrameProvider( 84 INSETS_OWNER, 0 /* index */, WindowInsets.Type.statusBars()), 85 new InsetsFrameProvider( 86 INSETS_OWNER, 0 /* index */, WindowInsets.Type.navigationBars()), 87 new InsetsFrameProvider( 88 INSETS_OWNER, 1 /* index */, WindowInsets.Type.statusBars()), 89 new InsetsFrameProvider( 90 INSETS_OWNER, 1 /* index */, WindowInsets.Type.navigationBars()), 91 }; 92 93 private static final Map<@SystemBarSide Integer, Integer> BAR_GRAVITY_MAP = new ArrayMap<>(); 94 private static final Map<@SystemBarSide Integer, String> BAR_TITLE_MAP = new ArrayMap<>(); 95 private static final Map<@SystemBarSide Integer, InsetsFrameProvider> BAR_GESTURE_MAP = 96 new ArrayMap<>(); 97 98 private final Resources mResources; 99 private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap = 100 new ArrayMap<>(); 101 private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>(); 102 103 private boolean mTopNavBarEnabled; 104 private boolean mBottomNavBarEnabled; 105 private boolean mLeftNavBarEnabled; 106 private boolean mRightNavBarEnabled; 107 private int mDisplayCompatToolbarState = 0; 108 109 @Inject SystemBarConfigs(@ain Resources resources)110 public SystemBarConfigs(@Main Resources resources) { 111 mResources = resources; 112 init(); 113 } 114 init()115 private void init() { 116 populateMaps(); 117 readConfigs(); 118 119 checkOnlyOneDisplayCompatIsEnabled(); 120 checkEnabledBarsHaveUniqueBarTypes(); 121 checkAllOverlappingBarsHaveDifferentZOrders(); 122 checkSystemBarEnabledForNotificationPanel(); 123 checkHideBottomBarForKeyboardConfigSync(); 124 125 setInsetPaddingsForOverlappingCorners(); 126 sortSystemBarSidesByZOrder(); 127 } 128 129 /** 130 * Invalidate cached resources and fetch from resources config file. 131 * TODO: b/260206944, Can remove this after we have a fix for overlaid resources not applied. 132 * <p> 133 * Since SystemBarConfig is a Scoped(Dagger Singleton Annotation), We will have stale values, of 134 * all the resources after the RRO is applied. 135 * Another way is to remove the Scope(Singleton), but the downside is that it will be re-created 136 * everytime. 137 * </p> 138 */ resetSystemBarConfigs()139 void resetSystemBarConfigs() { 140 init(); 141 } 142 getLayoutParamsBySide(@ystemBarSide int side)143 protected WindowManager.LayoutParams getLayoutParamsBySide(@SystemBarSide int side) { 144 return mSystemBarConfigMap.get(side) != null 145 ? mSystemBarConfigMap 146 .get(side).getLayoutParams() 147 : null; 148 } 149 getEnabledStatusBySide(@ystemBarSide int side)150 protected boolean getEnabledStatusBySide(@SystemBarSide int side) { 151 switch (side) { 152 case TOP: 153 return mTopNavBarEnabled; 154 case BOTTOM: 155 return mBottomNavBarEnabled; 156 case LEFT: 157 return mLeftNavBarEnabled || isLeftDisplayCompatToolbarEnabled(); 158 case RIGHT: 159 return mRightNavBarEnabled || isRightDisplayCompatToolbarEnabled(); 160 default: 161 return false; 162 } 163 } 164 getHideForKeyboardBySide(@ystemBarSide int side)165 protected boolean getHideForKeyboardBySide(@SystemBarSide int side) { 166 return mSystemBarConfigMap.get(side) != null 167 && mSystemBarConfigMap.get(side).getHideForKeyboard(); 168 } 169 insetSystemBar(@ystemBarSide int side, CarSystemBarView view)170 protected void insetSystemBar(@SystemBarSide int side, CarSystemBarView view) { 171 if (mSystemBarConfigMap.get(side) == null) return; 172 173 int[] paddings = mSystemBarConfigMap.get(side).getPaddings(); 174 if (DEBUG) { 175 Log.d(TAG, "Set padding to side = " + side + ", to " + Arrays.toString(paddings)); 176 } 177 view.setPadding(paddings[LEFT], paddings[TOP], paddings[RIGHT], paddings[BOTTOM]); 178 } 179 getSystemBarSidesByZOrder()180 protected List<Integer> getSystemBarSidesByZOrder() { 181 return mSystemBarSidesByZOrder; 182 } 183 184 @VisibleForTesting updateInsetPaddings(@ystemBarSide int side, Map<@SystemBarSide Integer, Boolean> barVisibilities)185 void updateInsetPaddings(@SystemBarSide int side, 186 Map<@SystemBarSide Integer, Boolean> barVisibilities) { 187 SystemBarConfig currentConfig = mSystemBarConfigMap.get(side); 188 189 if (currentConfig == null) return; 190 191 int defaultLeftPadding = 0; 192 int defaultRightPadding = 0; 193 int defaultTopPadding = 0; 194 int defaultBottomPadding = 0; 195 196 switch (side) { 197 case LEFT: { 198 defaultLeftPadding = mResources 199 .getDimensionPixelSize(R.dimen.car_left_system_bar_left_padding); 200 defaultRightPadding = mResources 201 .getDimensionPixelSize(R.dimen.car_left_system_bar_right_padding); 202 defaultTopPadding = mResources 203 .getDimensionPixelSize(R.dimen.car_left_system_bar_top_padding); 204 defaultBottomPadding = mResources 205 .getDimensionPixelSize(R.dimen.car_left_system_bar_bottom_padding); 206 break; 207 } 208 case RIGHT: { 209 defaultLeftPadding = mResources 210 .getDimensionPixelSize(R.dimen.car_right_system_bar_left_padding); 211 defaultRightPadding = mResources 212 .getDimensionPixelSize(R.dimen.car_right_system_bar_right_padding); 213 defaultTopPadding = mResources 214 .getDimensionPixelSize(R.dimen.car_right_system_bar_top_padding); 215 defaultBottomPadding = mResources 216 .getDimensionPixelSize(R.dimen.car_right_system_bar_bottom_padding); 217 break; 218 } 219 case TOP: { 220 defaultLeftPadding = mResources 221 .getDimensionPixelSize(R.dimen.car_top_system_bar_left_padding); 222 defaultRightPadding = mResources 223 .getDimensionPixelSize(R.dimen.car_top_system_bar_right_padding); 224 defaultTopPadding = mResources 225 .getDimensionPixelSize(R.dimen.car_top_system_bar_top_padding); 226 defaultBottomPadding = mResources 227 .getDimensionPixelSize(R.dimen.car_top_system_bar_bottom_padding); 228 break; 229 } 230 case BOTTOM: { 231 defaultLeftPadding = mResources 232 .getDimensionPixelSize(R.dimen.car_bottom_system_bar_left_padding); 233 defaultRightPadding = mResources 234 .getDimensionPixelSize(R.dimen.car_bottom_system_bar_right_padding); 235 defaultTopPadding = mResources 236 .getDimensionPixelSize(R.dimen.car_bottom_system_bar_top_padding); 237 defaultBottomPadding = mResources 238 .getDimensionPixelSize(R.dimen.car_bottom_system_bar_bottom_padding); 239 break; 240 } 241 default: 242 } 243 244 currentConfig.setPaddingBySide(LEFT, defaultLeftPadding); 245 currentConfig.setPaddingBySide(RIGHT, defaultRightPadding); 246 currentConfig.setPaddingBySide(TOP, defaultTopPadding); 247 currentConfig.setPaddingBySide(BOTTOM, defaultBottomPadding); 248 249 if (isHorizontalBar(side)) { 250 if (mLeftNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get( 251 LEFT).getZOrder()) { 252 currentConfig.setPaddingBySide(LEFT, 253 barVisibilities.get(LEFT) 254 ? mSystemBarConfigMap.get(LEFT).getGirth() 255 : defaultLeftPadding); 256 } 257 if (mRightNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get( 258 RIGHT).getZOrder()) { 259 currentConfig.setPaddingBySide(RIGHT, 260 barVisibilities.get(RIGHT) 261 ? mSystemBarConfigMap.get(RIGHT).getGirth() 262 : defaultRightPadding); 263 } 264 } 265 if (isVerticalBar(side)) { 266 if (mTopNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get( 267 TOP).getZOrder()) { 268 currentConfig.setPaddingBySide(TOP, 269 barVisibilities.get(TOP) 270 ? mSystemBarConfigMap.get(TOP).getGirth() 271 : defaultTopPadding); 272 } 273 if (mBottomNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get( 274 BOTTOM).getZOrder()) { 275 currentConfig.setPaddingBySide(BOTTOM, 276 barVisibilities.get(BOTTOM) 277 ? mSystemBarConfigMap.get(BOTTOM).getGirth() 278 : defaultBottomPadding); 279 } 280 281 } 282 if (DEBUG) { 283 Log.d(TAG, "Update padding for side = " + side + " to " 284 + Arrays.toString(currentConfig.getPaddings())); 285 } 286 } 287 288 @VisibleForTesting getHunZOrder()289 static int getHunZOrder() { 290 return HUN_ZORDER; 291 } 292 populateMaps()293 private static void populateMaps() { 294 BAR_GRAVITY_MAP.put(TOP, Gravity.TOP); 295 BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM); 296 BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT); 297 BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT); 298 299 BAR_TITLE_MAP.put(TOP, "TopCarSystemBar"); 300 BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar"); 301 BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar"); 302 BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar"); 303 304 BAR_GESTURE_MAP.put(TOP, new InsetsFrameProvider( 305 INSETS_OWNER, 0 /* index */, WindowInsets.Type.mandatorySystemGestures())); 306 BAR_GESTURE_MAP.put(BOTTOM, new InsetsFrameProvider( 307 INSETS_OWNER, 1 /* index */, WindowInsets.Type.mandatorySystemGestures())); 308 BAR_GESTURE_MAP.put(LEFT, new InsetsFrameProvider( 309 INSETS_OWNER, 2 /* index */, WindowInsets.Type.mandatorySystemGestures())); 310 BAR_GESTURE_MAP.put(RIGHT, new InsetsFrameProvider( 311 INSETS_OWNER, 3 /* index */, WindowInsets.Type.mandatorySystemGestures())); 312 } 313 readConfigs()314 private void readConfigs() { 315 mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopSystemBar); 316 mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomSystemBar); 317 mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftSystemBar); 318 mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightSystemBar); 319 mDisplayCompatToolbarState = 320 mResources.getInteger(R.integer.config_showDisplayCompatToolbarOnSystemBar); 321 mSystemBarConfigMap.clear(); 322 323 if ((mLeftNavBarEnabled && isLeftDisplayCompatToolbarEnabled()) 324 || (mRightNavBarEnabled && isRightDisplayCompatToolbarEnabled())) { 325 throw new IllegalStateException( 326 "Navigation Bar and Display Compat toolbar can't be " 327 + "on the same side"); 328 } 329 330 if (mTopNavBarEnabled) { 331 SystemBarConfig topBarConfig = 332 new SystemBarConfigBuilder() 333 .setSide(TOP) 334 .setGirth(mResources.getDimensionPixelSize( 335 R.dimen.car_top_system_bar_height)) 336 .setBarType( 337 mResources.getInteger(R.integer.config_topSystemBarType)) 338 .setZOrder( 339 mResources.getInteger(R.integer.config_topSystemBarZOrder)) 340 .setHideForKeyboard(mResources.getBoolean( 341 R.bool.config_hideTopSystemBarForKeyboard)) 342 .build(); 343 mSystemBarConfigMap.put(TOP, topBarConfig); 344 } 345 346 if (mBottomNavBarEnabled) { 347 SystemBarConfig bottomBarConfig = 348 new SystemBarConfigBuilder() 349 .setSide(BOTTOM) 350 .setGirth(mResources.getDimensionPixelSize( 351 R.dimen.car_bottom_system_bar_height)) 352 .setBarType( 353 mResources.getInteger(R.integer.config_bottomSystemBarType)) 354 .setZOrder( 355 mResources.getInteger( 356 R.integer.config_bottomSystemBarZOrder)) 357 .setHideForKeyboard(mResources.getBoolean( 358 R.bool.config_hideBottomSystemBarForKeyboard)) 359 .build(); 360 mSystemBarConfigMap.put(BOTTOM, bottomBarConfig); 361 } 362 363 if (mLeftNavBarEnabled || isLeftDisplayCompatToolbarEnabled()) { 364 SystemBarConfig leftBarConfig = 365 new SystemBarConfigBuilder() 366 .setSide(LEFT) 367 .setGirth(mResources.getDimensionPixelSize( 368 R.dimen.car_left_system_bar_width)) 369 .setBarType( 370 mResources.getInteger(R.integer.config_leftSystemBarType)) 371 .setZOrder( 372 mResources.getInteger(R.integer.config_leftSystemBarZOrder)) 373 .setHideForKeyboard(mResources.getBoolean( 374 R.bool.config_hideLeftSystemBarForKeyboard)) 375 .build(); 376 mSystemBarConfigMap.put(LEFT, leftBarConfig); 377 } 378 379 if (mRightNavBarEnabled || isRightDisplayCompatToolbarEnabled()) { 380 SystemBarConfig rightBarConfig = 381 new SystemBarConfigBuilder() 382 .setSide(RIGHT) 383 .setGirth(mResources.getDimensionPixelSize( 384 R.dimen.car_right_system_bar_width)) 385 .setBarType( 386 mResources.getInteger(R.integer.config_rightSystemBarType)) 387 .setZOrder(mResources.getInteger( 388 R.integer.config_rightSystemBarZOrder)) 389 .setHideForKeyboard(mResources.getBoolean( 390 R.bool.config_hideRightSystemBarForKeyboard)) 391 .build(); 392 mSystemBarConfigMap.put(RIGHT, rightBarConfig); 393 } 394 } 395 checkOnlyOneDisplayCompatIsEnabled()396 private void checkOnlyOneDisplayCompatIsEnabled() throws IllegalStateException { 397 boolean useRemoteLaunchTaskView = 398 mResources.getBoolean(R.bool.config_useRemoteLaunchTaskView); 399 int displayCompatEnabled = 400 mResources.getInteger(R.integer.config_showDisplayCompatToolbarOnSystemBar); 401 if (useRemoteLaunchTaskView && displayCompatEnabled != 0) { 402 throw new IllegalStateException("config_useRemoteLaunchTaskView is enabled but " 403 + "config_showDisplayCompatToolbarOnSystemBar is non-zero"); 404 } 405 } 406 checkEnabledBarsHaveUniqueBarTypes()407 private void checkEnabledBarsHaveUniqueBarTypes() throws RuntimeException { 408 Set<Integer> barTypesUsed = new ArraySet<>(); 409 int enabledNavBarCount = mSystemBarConfigMap.size(); 410 411 for (SystemBarConfig systemBarConfig : mSystemBarConfigMap.values()) { 412 barTypesUsed.add(systemBarConfig.getBarType()); 413 } 414 415 // The number of bar types used cannot be fewer than that of enabled system bars. 416 if (barTypesUsed.size() < enabledNavBarCount) { 417 throw new RuntimeException("Each enabled system bar must have a unique bar type. Check " 418 + "the configuration in config.xml"); 419 } 420 } 421 checkAllOverlappingBarsHaveDifferentZOrders()422 private void checkAllOverlappingBarsHaveDifferentZOrders() { 423 checkOverlappingBarsHaveDifferentZOrders(TOP, LEFT); 424 checkOverlappingBarsHaveDifferentZOrders(TOP, RIGHT); 425 checkOverlappingBarsHaveDifferentZOrders(BOTTOM, LEFT); 426 checkOverlappingBarsHaveDifferentZOrders(BOTTOM, RIGHT); 427 } 428 checkSystemBarEnabledForNotificationPanel()429 private void checkSystemBarEnabledForNotificationPanel() throws RuntimeException { 430 String notificationPanelMediatorName = 431 mResources.getString(R.string.config_notificationPanelViewMediator); 432 if (notificationPanelMediatorName == null) { 433 return; 434 } 435 436 Class<?> notificationPanelMediatorUsed = null; 437 try { 438 notificationPanelMediatorUsed = Class.forName(notificationPanelMediatorName); 439 } catch (ClassNotFoundException e) { 440 e.printStackTrace(); 441 } 442 443 if (!mTopNavBarEnabled && TopNotificationPanelViewMediator.class.isAssignableFrom( 444 notificationPanelMediatorUsed)) { 445 throw new RuntimeException( 446 "Top System Bar must be enabled to use " + notificationPanelMediatorName); 447 } 448 449 if (!mBottomNavBarEnabled && BottomNotificationPanelViewMediator.class.isAssignableFrom( 450 notificationPanelMediatorUsed)) { 451 throw new RuntimeException("Bottom System Bar must be enabled to use " 452 + notificationPanelMediatorName); 453 } 454 } 455 checkHideBottomBarForKeyboardConfigSync()456 private void checkHideBottomBarForKeyboardConfigSync() throws RuntimeException { 457 if (mBottomNavBarEnabled) { 458 boolean actual = mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard); 459 boolean expected = mResources.getBoolean( 460 com.android.internal.R.bool.config_hideNavBarForKeyboard); 461 462 if (actual != expected) { 463 throw new RuntimeException("config_hideBottomSystemBarForKeyboard must not be " 464 + "overlaid directly and should always refer to" 465 + "config_hideNavBarForKeyboard. However, their values " 466 + "currently do not sync. Set config_hideBottomSystemBarForKeyguard to " 467 + "@*android:bool/config_hideNavBarForKeyboard. To change its " 468 + "value, overlay config_hideNavBarForKeyboard in " 469 + "framework/base/core/res/res."); 470 } 471 } 472 } 473 setInsetPaddingsForOverlappingCorners()474 private void setInsetPaddingsForOverlappingCorners() { 475 Map<@SystemBarSide Integer, Boolean> systemBarVisibilityOnInit = 476 getSystemBarsVisibilityOnInit(); 477 updateInsetPaddings(TOP, systemBarVisibilityOnInit); 478 updateInsetPaddings(BOTTOM, systemBarVisibilityOnInit); 479 updateInsetPaddings(LEFT, systemBarVisibilityOnInit); 480 updateInsetPaddings(RIGHT, systemBarVisibilityOnInit); 481 } 482 sortSystemBarSidesByZOrder()483 private void sortSystemBarSidesByZOrder() { 484 List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values()); 485 486 systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() { 487 @Override 488 public int compare(SystemBarConfig o1, SystemBarConfig o2) { 489 return o1.getZOrder() - o2.getZOrder(); 490 } 491 }); 492 493 mSystemBarSidesByZOrder.clear(); 494 systemBarsByZOrder.forEach(systemBarConfig -> { 495 mSystemBarSidesByZOrder.add(systemBarConfig.getSide()); 496 }); 497 } 498 499 // On init, system bars are visible as long as they are enabled. getSystemBarsVisibilityOnInit()500 private Map<@SystemBarSide Integer, Boolean> getSystemBarsVisibilityOnInit() { 501 ArrayMap<@SystemBarSide Integer, Boolean> visibilityMap = new ArrayMap<>(); 502 visibilityMap.put(TOP, mTopNavBarEnabled); 503 visibilityMap.put(BOTTOM, mBottomNavBarEnabled); 504 visibilityMap.put(LEFT, mLeftNavBarEnabled || isLeftDisplayCompatToolbarEnabled()); 505 visibilityMap.put(RIGHT, mRightNavBarEnabled || isRightDisplayCompatToolbarEnabled()); 506 return visibilityMap; 507 } 508 checkOverlappingBarsHaveDifferentZOrders(@ystemBarSide int horizontalSide, @SystemBarSide int verticalSide)509 private void checkOverlappingBarsHaveDifferentZOrders(@SystemBarSide int horizontalSide, 510 @SystemBarSide int verticalSide) { 511 512 if (isVerticalBar(horizontalSide) || isHorizontalBar(verticalSide)) { 513 Log.w(TAG, "configureBarPaddings: Returning immediately since the horizontal and " 514 + "vertical sides were not provided correctly."); 515 return; 516 } 517 518 SystemBarConfig horizontalBarConfig = mSystemBarConfigMap.get(horizontalSide); 519 SystemBarConfig verticalBarConfig = mSystemBarConfigMap.get(verticalSide); 520 521 if (verticalBarConfig != null && horizontalBarConfig != null) { 522 int horizontalBarZOrder = horizontalBarConfig.getZOrder(); 523 int verticalBarZOrder = verticalBarConfig.getZOrder(); 524 525 if (horizontalBarZOrder == verticalBarZOrder) { 526 throw new RuntimeException( 527 BAR_TITLE_MAP.get(horizontalSide) + " " + BAR_TITLE_MAP.get(verticalSide) 528 + " have the same Z-Order, and so their placing order cannot be " 529 + "determined. Determine which bar should be placed on top of the " 530 + "other bar and change the Z-order in config.xml accordingly." 531 ); 532 } 533 } 534 } 535 isHorizontalBar(@ystemBarSide int side)536 private static boolean isHorizontalBar(@SystemBarSide int side) { 537 return side == TOP || side == BOTTOM; 538 } 539 isVerticalBar(@ystemBarSide int side)540 private static boolean isVerticalBar(@SystemBarSide int side) { 541 return side == LEFT || side == RIGHT; 542 } isLeftDisplayCompatToolbarEnabled()543 boolean isLeftDisplayCompatToolbarEnabled() { 544 return mDisplayCompatToolbarState == 1; 545 } 546 isRightDisplayCompatToolbarEnabled()547 boolean isRightDisplayCompatToolbarEnabled() { 548 return mDisplayCompatToolbarState == 2; 549 } 550 551 private static final class SystemBarConfig { 552 private final int mSide; 553 private final int mBarType; 554 private final int mGirth; 555 private final int mZOrder; 556 private final boolean mHideForKeyboard; 557 558 private int[] mPaddings = new int[]{0, 0, 0, 0}; 559 SystemBarConfig(@ystemBarSide int side, int barType, int girth, int zOrder, boolean hideForKeyboard)560 private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder, 561 boolean hideForKeyboard) { 562 mSide = side; 563 mBarType = barType; 564 mGirth = girth; 565 mZOrder = zOrder; 566 mHideForKeyboard = hideForKeyboard; 567 } 568 getSide()569 private int getSide() { 570 return mSide; 571 } 572 getBarType()573 private int getBarType() { 574 return mBarType; 575 } 576 getGirth()577 private int getGirth() { 578 return mGirth; 579 } 580 getZOrder()581 private int getZOrder() { 582 return mZOrder; 583 } 584 getHideForKeyboard()585 private boolean getHideForKeyboard() { 586 return mHideForKeyboard; 587 } 588 getPaddings()589 private int[] getPaddings() { 590 return mPaddings; 591 } 592 getLayoutParams()593 private WindowManager.LayoutParams getLayoutParams() { 594 WindowManager.LayoutParams lp = new WindowManager.LayoutParams( 595 isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth, 596 isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT, 597 mapZOrderToBarType(mZOrder), 598 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 599 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 600 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH 601 | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, 602 PixelFormat.TRANSLUCENT); 603 lp.setTitle(BAR_TITLE_MAP.get(mSide)); 604 lp.providedInsets = new InsetsFrameProvider[] { 605 BAR_PROVIDER_MAP[mBarType], 606 BAR_GESTURE_MAP.get(mSide) 607 }; 608 lp.setFitInsetsTypes(0); 609 lp.windowAnimations = 0; 610 lp.gravity = BAR_GRAVITY_MAP.get(mSide); 611 lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; 612 if (Flags.dockFeature()) { 613 lp.privateFlags = lp.privateFlags 614 | WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; 615 } 616 return lp; 617 } 618 mapZOrderToBarType(int zOrder)619 private int mapZOrderToBarType(int zOrder) { 620 return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL 621 : WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; 622 } 623 setPaddingBySide(@ystemBarSide int side, int padding)624 private void setPaddingBySide(@SystemBarSide int side, int padding) { 625 mPaddings[side] = padding; 626 } 627 } 628 629 private static final class SystemBarConfigBuilder { 630 private int mSide; 631 private int mBarType; 632 private int mGirth; 633 private int mZOrder; 634 private boolean mHideForKeyboard; 635 setSide(@ystemBarSide int side)636 private SystemBarConfigBuilder setSide(@SystemBarSide int side) { 637 mSide = side; 638 return this; 639 } 640 setBarType(int type)641 private SystemBarConfigBuilder setBarType(int type) { 642 mBarType = type; 643 return this; 644 } 645 setGirth(int girth)646 private SystemBarConfigBuilder setGirth(int girth) { 647 mGirth = girth; 648 return this; 649 } 650 setZOrder(int zOrder)651 private SystemBarConfigBuilder setZOrder(int zOrder) { 652 mZOrder = zOrder; 653 return this; 654 } 655 setHideForKeyboard(boolean hide)656 private SystemBarConfigBuilder setHideForKeyboard(boolean hide) { 657 mHideForKeyboard = hide; 658 return this; 659 } 660 build()661 private SystemBarConfig build() { 662 return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard); 663 } 664 } 665 } 666