diff options
author | kwaky <kwaky@google.com> | 2020-07-17 14:38:07 -0700 |
---|---|---|
committer | kwaky <kwaky@google.com> | 2020-07-29 09:18:31 -0700 |
commit | 4030db5f0d3b0260b7e2dea6cdda7712bafa53c7 (patch) | |
tree | 84ca773b7d601acf7c0172b6f72c70f9ae0d264c /packages/CarSystemUI/src | |
parent | 8d411d947a7dddf42c07a1c56d9ded0577ad53a3 (diff) |
Allow SystemBar configuration via XML.
Bug: 160028073
Bug: 161825538
Test: Unit Tests + Manual -- CarNavigationBar reads configs from
SystemBarConfigs and applies them as intended. It throws an error when
the config validation fails.
Change-Id: If1575bdc2549058600fb80fa0d6c340fd3e1dbc5
Diffstat (limited to 'packages/CarSystemUI/src')
4 files changed, 426 insertions, 119 deletions
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java index 35b2080dddf9..9584850fde7c 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java @@ -16,12 +16,8 @@ package com.android.systemui.car.navigationbar; -import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; -import static android.view.InsetsState.ITYPE_TOP_GESTURES; import static android.view.InsetsState.containsType; import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; @@ -30,13 +26,11 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARE import android.content.Context; import android.content.res.Resources; -import android.graphics.PixelFormat; import android.inputmethodservice.InputMethodService; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.view.Display; -import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowInsetsController; @@ -47,7 +41,6 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.RegisterStatusBarResult; import com.android.internal.view.AppearanceRegion; -import com.android.systemui.R; import com.android.systemui.SystemUI; import com.android.systemui.car.CarDeviceProvisionedController; import com.android.systemui.car.CarDeviceProvisionedListener; @@ -76,7 +69,6 @@ import dagger.Lazy; /** Navigation bars customized for the automotive use case. */ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks { - private final Resources mResources; private final CarNavigationBarController mCarNavigationBarController; private final SysuiDarkIconDispatcher mStatusBarIconController; @@ -93,6 +85,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks private final Lazy<StatusBarIconController> mIconControllerLazy; private final int mDisplayId; + private final SystemBarConfigs mSystemBarConfigs; private StatusBarSignalPolicy mSignalPolicy; private ActivityManagerWrapper mActivityManagerWrapper; @@ -141,7 +134,8 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks IStatusBarService barService, Lazy<KeyguardStateController> keyguardStateControllerLazy, Lazy<PhoneStatusBarPolicy> iconPolicyLazy, - Lazy<StatusBarIconController> iconControllerLazy + Lazy<StatusBarIconController> iconControllerLazy, + SystemBarConfigs systemBarConfigs ) { super(context); mResources = resources; @@ -158,6 +152,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks mKeyguardStateControllerLazy = keyguardStateControllerLazy; mIconPolicyLazy = iconPolicyLazy; mIconControllerLazy = iconControllerLazy; + mSystemBarConfigs = systemBarConfigs; mDisplayId = context.getDisplayId(); } @@ -344,103 +339,63 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks private void buildNavBarContent() { mTopNavigationBarView = mCarNavigationBarController.getTopBar(isDeviceSetupForUser()); if (mTopNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopNavigationBarView); mTopNavigationBarWindow.addView(mTopNavigationBarView); } mBottomNavigationBarView = mCarNavigationBarController.getBottomBar(isDeviceSetupForUser()); if (mBottomNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomNavigationBarView); mBottomNavigationBarWindow.addView(mBottomNavigationBarView); } mLeftNavigationBarView = mCarNavigationBarController.getLeftBar(isDeviceSetupForUser()); if (mLeftNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftNavigationBarView); mLeftNavigationBarWindow.addView(mLeftNavigationBarView); } mRightNavigationBarView = mCarNavigationBarController.getRightBar(isDeviceSetupForUser()); if (mRightNavigationBarView != null) { + mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightNavigationBarView); mRightNavigationBarWindow.addView(mRightNavigationBarView); } } private void attachNavBarWindows() { - if (mTopNavigationBarWindow != null) { - int height = mResources.getDimensionPixelSize( - com.android.internal.R.dimen.status_bar_height); - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - height, - WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.setTitle("TopCarNavigationBar"); - lp.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES}; - lp.setFitInsetsTypes(0); - lp.windowAnimations = 0; - lp.gravity = Gravity.TOP; - mWindowManager.addView(mTopNavigationBarWindow, lp); - } - - if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { - mBottomNavBarVisible = true; - int height = mResources.getDimensionPixelSize( - com.android.internal.R.dimen.navigation_bar_height); - - WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - height, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - lp.setTitle("BottomCarNavigationBar"); - lp.providesInsetsTypes = new int[]{ITYPE_NAVIGATION_BAR, ITYPE_BOTTOM_GESTURES}; - lp.windowAnimations = 0; - lp.gravity = Gravity.BOTTOM; - mWindowManager.addView(mBottomNavigationBarWindow, lp); - } - - if (mLeftNavigationBarWindow != null) { - int width = mResources.getDimensionPixelSize( - R.dimen.car_left_navigation_bar_width); - WindowManager.LayoutParams leftlp = new WindowManager.LayoutParams( - width, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - leftlp.setTitle("LeftCarNavigationBar"); - leftlp.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR}; - leftlp.setFitInsetsTypes(0); - leftlp.windowAnimations = 0; - leftlp.gravity = Gravity.LEFT; - mWindowManager.addView(mLeftNavigationBarWindow, leftlp); - } + mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide); + } - if (mRightNavigationBarWindow != null) { - int width = mResources.getDimensionPixelSize( - R.dimen.car_right_navigation_bar_width); - WindowManager.LayoutParams rightlp = new WindowManager.LayoutParams( - width, ViewGroup.LayoutParams.MATCH_PARENT, - WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE - | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH - | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, - PixelFormat.TRANSLUCENT); - rightlp.setTitle("RightCarNavigationBar"); - rightlp.providesInsetsTypes = new int[]{ITYPE_EXTRA_NAVIGATION_BAR}; - rightlp.setFitInsetsTypes(0); - rightlp.windowAnimations = 0; - rightlp.gravity = Gravity.RIGHT; - mWindowManager.addView(mRightNavigationBarWindow, rightlp); + private void attachNavBarBySide(int side) { + switch(side) { + case SystemBarConfigs.TOP: + if (mTopNavigationBarWindow != null) { + mWindowManager.addView(mTopNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP)); + } + break; + case SystemBarConfigs.BOTTOM: + if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) { + mBottomNavBarVisible = true; + + mWindowManager.addView(mBottomNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM)); + } + break; + case SystemBarConfigs.LEFT: + if (mLeftNavigationBarWindow != null) { + mWindowManager.addView(mLeftNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT)); + } + break; + case SystemBarConfigs.RIGHT: + if (mRightNavigationBarWindow != null) { + mWindowManager.addView(mRightNavigationBarWindow, + mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT)); + } + break; + default: + return; } } diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java index ca780ae645c9..fe26040c5eae 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java @@ -22,7 +22,6 @@ import android.view.ViewGroup; import androidx.annotation.Nullable; -import com.android.systemui.R; import com.android.systemui.car.hvac.HvacController; import javax.inject.Inject; @@ -61,7 +60,8 @@ public class CarNavigationBarController { NavigationBarViewFactory navigationBarViewFactory, ButtonSelectionStateController buttonSelectionStateController, Lazy<HvacController> hvacControllerLazy, - ButtonRoleHolderController buttonRoleHolderController) { + ButtonRoleHolderController buttonRoleHolderController, + SystemBarConfigs systemBarConfigs) { mContext = context; mNavigationBarViewFactory = navigationBarViewFactory; mButtonSelectionStateController = buttonSelectionStateController; @@ -69,10 +69,10 @@ public class CarNavigationBarController { mButtonRoleHolderController = buttonRoleHolderController; // Read configuration. - mShowTop = mContext.getResources().getBoolean(R.bool.config_enableTopNavigationBar); - mShowBottom = mContext.getResources().getBoolean(R.bool.config_enableBottomNavigationBar); - mShowLeft = mContext.getResources().getBoolean(R.bool.config_enableLeftNavigationBar); - mShowRight = mContext.getResources().getBoolean(R.bool.config_enableRightNavigationBar); + mShowTop = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.TOP); + mShowBottom = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.BOTTOM); + mShowLeft = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.LEFT); + mShowRight = systemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.RIGHT); } /** diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java index 0ced4021ce38..ab401bbf06bb 100644 --- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarView.java @@ -16,14 +16,10 @@ package com.android.systemui.car.navigationbar; -import static android.view.WindowInsets.Type.systemBars; - import android.content.Context; -import android.graphics.Insets; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; -import android.view.WindowInsets; import android.widget.LinearLayout; import com.android.systemui.Dependency; @@ -80,30 +76,6 @@ public class CarNavigationBarView extends LinearLayout { setFocusable(false); } - @Override - public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) { - applyMargins(windowInsets.getInsets(systemBars())); - return windowInsets; - } - - private void applyMargins(Insets insets) { - final int count = getChildCount(); - for (int i = 0; i < count; i++) { - View child = getChildAt(i); - if (child.getLayoutParams() instanceof LayoutParams) { - LayoutParams lp = (LayoutParams) child.getLayoutParams(); - if (lp.rightMargin != insets.right || lp.leftMargin != insets.left - || lp.topMargin != insets.top || lp.bottomMargin != insets.bottom) { - lp.rightMargin = insets.right; - lp.leftMargin = insets.left; - lp.topMargin = insets.top; - lp.bottomMargin = insets.bottom; - child.requestLayout(); - } - } - } - } - // Used to forward touch events even if the touch was initiated from a child component @Override public boolean onInterceptTouchEvent(MotionEvent ev) { diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java new file mode 100644 index 000000000000..3527bf93682f --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.car.navigationbar; + +import android.annotation.IntDef; +import android.content.res.Resources; +import android.graphics.PixelFormat; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Log; +import android.view.Gravity; +import android.view.InsetsState; +import android.view.ViewGroup; +import android.view.WindowManager; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.R; +import com.android.systemui.dagger.qualifiers.Main; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the + * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration. + */ +@Singleton +public class SystemBarConfigs { + + private static final String TAG = SystemBarConfigs.class.getSimpleName(); + // The z-order from which system bars will start to appear on top of HUN's. + private static final int HUN_ZORDER = 10; + + @IntDef(value = {TOP, BOTTOM, LEFT, RIGHT}) + @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) + private @interface SystemBarSide { + } + + public static final int TOP = 0; + public static final int BOTTOM = 1; + public static final int LEFT = 2; + public static final int RIGHT = 3; + + /* + NOTE: The elements' order in the map below must be preserved as-is since the correct + corresponding values are obtained by the index. + */ + private static final int[] BAR_TYPE_MAP = { + InsetsState.ITYPE_STATUS_BAR, + InsetsState.ITYPE_NAVIGATION_BAR, + InsetsState.ITYPE_CLIMATE_BAR, + InsetsState.ITYPE_EXTRA_NAVIGATION_BAR + }; + + private static final Map<@SystemBarSide Integer, Integer> BAR_GRAVITY_MAP = new ArrayMap<>(); + private static final Map<@SystemBarSide Integer, String> BAR_TITLE_MAP = new ArrayMap<>(); + private static final Map<@SystemBarSide Integer, Integer> BAR_GESTURE_MAP = new ArrayMap<>(); + + private final Resources mResources; + private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap = + new ArrayMap<>(); + private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>(); + + private boolean mTopNavBarEnabled; + private boolean mBottomNavBarEnabled; + private boolean mLeftNavBarEnabled; + private boolean mRightNavBarEnabled; + + @Inject + public SystemBarConfigs(@Main Resources resources) { + mResources = resources; + + populateMaps(); + readConfigs(); + checkEnabledBarsHaveUniqueBarTypes(); + setInsetPaddingsForOverlappingCorners(); + sortSystemBarSidesByZOrder(); + } + + protected WindowManager.LayoutParams getLayoutParamsBySide(@SystemBarSide int side) { + return mSystemBarConfigMap.get(side) != null + ? mSystemBarConfigMap.get(side).getLayoutParams() : null; + } + + protected boolean getEnabledStatusBySide(@SystemBarSide int side) { + switch (side) { + case TOP: + return mTopNavBarEnabled; + case BOTTOM: + return mBottomNavBarEnabled; + case LEFT: + return mLeftNavBarEnabled; + case RIGHT: + return mRightNavBarEnabled; + default: + return false; + } + } + + protected void insetSystemBar(@SystemBarSide int side, CarNavigationBarView view) { + int[] paddings = mSystemBarConfigMap.get(side).getPaddings(); + view.setPadding(paddings[2], paddings[0], paddings[3], paddings[1]); + } + + protected List<Integer> getSystemBarSidesByZOrder() { + return mSystemBarSidesByZOrder; + } + + @VisibleForTesting + protected static int getHunZOrder() { + return HUN_ZORDER; + } + + private static void populateMaps() { + BAR_GRAVITY_MAP.put(TOP, Gravity.TOP); + BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM); + BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT); + BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT); + + BAR_TITLE_MAP.put(TOP, "TopCarSystemBar"); + BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar"); + BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar"); + BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar"); + + BAR_GESTURE_MAP.put(TOP, InsetsState.ITYPE_TOP_GESTURES); + BAR_GESTURE_MAP.put(BOTTOM, InsetsState.ITYPE_BOTTOM_GESTURES); + BAR_GESTURE_MAP.put(LEFT, InsetsState.ITYPE_LEFT_GESTURES); + BAR_GESTURE_MAP.put(RIGHT, InsetsState.ITYPE_RIGHT_GESTURES); + } + + private void readConfigs() { + mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopNavigationBar); + mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomNavigationBar); + mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftNavigationBar); + mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightNavigationBar); + + if (mTopNavBarEnabled) { + SystemBarConfig topBarConfig = + new SystemBarConfigBuilder() + .setSide(TOP) + .setGirth(mResources.getDimensionPixelSize( + com.android.internal.R.dimen.status_bar_height)) + .setBarType(mResources.getInteger(R.integer.config_topSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder)) + .build(); + mSystemBarConfigMap.put(TOP, topBarConfig); + } + + if (mBottomNavBarEnabled) { + SystemBarConfig bottomBarConfig = + new SystemBarConfigBuilder() + .setSide(BOTTOM) + .setGirth(mResources.getDimensionPixelSize( + com.android.internal.R.dimen.navigation_bar_height)) + .setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType)) + .setZOrder( + mResources.getInteger(R.integer.config_bottomSystemBarZOrder)) + .build(); + mSystemBarConfigMap.put(BOTTOM, bottomBarConfig); + } + + if (mLeftNavBarEnabled) { + SystemBarConfig leftBarConfig = + new SystemBarConfigBuilder() + .setSide(LEFT) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_left_navigation_bar_width)) + .setBarType(mResources.getInteger(R.integer.config_leftSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder)) + .build(); + mSystemBarConfigMap.put(LEFT, leftBarConfig); + } + + if (mRightNavBarEnabled) { + SystemBarConfig rightBarConfig = + new SystemBarConfigBuilder() + .setSide(RIGHT) + .setGirth(mResources.getDimensionPixelSize( + R.dimen.car_right_navigation_bar_width)) + .setBarType(mResources.getInteger(R.integer.config_rightSystemBarType)) + .setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder)) + .build(); + mSystemBarConfigMap.put(RIGHT, rightBarConfig); + } + } + + private void checkEnabledBarsHaveUniqueBarTypes() throws RuntimeException { + Set<Integer> barTypesUsed = new ArraySet<>(); + int enabledNavBarCount = mSystemBarConfigMap.size(); + + for (SystemBarConfig systemBarConfig : mSystemBarConfigMap.values()) { + barTypesUsed.add(systemBarConfig.getBarType()); + } + + // The number of bar types used cannot be fewer than that of enabled system bars. + if (barTypesUsed.size() < enabledNavBarCount) { + throw new RuntimeException("Each enabled system bar must have a unique bar type. Check " + + "the configuration in config.xml"); + } + } + + private void setInsetPaddingsForOverlappingCorners() { + setInsetPaddingForOverlappingCorner(TOP, LEFT); + setInsetPaddingForOverlappingCorner(TOP, RIGHT); + setInsetPaddingForOverlappingCorner(BOTTOM, LEFT); + setInsetPaddingForOverlappingCorner(BOTTOM, RIGHT); + } + + private void setInsetPaddingForOverlappingCorner(@SystemBarSide int horizontalSide, + @SystemBarSide int verticalSide) { + + if (isVerticalBar(horizontalSide) || isHorizontalBar(verticalSide)) { + Log.w(TAG, "configureBarPaddings: Returning immediately since the horizontal and " + + "vertical sides were not provided correctly."); + return; + } + + SystemBarConfig horizontalBarConfig = mSystemBarConfigMap.get(horizontalSide); + SystemBarConfig verticalBarConfig = mSystemBarConfigMap.get(verticalSide); + + if (verticalBarConfig != null && horizontalBarConfig != null) { + int horizontalBarZOrder = horizontalBarConfig.getZOrder(); + int horizontalBarGirth = horizontalBarConfig.getGirth(); + int verticalBarZOrder = verticalBarConfig.getZOrder(); + int verticalBarGirth = verticalBarConfig.getGirth(); + + if (horizontalBarZOrder > verticalBarZOrder) { + verticalBarConfig.setPaddingBySide(horizontalSide, horizontalBarGirth); + } else if (horizontalBarZOrder < verticalBarZOrder) { + horizontalBarConfig.setPaddingBySide(verticalSide, verticalBarGirth); + } else { + throw new RuntimeException( + BAR_TITLE_MAP.get(horizontalSide) + " " + BAR_TITLE_MAP.get(verticalSide) + + " have the same Z-Order, and so their placing order cannot be " + + "determined. Determine which bar should be placed on top of the " + + "other bar and change the Z-order in config.xml accordingly." + ); + } + } + } + + private void sortSystemBarSidesByZOrder() { + List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values()); + + systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() { + @Override + public int compare(SystemBarConfig o1, SystemBarConfig o2) { + return o1.getZOrder() - o2.getZOrder(); + } + }); + + systemBarsByZOrder.forEach(systemBarConfig -> { + mSystemBarSidesByZOrder.add(systemBarConfig.getSide()); + }); + } + + private static boolean isHorizontalBar(@SystemBarSide int side) { + return side == TOP || side == BOTTOM; + } + + private static boolean isVerticalBar(@SystemBarSide int side) { + return side == LEFT || side == RIGHT; + } + + private static final class SystemBarConfig { + private final int mSide; + private final int mBarType; + private final int mGirth; + private final int mZOrder; + + private int[] mPaddings = new int[]{0, 0, 0, 0}; + + private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder) { + mSide = side; + mBarType = barType; + mGirth = girth; + mZOrder = zOrder; + } + + private int getSide() { + return mSide; + } + + private int getBarType() { + return mBarType; + } + + private int getGirth() { + return mGirth; + } + + private int getZOrder() { + return mZOrder; + } + + private int[] getPaddings() { + return mPaddings; + } + + private WindowManager.LayoutParams getLayoutParams() { + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth, + isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT, + mapZOrderToBarType(mZOrder), + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE + | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH + | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH, + PixelFormat.TRANSLUCENT); + lp.setTitle(BAR_TITLE_MAP.get(mSide)); + lp.providesInsetsTypes = new int[]{BAR_TYPE_MAP[mBarType], BAR_GESTURE_MAP.get(mSide)}; + lp.setFitInsetsTypes(0); + lp.windowAnimations = 0; + lp.gravity = BAR_GRAVITY_MAP.get(mSide); + return lp; + } + + private int mapZOrderToBarType(int zOrder) { + return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL + : WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL; + } + + private void setPaddingBySide(@SystemBarSide int side, int padding) { + mPaddings[side] = padding; + } + } + + private static final class SystemBarConfigBuilder { + private int mSide; + private int mBarType; + private int mGirth; + private int mZOrder; + + private SystemBarConfigBuilder setSide(@SystemBarSide int side) { + mSide = side; + return this; + } + + private SystemBarConfigBuilder setBarType(int type) { + mBarType = type; + return this; + } + + private SystemBarConfigBuilder setGirth(int girth) { + mGirth = girth; + return this; + } + + private SystemBarConfigBuilder setZOrder(int zOrder) { + mZOrder = zOrder; + return this; + } + + private SystemBarConfig build() { + return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder); + } + } +} |