Merge "Allow SystemBar configuration via XML." into rvc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
4dbcd829fb
@@ -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>
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user