Merge "Allow SystemBar configuration via XML." into rvc-qpr-dev

This commit is contained in:
Youngjun Kwak
2020-07-29 20:39:43 +00:00
committed by Android (Google) Code Review
8 changed files with 614 additions and 121 deletions

View File

@@ -24,12 +24,35 @@
<bool name="config_enableFullscreenUserSwitcher">true</bool>
<!-- configure which system ui bars should be displayed -->
<!-- Configure which system bars should be displayed. -->
<bool name="config_enableTopNavigationBar">true</bool>
<bool name="config_enableLeftNavigationBar">false</bool>
<bool name="config_enableRightNavigationBar">false</bool>
<bool name="config_enableBottomNavigationBar">true</bool>
<!-- Configure the type of each system bar. Each system bar must have a unique type. -->
<!-- STATUS_BAR = 0-->
<!-- NAVIGATION_BAR = 1-->
<!-- STATUS_BAR_EXTRA = 2-->
<!-- NAVIGATION_BAR_EXTRA = 3-->
<integer name="config_topSystemBarType">0</integer>
<integer name="config_leftSystemBarType">2</integer>
<integer name="config_rightSystemBarType">3</integer>
<integer name="config_bottomSystemBarType">1</integer>
<!-- Configure the relative z-order among the system bars. When two system bars overlap (e.g.
if both top bar and left bar are enabled, it creates an overlapping space in the upper left
corner), the system bar with the higher z-order takes the overlapping space and padding is
applied to the other bar.-->
<!-- NOTE: If two overlapping system bars have the same z-order, SystemBarConfigs will throw a
RuntimeException, since their placing order cannot be determined. Bars that do not overlap
are allowed to have the same z-order. -->
<!-- NOTE: If the z-order of a bar is 10 or above, it will also appear on top of HUN's. -->
<integer name="config_topSystemBarZOrder">1</integer>
<integer name="config_leftSystemBarZOrder">0</integer>
<integer name="config_rightSystemBarZOrder">0</integer>
<integer name="config_bottomSystemBarZOrder">10</integer>
<!-- Disable normal notification rendering; we handle that ourselves -->
<bool name="config_renderNotifications">false</bool>

View File

@@ -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);
}
mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide);
}
if (mBottomNavigationBarWindow != null && !mBottomNavBarVisible) {
mBottomNavBarVisible = true;
int height = mResources.getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_height);
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;
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);
}
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);
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;
}
}

View File

@@ -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);
}
/**

View File

@@ -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) {

View File

@@ -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);
}
}
}

View File

@@ -73,7 +73,8 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
private CarNavigationBarController createNavigationBarController() {
return new CarNavigationBarController(mContext, mNavigationBarViewFactory,
mButtonSelectionStateController, () -> mHvacController,
mButtonRoleHolderController);
mButtonRoleHolderController,
new SystemBarConfigs(mTestableResources.getResources()));
}
@Test

View File

@@ -142,7 +142,7 @@ public class CarNavigationBarTest extends SysuiTestCase {
mWindowManager, mDeviceProvisionedController, new CommandQueue(mContext),
mAutoHideController, mButtonSelectionStateListener, mHandler, mUiBgExecutor,
mBarService, () -> mKeyguardStateController, () -> mIconPolicy,
() -> mIconController);
() -> mIconController, new SystemBarConfigs(mTestableResources.getResources()));
}
@Test

View File

@@ -0,0 +1,162 @@
/*
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.content.res.Resources;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.car.CarSystemUiTest;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List;
@CarSystemUiTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
public class SystemBarConfigsTest extends SysuiTestCase {
private SystemBarConfigs mSystemBarConfigs;
@Mock
private Resources mResources;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
setDefaultValidConfig();
}
@Test
public void onInit_allSystemBarsEnabled_eachHasUniqueBarTypes_doesNotThrowException() {
mSystemBarConfigs = new SystemBarConfigs(mResources);
}
@Test(expected = RuntimeException.class)
public void onInit_allSystemBarsEnabled_twoBarsHaveDuplicateType_throwsRuntimeException() {
when(mResources.getInteger(R.integer.config_topSystemBarType)).thenReturn(0);
when(mResources.getInteger(R.integer.config_bottomSystemBarType)).thenReturn(0);
mSystemBarConfigs = new SystemBarConfigs(mResources);
}
@Test
public void onInit_allSystemBarsEnabled_systemBarSidesSortedByZOrder() {
mSystemBarConfigs = new SystemBarConfigs(mResources);
List<Integer> actualOrder = mSystemBarConfigs.getSystemBarSidesByZOrder();
List<Integer> expectedOrder = new ArrayList<>();
expectedOrder.add(SystemBarConfigs.LEFT);
expectedOrder.add(SystemBarConfigs.RIGHT);
expectedOrder.add(SystemBarConfigs.TOP);
expectedOrder.add(SystemBarConfigs.BOTTOM);
assertTrue(actualOrder.equals(expectedOrder));
}
@Test(expected = RuntimeException.class)
public void onInit_intersectingBarsHaveSameZOrder_throwsRuntimeException() {
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(33);
when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(33);
mSystemBarConfigs = new SystemBarConfigs(mResources);
}
@Test
public void getTopSystemBarLayoutParams_topBarEnabled_returnsTopSystemBarLayoutParams() {
mSystemBarConfigs = new SystemBarConfigs(mResources);
WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
SystemBarConfigs.TOP);
assertNotNull(lp);
}
@Test
public void getTopSystemBarLayoutParams_topBarNotEnabled_returnsNull() {
when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
mSystemBarConfigs = new SystemBarConfigs(mResources);
WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
SystemBarConfigs.TOP);
assertNull(lp);
}
@Test
public void topSystemBarHasHigherZOrderThanHuns_topSystemBarIsNavigationBarPanelType() {
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
SystemBarConfigs.getHunZOrder() + 1);
mSystemBarConfigs = new SystemBarConfigs(mResources);
WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
SystemBarConfigs.TOP);
assertEquals(lp.type, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL);
}
@Test
public void topSystemBarHasLowerZOrderThanHuns_topSystemBarIsStatusBarAdditionalType() {
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
SystemBarConfigs.getHunZOrder() - 1);
mSystemBarConfigs = new SystemBarConfigs(mResources);
WindowManager.LayoutParams lp = mSystemBarConfigs.getLayoutParamsBySide(
SystemBarConfigs.TOP);
assertEquals(lp.type, WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL);
}
// Set valid config where all system bars are enabled.
private void setDefaultValidConfig() {
when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_enableBottomNavigationBar)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_enableLeftNavigationBar)).thenReturn(true);
when(mResources.getBoolean(R.bool.config_enableRightNavigationBar)).thenReturn(true);
when(mResources.getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height)).thenReturn(100);
when(mResources.getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_height)).thenReturn(100);
when(mResources.getDimensionPixelSize(R.dimen.car_left_navigation_bar_width)).thenReturn(
100);
when(mResources.getDimensionPixelSize(R.dimen.car_right_navigation_bar_width)).thenReturn(
100);
when(mResources.getInteger(R.integer.config_topSystemBarType)).thenReturn(0);
when(mResources.getInteger(R.integer.config_bottomSystemBarType)).thenReturn(1);
when(mResources.getInteger(R.integer.config_leftSystemBarType)).thenReturn(2);
when(mResources.getInteger(R.integer.config_rightSystemBarType)).thenReturn(3);
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(5);
when(mResources.getInteger(R.integer.config_bottomSystemBarZOrder)).thenReturn(10);
when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(2);
when(mResources.getInteger(R.integer.config_rightSystemBarZOrder)).thenReturn(3);
}
}