• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.car.systembar;
18 
19 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
20 
21 import android.annotation.IntDef;
22 import android.content.res.Resources;
23 import android.graphics.PixelFormat;
24 import android.os.Binder;
25 import android.util.ArrayMap;
26 import android.util.ArraySet;
27 import android.util.Log;
28 import android.view.Gravity;
29 import android.view.InsetsFrameProvider;
30 import android.view.ViewGroup;
31 import android.view.WindowInsets;
32 import android.view.WindowManager;
33 
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.systemui.R;
36 import com.android.systemui.car.notification.BottomNotificationPanelViewMediator;
37 import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
38 import com.android.systemui.dagger.SysUISingleton;
39 import com.android.systemui.dagger.qualifiers.Main;
40 
41 import java.lang.annotation.ElementType;
42 import java.lang.annotation.Target;
43 import java.util.ArrayList;
44 import java.util.Comparator;
45 import java.util.List;
46 import java.util.Map;
47 import java.util.Set;
48 
49 import javax.inject.Inject;
50 
51 /**
52  * Reads configs for system bars for each side (TOP, BOTTOM, LEFT, and RIGHT) and returns the
53  * corresponding {@link android.view.WindowManager.LayoutParams} per the configuration.
54  */
55 @SysUISingleton
56 public class SystemBarConfigs {
57 
58     private static final String TAG = SystemBarConfigs.class.getSimpleName();
59     // The z-order from which system bars will start to appear on top of HUN's.
60     private static final int HUN_ZORDER = 10;
61 
62     @IntDef(value = {TOP, BOTTOM, LEFT, RIGHT})
63     @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
64     private @interface SystemBarSide {
65     }
66 
67     public static final int TOP = 0;
68     public static final int BOTTOM = 1;
69     public static final int LEFT = 2;
70     public static final int RIGHT = 3;
71 
72     private static final Binder INSETS_OWNER = new Binder();
73 
74     /*
75         NOTE: The elements' order in the map below must be preserved as-is since the correct
76         corresponding values are obtained by the index.
77      */
78     public static final InsetsFrameProvider[] BAR_PROVIDER_MAP = {
79             new InsetsFrameProvider(
80                     INSETS_OWNER, 0 /* index */, WindowInsets.Type.statusBars()),
81             new InsetsFrameProvider(
82                     INSETS_OWNER, 0 /* index */, WindowInsets.Type.navigationBars()),
83             new InsetsFrameProvider(
84                     INSETS_OWNER, 1 /* index */, WindowInsets.Type.statusBars()),
85             new InsetsFrameProvider(
86                     INSETS_OWNER, 1 /* index */, WindowInsets.Type.navigationBars()),
87     };
88 
89     private static final Map<@SystemBarSide Integer, Integer> BAR_GRAVITY_MAP = new ArrayMap<>();
90     private static final Map<@SystemBarSide Integer, String> BAR_TITLE_MAP = new ArrayMap<>();
91     private static final Map<@SystemBarSide Integer, InsetsFrameProvider> BAR_GESTURE_MAP =
92             new ArrayMap<>();
93 
94     private final Resources mResources;
95     private final Map<@SystemBarSide Integer, SystemBarConfig> mSystemBarConfigMap =
96             new ArrayMap<>();
97     private final List<@SystemBarSide Integer> mSystemBarSidesByZOrder = new ArrayList<>();
98 
99     private boolean mTopNavBarEnabled;
100     private boolean mBottomNavBarEnabled;
101     private boolean mLeftNavBarEnabled;
102     private boolean mRightNavBarEnabled;
103 
104     @Inject
SystemBarConfigs(@ain Resources resources)105     public SystemBarConfigs(@Main Resources resources) {
106         mResources = resources;
107         init();
108     }
109 
init()110     private void init() {
111         populateMaps();
112         readConfigs();
113 
114         checkEnabledBarsHaveUniqueBarTypes();
115         checkAllOverlappingBarsHaveDifferentZOrders();
116         checkSystemBarEnabledForNotificationPanel();
117         checkHideBottomBarForKeyboardConfigSync();
118 
119         setInsetPaddingsForOverlappingCorners();
120         sortSystemBarSidesByZOrder();
121     }
122 
123     /**
124      * Invalidate cached resources and fetch from resources config file.
125      * TODO: b/260206944, Can remove this after we have a fix for overlaid resources not applied.
126      * <p>
127      * Since SystemBarConfig is a Scoped(Dagger Singleton Annotation), We will have stale values, of
128      * all the resources after the RRO is applied.
129      * Another way is to remove the Scope(Singleton), but the downside is that it will be re-created
130      * everytime.
131      * </p>
132      */
resetSystemBarConfigs()133     void resetSystemBarConfigs() {
134         init();
135     }
136 
getLayoutParamsBySide(@ystemBarSide int side)137     protected WindowManager.LayoutParams getLayoutParamsBySide(@SystemBarSide int side) {
138         return mSystemBarConfigMap.get(side) != null
139                 ? mSystemBarConfigMap.get(side).getLayoutParams() : null;
140     }
141 
getEnabledStatusBySide(@ystemBarSide int side)142     protected boolean getEnabledStatusBySide(@SystemBarSide int side) {
143         switch (side) {
144             case TOP:
145                 return mTopNavBarEnabled;
146             case BOTTOM:
147                 return mBottomNavBarEnabled;
148             case LEFT:
149                 return mLeftNavBarEnabled;
150             case RIGHT:
151                 return mRightNavBarEnabled;
152             default:
153                 return false;
154         }
155     }
156 
getHideForKeyboardBySide(@ystemBarSide int side)157     protected boolean getHideForKeyboardBySide(@SystemBarSide int side) {
158         return mSystemBarConfigMap.get(side) != null
159                 && mSystemBarConfigMap.get(side).getHideForKeyboard();
160     }
161 
insetSystemBar(@ystemBarSide int side, CarSystemBarView view)162     protected void insetSystemBar(@SystemBarSide int side, CarSystemBarView view) {
163         if (mSystemBarConfigMap.get(side) == null) return;
164 
165         int[] paddings = mSystemBarConfigMap.get(side).getPaddings();
166         view.setPadding(paddings[2], paddings[0], paddings[3], paddings[1]);
167     }
168 
getSystemBarSidesByZOrder()169     protected List<Integer> getSystemBarSidesByZOrder() {
170         return mSystemBarSidesByZOrder;
171     }
172 
173     @VisibleForTesting
updateInsetPaddings(@ystemBarSide int side, Map<@SystemBarSide Integer, Boolean> barVisibilities)174     void updateInsetPaddings(@SystemBarSide int side,
175             Map<@SystemBarSide Integer, Boolean> barVisibilities) {
176         SystemBarConfig currentConfig = mSystemBarConfigMap.get(side);
177 
178         if (currentConfig == null) return;
179 
180         if (isHorizontalBar(side)) {
181             if (mLeftNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get(
182                     LEFT).getZOrder()) {
183                 currentConfig.setPaddingBySide(LEFT,
184                         barVisibilities.get(LEFT) ? mSystemBarConfigMap.get(LEFT).getGirth() : 0);
185             }
186             if (mRightNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get(
187                     RIGHT).getZOrder()) {
188                 currentConfig.setPaddingBySide(RIGHT,
189                         barVisibilities.get(RIGHT) ? mSystemBarConfigMap.get(RIGHT).getGirth() : 0);
190             }
191         }
192         if (isVerticalBar(side)) {
193             if (mTopNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get(
194                     TOP).getZOrder()) {
195                 currentConfig.setPaddingBySide(TOP,
196                         barVisibilities.get(TOP) ? mSystemBarConfigMap.get(TOP).getGirth() : 0);
197             }
198             if (mBottomNavBarEnabled && currentConfig.getZOrder() < mSystemBarConfigMap.get(
199                     BOTTOM).getZOrder()) {
200                 currentConfig.setPaddingBySide(BOTTOM,
201                         barVisibilities.get(BOTTOM) ? mSystemBarConfigMap.get(BOTTOM).getGirth()
202                                 : 0);
203             }
204         }
205     }
206 
207     @VisibleForTesting
getHunZOrder()208     static int getHunZOrder() {
209         return HUN_ZORDER;
210     }
211 
populateMaps()212     private static void populateMaps() {
213         BAR_GRAVITY_MAP.put(TOP, Gravity.TOP);
214         BAR_GRAVITY_MAP.put(BOTTOM, Gravity.BOTTOM);
215         BAR_GRAVITY_MAP.put(LEFT, Gravity.LEFT);
216         BAR_GRAVITY_MAP.put(RIGHT, Gravity.RIGHT);
217 
218         BAR_TITLE_MAP.put(TOP, "TopCarSystemBar");
219         BAR_TITLE_MAP.put(BOTTOM, "BottomCarSystemBar");
220         BAR_TITLE_MAP.put(LEFT, "LeftCarSystemBar");
221         BAR_TITLE_MAP.put(RIGHT, "RightCarSystemBar");
222 
223         BAR_GESTURE_MAP.put(TOP, new InsetsFrameProvider(
224                 INSETS_OWNER, 0 /* index */, WindowInsets.Type.mandatorySystemGestures()));
225         BAR_GESTURE_MAP.put(BOTTOM, new InsetsFrameProvider(
226                 INSETS_OWNER, 1 /* index */, WindowInsets.Type.mandatorySystemGestures()));
227         BAR_GESTURE_MAP.put(LEFT, new InsetsFrameProvider(
228                 INSETS_OWNER, 2 /* index */, WindowInsets.Type.mandatorySystemGestures()));
229         BAR_GESTURE_MAP.put(RIGHT, new InsetsFrameProvider(
230                 INSETS_OWNER, 3 /* index */, WindowInsets.Type.mandatorySystemGestures()));
231     }
232 
readConfigs()233     private void readConfigs() {
234         mTopNavBarEnabled = mResources.getBoolean(R.bool.config_enableTopSystemBar);
235         mBottomNavBarEnabled = mResources.getBoolean(R.bool.config_enableBottomSystemBar);
236         mLeftNavBarEnabled = mResources.getBoolean(R.bool.config_enableLeftSystemBar);
237         mRightNavBarEnabled = mResources.getBoolean(R.bool.config_enableRightSystemBar);
238 
239         if (mTopNavBarEnabled) {
240             SystemBarConfig topBarConfig =
241                     new SystemBarConfigBuilder()
242                             .setSide(TOP)
243                             .setGirth(mResources.getDimensionPixelSize(
244                                     R.dimen.car_top_system_bar_height))
245                             .setBarType(mResources.getInteger(R.integer.config_topSystemBarType))
246                             .setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder))
247                             .setHideForKeyboard(mResources.getBoolean(
248                                     R.bool.config_hideTopSystemBarForKeyboard))
249                             .build();
250             mSystemBarConfigMap.put(TOP, topBarConfig);
251         }
252 
253         if (mBottomNavBarEnabled) {
254             SystemBarConfig bottomBarConfig =
255                     new SystemBarConfigBuilder()
256                             .setSide(BOTTOM)
257                             .setGirth(mResources.getDimensionPixelSize(
258                                     R.dimen.car_bottom_system_bar_height))
259                             .setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType))
260                             .setZOrder(
261                                     mResources.getInteger(R.integer.config_bottomSystemBarZOrder))
262                             .setHideForKeyboard(mResources.getBoolean(
263                                     R.bool.config_hideBottomSystemBarForKeyboard))
264                             .build();
265             mSystemBarConfigMap.put(BOTTOM, bottomBarConfig);
266         }
267 
268         if (mLeftNavBarEnabled) {
269             SystemBarConfig leftBarConfig =
270                     new SystemBarConfigBuilder()
271                             .setSide(LEFT)
272                             .setGirth(mResources.getDimensionPixelSize(
273                                     R.dimen.car_left_system_bar_width))
274                             .setBarType(mResources.getInteger(R.integer.config_leftSystemBarType))
275                             .setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder))
276                             .setHideForKeyboard(mResources.getBoolean(
277                                     R.bool.config_hideLeftSystemBarForKeyboard))
278                             .build();
279             mSystemBarConfigMap.put(LEFT, leftBarConfig);
280         }
281 
282         if (mRightNavBarEnabled) {
283             SystemBarConfig rightBarConfig =
284                     new SystemBarConfigBuilder()
285                             .setSide(RIGHT)
286                             .setGirth(mResources.getDimensionPixelSize(
287                                     R.dimen.car_right_system_bar_width))
288                             .setBarType(mResources.getInteger(R.integer.config_rightSystemBarType))
289                             .setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder))
290                             .setHideForKeyboard(mResources.getBoolean(
291                                     R.bool.config_hideRightSystemBarForKeyboard))
292                             .build();
293             mSystemBarConfigMap.put(RIGHT, rightBarConfig);
294         }
295     }
296 
checkEnabledBarsHaveUniqueBarTypes()297     private void checkEnabledBarsHaveUniqueBarTypes() throws RuntimeException {
298         Set<Integer> barTypesUsed = new ArraySet<>();
299         int enabledNavBarCount = mSystemBarConfigMap.size();
300 
301         for (SystemBarConfig systemBarConfig : mSystemBarConfigMap.values()) {
302             barTypesUsed.add(systemBarConfig.getBarType());
303         }
304 
305         // The number of bar types used cannot be fewer than that of enabled system bars.
306         if (barTypesUsed.size() < enabledNavBarCount) {
307             throw new RuntimeException("Each enabled system bar must have a unique bar type. Check "
308                     + "the configuration in config.xml");
309         }
310     }
311 
checkAllOverlappingBarsHaveDifferentZOrders()312     private void checkAllOverlappingBarsHaveDifferentZOrders() {
313         checkOverlappingBarsHaveDifferentZOrders(TOP, LEFT);
314         checkOverlappingBarsHaveDifferentZOrders(TOP, RIGHT);
315         checkOverlappingBarsHaveDifferentZOrders(BOTTOM, LEFT);
316         checkOverlappingBarsHaveDifferentZOrders(BOTTOM, RIGHT);
317     }
318 
checkSystemBarEnabledForNotificationPanel()319     private void checkSystemBarEnabledForNotificationPanel() throws RuntimeException {
320         String notificationPanelMediatorName =
321                 mResources.getString(R.string.config_notificationPanelViewMediator);
322         if (notificationPanelMediatorName == null) {
323             return;
324         }
325 
326         Class<?> notificationPanelMediatorUsed = null;
327         try {
328             notificationPanelMediatorUsed = Class.forName(notificationPanelMediatorName);
329         } catch (ClassNotFoundException e) {
330             e.printStackTrace();
331         }
332 
333         if (!mTopNavBarEnabled && TopNotificationPanelViewMediator.class.isAssignableFrom(
334                 notificationPanelMediatorUsed)) {
335             throw new RuntimeException(
336                     "Top System Bar must be enabled to use " + notificationPanelMediatorName);
337         }
338 
339         if (!mBottomNavBarEnabled && BottomNotificationPanelViewMediator.class.isAssignableFrom(
340                 notificationPanelMediatorUsed)) {
341             throw new RuntimeException("Bottom System Bar must be enabled to use "
342                     + notificationPanelMediatorName);
343         }
344     }
345 
checkHideBottomBarForKeyboardConfigSync()346     private void checkHideBottomBarForKeyboardConfigSync() throws RuntimeException {
347         if (mBottomNavBarEnabled) {
348             boolean actual = mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard);
349             boolean expected = mResources.getBoolean(
350                     com.android.internal.R.bool.config_hideNavBarForKeyboard);
351 
352             if (actual != expected) {
353                 throw new RuntimeException("config_hideBottomSystemBarForKeyboard must not be "
354                         + "overlaid directly and should always refer to"
355                         + "config_hideNavBarForKeyboard. However, their values "
356                         + "currently do not sync. Set config_hideBottomSystemBarForKeyguard to "
357                         + "@*android:bool/config_hideNavBarForKeyboard. To change its "
358                         + "value, overlay config_hideNavBarForKeyboard in "
359                         + "framework/base/core/res/res.");
360             }
361         }
362     }
363 
setInsetPaddingsForOverlappingCorners()364     private void setInsetPaddingsForOverlappingCorners() {
365         Map<@SystemBarSide Integer, Boolean> systemBarVisibilityOnInit =
366                 getSystemBarsVisibilityOnInit();
367         updateInsetPaddings(TOP, systemBarVisibilityOnInit);
368         updateInsetPaddings(BOTTOM, systemBarVisibilityOnInit);
369         updateInsetPaddings(LEFT, systemBarVisibilityOnInit);
370         updateInsetPaddings(RIGHT, systemBarVisibilityOnInit);
371     }
372 
sortSystemBarSidesByZOrder()373     private void sortSystemBarSidesByZOrder() {
374         List<SystemBarConfig> systemBarsByZOrder = new ArrayList<>(mSystemBarConfigMap.values());
375 
376         systemBarsByZOrder.sort(new Comparator<SystemBarConfig>() {
377             @Override
378             public int compare(SystemBarConfig o1, SystemBarConfig o2) {
379                 return o1.getZOrder() - o2.getZOrder();
380             }
381         });
382 
383         mSystemBarSidesByZOrder.clear();
384         systemBarsByZOrder.forEach(systemBarConfig -> {
385             mSystemBarSidesByZOrder.add(systemBarConfig.getSide());
386         });
387     }
388 
389     // On init, system bars are visible as long as they are enabled.
getSystemBarsVisibilityOnInit()390     private Map<@SystemBarSide Integer, Boolean> getSystemBarsVisibilityOnInit() {
391         ArrayMap<@SystemBarSide Integer, Boolean> visibilityMap = new ArrayMap<>();
392         visibilityMap.put(TOP, mTopNavBarEnabled);
393         visibilityMap.put(BOTTOM, mBottomNavBarEnabled);
394         visibilityMap.put(LEFT, mLeftNavBarEnabled);
395         visibilityMap.put(RIGHT, mRightNavBarEnabled);
396         return visibilityMap;
397     }
398 
checkOverlappingBarsHaveDifferentZOrders(@ystemBarSide int horizontalSide, @SystemBarSide int verticalSide)399     private void checkOverlappingBarsHaveDifferentZOrders(@SystemBarSide int horizontalSide,
400             @SystemBarSide int verticalSide) {
401 
402         if (isVerticalBar(horizontalSide) || isHorizontalBar(verticalSide)) {
403             Log.w(TAG, "configureBarPaddings: Returning immediately since the horizontal and "
404                     + "vertical sides were not provided correctly.");
405             return;
406         }
407 
408         SystemBarConfig horizontalBarConfig = mSystemBarConfigMap.get(horizontalSide);
409         SystemBarConfig verticalBarConfig = mSystemBarConfigMap.get(verticalSide);
410 
411         if (verticalBarConfig != null && horizontalBarConfig != null) {
412             int horizontalBarZOrder = horizontalBarConfig.getZOrder();
413             int verticalBarZOrder = verticalBarConfig.getZOrder();
414 
415             if (horizontalBarZOrder == verticalBarZOrder) {
416                 throw new RuntimeException(
417                         BAR_TITLE_MAP.get(horizontalSide) + " " + BAR_TITLE_MAP.get(verticalSide)
418                                 + " have the same Z-Order, and so their placing order cannot be "
419                                 + "determined. Determine which bar should be placed on top of the "
420                                 + "other bar and change the Z-order in config.xml accordingly."
421                 );
422             }
423         }
424     }
425 
isHorizontalBar(@ystemBarSide int side)426     private static boolean isHorizontalBar(@SystemBarSide int side) {
427         return side == TOP || side == BOTTOM;
428     }
429 
isVerticalBar(@ystemBarSide int side)430     private static boolean isVerticalBar(@SystemBarSide int side) {
431         return side == LEFT || side == RIGHT;
432     }
433 
434     private static final class SystemBarConfig {
435         private final int mSide;
436         private final int mBarType;
437         private final int mGirth;
438         private final int mZOrder;
439         private final boolean mHideForKeyboard;
440 
441         private int[] mPaddings = new int[]{0, 0, 0, 0};
442 
SystemBarConfig(@ystemBarSide int side, int barType, int girth, int zOrder, boolean hideForKeyboard)443         private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder,
444                 boolean hideForKeyboard) {
445             mSide = side;
446             mBarType = barType;
447             mGirth = girth;
448             mZOrder = zOrder;
449             mHideForKeyboard = hideForKeyboard;
450         }
451 
getSide()452         private int getSide() {
453             return mSide;
454         }
455 
getBarType()456         private int getBarType() {
457             return mBarType;
458         }
459 
getGirth()460         private int getGirth() {
461             return mGirth;
462         }
463 
getZOrder()464         private int getZOrder() {
465             return mZOrder;
466         }
467 
getHideForKeyboard()468         private boolean getHideForKeyboard() {
469             return mHideForKeyboard;
470         }
471 
getPaddings()472         private int[] getPaddings() {
473             return mPaddings;
474         }
475 
getLayoutParams()476         private WindowManager.LayoutParams getLayoutParams() {
477             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
478                     isHorizontalBar(mSide) ? ViewGroup.LayoutParams.MATCH_PARENT : mGirth,
479                     isHorizontalBar(mSide) ? mGirth : ViewGroup.LayoutParams.MATCH_PARENT,
480                     mapZOrderToBarType(mZOrder),
481                     WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
482                             | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
483                             | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
484                             | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH,
485                     PixelFormat.TRANSLUCENT);
486             lp.setTitle(BAR_TITLE_MAP.get(mSide));
487             lp.providedInsets = new InsetsFrameProvider[] {
488                     BAR_PROVIDER_MAP[mBarType],
489                     BAR_GESTURE_MAP.get(mSide)
490             };
491             lp.setFitInsetsTypes(0);
492             lp.windowAnimations = 0;
493             lp.gravity = BAR_GRAVITY_MAP.get(mSide);
494             lp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
495             return lp;
496         }
497 
mapZOrderToBarType(int zOrder)498         private int mapZOrderToBarType(int zOrder) {
499             return zOrder >= HUN_ZORDER ? WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL
500                     : WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
501         }
502 
setPaddingBySide(@ystemBarSide int side, int padding)503         private void setPaddingBySide(@SystemBarSide int side, int padding) {
504             mPaddings[side] = padding;
505         }
506     }
507 
508     private static final class SystemBarConfigBuilder {
509         private int mSide;
510         private int mBarType;
511         private int mGirth;
512         private int mZOrder;
513         private boolean mHideForKeyboard;
514 
setSide(@ystemBarSide int side)515         private SystemBarConfigBuilder setSide(@SystemBarSide int side) {
516             mSide = side;
517             return this;
518         }
519 
setBarType(int type)520         private SystemBarConfigBuilder setBarType(int type) {
521             mBarType = type;
522             return this;
523         }
524 
setGirth(int girth)525         private SystemBarConfigBuilder setGirth(int girth) {
526             mGirth = girth;
527             return this;
528         }
529 
setZOrder(int zOrder)530         private SystemBarConfigBuilder setZOrder(int zOrder) {
531             mZOrder = zOrder;
532             return this;
533         }
534 
setHideForKeyboard(boolean hide)535         private SystemBarConfigBuilder setHideForKeyboard(boolean hide) {
536             mHideForKeyboard = hide;
537             return this;
538         }
539 
build()540         private SystemBarConfig build() {
541             return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard);
542         }
543     }
544 }
545