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.InsetsState.ITYPE_NAVIGATION_BAR;
20 import static android.view.InsetsState.ITYPE_STATUS_BAR;
21 import static android.view.InsetsState.containsType;
22 import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
23 
24 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
25 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
26 
27 import android.app.StatusBarManager.Disable2Flags;
28 import android.app.StatusBarManager.DisableFlags;
29 import android.content.Context;
30 import android.inputmethodservice.InputMethodService;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.view.Display;
34 import android.view.InsetsVisibilities;
35 import android.view.View;
36 import android.view.ViewGroup;
37 import android.view.WindowInsetsController;
38 import android.view.WindowManager;
39 
40 import androidx.annotation.VisibleForTesting;
41 
42 import com.android.internal.statusbar.IStatusBarService;
43 import com.android.internal.statusbar.RegisterStatusBarResult;
44 import com.android.internal.view.AppearanceRegion;
45 import com.android.systemui.SystemUI;
46 import com.android.systemui.car.CarDeviceProvisionedController;
47 import com.android.systemui.car.CarDeviceProvisionedListener;
48 import com.android.systemui.car.hvac.HvacController;
49 import com.android.systemui.dagger.qualifiers.Main;
50 import com.android.systemui.dagger.qualifiers.UiBackground;
51 import com.android.systemui.plugins.DarkIconDispatcher;
52 import com.android.systemui.shared.system.ActivityManagerWrapper;
53 import com.android.systemui.shared.system.TaskStackChangeListener;
54 import com.android.systemui.statusbar.AutoHideUiElement;
55 import com.android.systemui.statusbar.CommandQueue;
56 import com.android.systemui.statusbar.phone.AutoHideController;
57 import com.android.systemui.statusbar.phone.BarTransitions;
58 import com.android.systemui.statusbar.phone.LightBarController;
59 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
60 import com.android.systemui.statusbar.phone.StatusBarSignalPolicy;
61 import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher;
62 import com.android.systemui.statusbar.policy.KeyguardStateController;
63 import com.android.systemui.util.concurrency.DelayableExecutor;
64 
65 import java.io.FileDescriptor;
66 import java.io.PrintWriter;
67 import java.util.concurrent.Executor;
68 
69 import javax.inject.Inject;
70 
71 import dagger.Lazy;
72 
73 /** Navigation bars customized for the automotive use case. */
74 public class CarSystemBar extends SystemUI implements CommandQueue.Callbacks {
75     private final CarSystemBarController mCarSystemBarController;
76     private final SysuiDarkIconDispatcher mStatusBarIconController;
77     private final WindowManager mWindowManager;
78     private final CarDeviceProvisionedController mCarDeviceProvisionedController;
79     private final CommandQueue mCommandQueue;
80     private final AutoHideController mAutoHideController;
81     private final ButtonSelectionStateListener mButtonSelectionStateListener;
82     private final DelayableExecutor mExecutor;
83     private final Executor mUiBgExecutor;
84     private final IStatusBarService mBarService;
85     private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy;
86     private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy;
87     private final HvacController mHvacController;
88     private final int mDisplayId;
89     private final SystemBarConfigs mSystemBarConfigs;
90 
91     private StatusBarSignalPolicy mSignalPolicy;
92     private ActivityManagerWrapper mActivityManagerWrapper;
93 
94     // If the nav bar should be hidden when the soft keyboard is visible.
95     private boolean mHideTopBarForKeyboard;
96     private boolean mHideLeftBarForKeyboard;
97     private boolean mHideRightBarForKeyboard;
98     private boolean mHideBottomBarForKeyboard;
99 
100     private boolean mBottomNavBarVisible;
101 
102     // Nav bar views.
103     private ViewGroup mTopSystemBarWindow;
104     private ViewGroup mBottomSystemBarWindow;
105     private ViewGroup mLeftSystemBarWindow;
106     private ViewGroup mRightSystemBarWindow;
107     private CarSystemBarView mTopSystemBarView;
108     private CarSystemBarView mBottomSystemBarView;
109     private CarSystemBarView mLeftSystemBarView;
110     private CarSystemBarView mRightSystemBarView;
111 
112     // To be attached to the navigation bars such that they can close the notification panel if
113     // it's open.
114     private boolean mDeviceIsSetUpForUser = true;
115     private boolean mIsUserSetupInProgress = false;
116 
117     private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0];
118     @BarTransitions.TransitionMode
119     private int mStatusBarMode;
120     @BarTransitions.TransitionMode
121     private int mSystemBarMode;
122     private boolean mStatusBarTransientShown;
123     private boolean mNavBarTransientShown;
124 
125     @Inject
CarSystemBar(Context context, CarSystemBarController carSystemBarController, LightBarController lightBarController, DarkIconDispatcher darkIconDispatcher, WindowManager windowManager, CarDeviceProvisionedController deviceProvisionedController, CommandQueue commandQueue, AutoHideController autoHideController, ButtonSelectionStateListener buttonSelectionStateListener, @Main DelayableExecutor mainExecutor, @UiBackground Executor uiBgExecutor, IStatusBarService barService, Lazy<KeyguardStateController> keyguardStateControllerLazy, Lazy<PhoneStatusBarPolicy> iconPolicyLazy, StatusBarSignalPolicy signalPolicy, HvacController hvacController, SystemBarConfigs systemBarConfigs )126     public CarSystemBar(Context context,
127             CarSystemBarController carSystemBarController,
128             // TODO(b/156052638): Should not need to inject LightBarController
129             LightBarController lightBarController,
130             DarkIconDispatcher darkIconDispatcher,
131             WindowManager windowManager,
132             CarDeviceProvisionedController deviceProvisionedController,
133             CommandQueue commandQueue,
134             AutoHideController autoHideController,
135             ButtonSelectionStateListener buttonSelectionStateListener,
136             @Main DelayableExecutor mainExecutor,
137             @UiBackground Executor uiBgExecutor,
138             IStatusBarService barService,
139             Lazy<KeyguardStateController> keyguardStateControllerLazy,
140             Lazy<PhoneStatusBarPolicy> iconPolicyLazy,
141             StatusBarSignalPolicy signalPolicy,
142             HvacController hvacController,
143             SystemBarConfigs systemBarConfigs
144     ) {
145         super(context);
146         mCarSystemBarController = carSystemBarController;
147         mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
148         mWindowManager = windowManager;
149         mCarDeviceProvisionedController = deviceProvisionedController;
150         mCommandQueue = commandQueue;
151         mAutoHideController = autoHideController;
152         mButtonSelectionStateListener = buttonSelectionStateListener;
153         mExecutor = mainExecutor;
154         mUiBgExecutor = uiBgExecutor;
155         mBarService = barService;
156         mKeyguardStateControllerLazy = keyguardStateControllerLazy;
157         mIconPolicyLazy = iconPolicyLazy;
158         mHvacController = hvacController;
159         mSystemBarConfigs = systemBarConfigs;
160         mSignalPolicy = signalPolicy;
161         mDisplayId = context.getDisplayId();
162     }
163 
164     @Override
start()165     public void start() {
166         // Set initial state.
167         mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
168         mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
169                 SystemBarConfigs.BOTTOM);
170         mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT);
171         mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
172                 SystemBarConfigs.RIGHT);
173 
174         mBottomNavBarVisible = false;
175 
176         // Connect into the status bar manager service
177         mCommandQueue.addCallback(this);
178 
179         RegisterStatusBarResult result = null;
180         try {
181             result = mBarService.registerStatusBar(mCommandQueue);
182         } catch (RemoteException ex) {
183             ex.rethrowFromSystemServer();
184         }
185 
186         onSystemBarAttributesChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions,
187                 result.mNavbarColorManagedByIme, result.mBehavior, result.mRequestedVisibilities,
188                 result.mPackageName);
189 
190         // StatusBarManagerService has a back up of IME token and it's restored here.
191         setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis,
192                 result.mImeBackDisposition, result.mShowImeSwitcher);
193 
194         // Set up the initial icon state
195         int numIcons = result.mIcons.size();
196         for (int i = 0; i < numIcons; i++) {
197             mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
198         }
199 
200         mAutoHideController.setStatusBar(new AutoHideUiElement() {
201             @Override
202             public void synchronizeState() {
203                 // No op.
204             }
205 
206             @Override
207             public boolean isVisible() {
208                 return mStatusBarTransientShown;
209             }
210 
211             @Override
212             public void hide() {
213                 clearTransient();
214             }
215         });
216 
217         mAutoHideController.setNavigationBar(new AutoHideUiElement() {
218             @Override
219             public void synchronizeState() {
220                 // No op.
221             }
222 
223             @Override
224             public boolean isVisible() {
225                 return mNavBarTransientShown;
226             }
227 
228             @Override
229             public void hide() {
230                 clearTransient();
231             }
232         });
233 
234         mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup();
235         mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
236         mCarDeviceProvisionedController.addCallback(
237                 new CarDeviceProvisionedListener() {
238                     @Override
239                     public void onUserSetupInProgressChanged() {
240                         mExecutor.execute(() -> restartNavBarsIfNecessary());
241                     }
242 
243                     @Override
244                     public void onUserSetupChanged() {
245                         mExecutor.execute(() -> restartNavBarsIfNecessary());
246                     }
247 
248                     @Override
249                     public void onUserSwitched() {
250                         mExecutor.execute(() -> restartNavBarsIfNecessary());
251                     }
252                 });
253 
254         createSystemBar(result);
255 
256         mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
257         mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener);
258         mActivityManagerWrapper.registerTaskStackListener(new TaskStackChangeListener() {
259             @Override
260             public void onLockTaskModeChanged(int mode) {
261                 mCarSystemBarController.refreshSystemBarByLockTaskFeatures();
262             }
263         });
264 
265         // Lastly, call to the icon policy to install/update all the icons.
266         // Must be called on the main thread due to the use of observeForever() in
267         // mIconPolicy.init().
268         mExecutor.execute(() -> {
269             mIconPolicyLazy.get().init();
270         });
271     }
272 
restartNavBarsIfNecessary()273     private void restartNavBarsIfNecessary() {
274         boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup();
275         boolean currentUserSetupInProgress = mCarDeviceProvisionedController
276                 .isCurrentUserSetupInProgress();
277         if (mIsUserSetupInProgress != currentUserSetupInProgress
278                 || mDeviceIsSetUpForUser != currentUserSetup) {
279             mDeviceIsSetUpForUser = currentUserSetup;
280             mIsUserSetupInProgress = currentUserSetupInProgress;
281             restartNavBars();
282         }
283     }
284 
285     /**
286      * Remove all content from navbars and rebuild them. Used to allow for different nav bars
287      * before and after the device is provisioned. . Also for change of density and font size.
288      */
restartNavBars()289     private void restartNavBars() {
290         // remove and reattach all components such that we don't keep a reference to unused ui
291         // elements
292         mCarSystemBarController.removeAll();
293 
294         if (mTopSystemBarWindow != null) {
295             mTopSystemBarWindow.removeAllViews();
296             mHvacController.unregisterViews(mTopSystemBarView);
297             mTopSystemBarView = null;
298         }
299 
300         if (mBottomSystemBarWindow != null) {
301             mBottomSystemBarWindow.removeAllViews();
302             mHvacController.unregisterViews(mBottomSystemBarView);
303             mBottomSystemBarView = null;
304         }
305 
306         if (mLeftSystemBarWindow != null) {
307             mLeftSystemBarWindow.removeAllViews();
308             mHvacController.unregisterViews(mLeftSystemBarView);
309             mLeftSystemBarView = null;
310         }
311 
312         if (mRightSystemBarWindow != null) {
313             mRightSystemBarWindow.removeAllViews();
314             mHvacController.unregisterViews(mRightSystemBarView);
315             mRightSystemBarView = null;
316         }
317 
318         buildNavBarContent();
319         // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need
320         // to correctly respect that state.
321         if (mKeyguardStateControllerLazy.get().isShowing()) {
322             mCarSystemBarController.showAllKeyguardButtons(isDeviceSetupForUser());
323         } else {
324             mCarSystemBarController.showAllNavigationButtons(isDeviceSetupForUser());
325         }
326 
327         // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the
328         // selection state that reflects the current task stack.
329         mButtonSelectionStateListener.onTaskStackChanged();
330     }
331 
isDeviceSetupForUser()332     private boolean isDeviceSetupForUser() {
333         return mDeviceIsSetUpForUser && !mIsUserSetupInProgress;
334     }
335 
createSystemBar(RegisterStatusBarResult result)336     private void createSystemBar(RegisterStatusBarResult result) {
337         buildNavBarWindows();
338         buildNavBarContent();
339         attachNavBarWindows();
340 
341         // Try setting up the initial state of the nav bar if applicable.
342         if (result != null) {
343             setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken,
344                     result.mImeWindowVis, result.mImeBackDisposition,
345                     result.mShowImeSwitcher);
346         }
347     }
348 
buildNavBarWindows()349     private void buildNavBarWindows() {
350         mTopSystemBarWindow = mCarSystemBarController.getTopWindow();
351         mBottomSystemBarWindow = mCarSystemBarController.getBottomWindow();
352         mLeftSystemBarWindow = mCarSystemBarController.getLeftWindow();
353         mRightSystemBarWindow = mCarSystemBarController.getRightWindow();
354     }
355 
buildNavBarContent()356     private void buildNavBarContent() {
357         mTopSystemBarView = mCarSystemBarController.getTopBar(isDeviceSetupForUser());
358         if (mTopSystemBarView != null) {
359             mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopSystemBarView);
360             mHvacController.registerHvacViews(mTopSystemBarView);
361             mTopSystemBarWindow.addView(mTopSystemBarView);
362         }
363 
364         mBottomSystemBarView = mCarSystemBarController.getBottomBar(isDeviceSetupForUser());
365         if (mBottomSystemBarView != null) {
366             mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomSystemBarView);
367             mHvacController.registerHvacViews(mBottomSystemBarView);
368             mBottomSystemBarWindow.addView(mBottomSystemBarView);
369         }
370 
371         mLeftSystemBarView = mCarSystemBarController.getLeftBar(isDeviceSetupForUser());
372         if (mLeftSystemBarView != null) {
373             mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftSystemBarView);
374             mHvacController.registerHvacViews(mLeftSystemBarView);
375             mLeftSystemBarWindow.addView(mLeftSystemBarView);
376         }
377 
378         mRightSystemBarView = mCarSystemBarController.getRightBar(isDeviceSetupForUser());
379         if (mRightSystemBarView != null) {
380             mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightSystemBarView);
381             mHvacController.registerHvacViews(mRightSystemBarView);
382             mRightSystemBarWindow.addView(mRightSystemBarView);
383         }
384     }
385 
attachNavBarWindows()386     private void attachNavBarWindows() {
387         mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide);
388     }
389 
attachNavBarBySide(int side)390     private void attachNavBarBySide(int side) {
391         switch (side) {
392             case SystemBarConfigs.TOP:
393                 if (mTopSystemBarWindow != null) {
394                     mWindowManager.addView(mTopSystemBarWindow,
395                             mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP));
396                 }
397                 break;
398             case SystemBarConfigs.BOTTOM:
399                 if (mBottomSystemBarWindow != null && !mBottomNavBarVisible) {
400                     mBottomNavBarVisible = true;
401 
402                     mWindowManager.addView(mBottomSystemBarWindow,
403                             mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM));
404                 }
405                 break;
406             case SystemBarConfigs.LEFT:
407                 if (mLeftSystemBarWindow != null) {
408                     mWindowManager.addView(mLeftSystemBarWindow,
409                             mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT));
410                 }
411                 break;
412             case SystemBarConfigs.RIGHT:
413                 if (mRightSystemBarWindow != null) {
414                     mWindowManager.addView(mRightSystemBarWindow,
415                             mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT));
416                 }
417                 break;
418             default:
419                 return;
420         }
421     }
422 
423     /**
424      * We register for soft keyboard visibility events such that we can hide the navigation bar
425      * giving more screen space to the IME. Note: this is optional and controlled by
426      * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}.
427      */
428     @Override
setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, boolean showImeSwitcher)429     public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
430             boolean showImeSwitcher) {
431         if (mContext.getDisplayId() != displayId) {
432             return;
433         }
434 
435         boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
436 
437         if (mHideTopBarForKeyboard) {
438             mCarSystemBarController.setTopWindowVisibility(
439                     isKeyboardVisible ? View.GONE : View.VISIBLE);
440         }
441 
442         if (mHideBottomBarForKeyboard) {
443             mCarSystemBarController.setBottomWindowVisibility(
444                     isKeyboardVisible ? View.GONE : View.VISIBLE);
445         }
446 
447         if (mHideLeftBarForKeyboard) {
448             mCarSystemBarController.setLeftWindowVisibility(
449                     isKeyboardVisible ? View.GONE : View.VISIBLE);
450         }
451         if (mHideRightBarForKeyboard) {
452             mCarSystemBarController.setRightWindowVisibility(
453                     isKeyboardVisible ? View.GONE : View.VISIBLE);
454         }
455     }
456 
457     @Override
onSystemBarAttributesChanged( int displayId, @WindowInsetsController.Appearance int appearance, AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, @WindowInsetsController.Behavior int behavior, InsetsVisibilities requestedVisibilities, String packageName)458     public void onSystemBarAttributesChanged(
459             int displayId,
460             @WindowInsetsController.Appearance int appearance,
461             AppearanceRegion[] appearanceRegions,
462             boolean navbarColorManagedByIme,
463             @WindowInsetsController.Behavior int behavior,
464             InsetsVisibilities requestedVisibilities,
465             String packageName) {
466         if (displayId != mDisplayId) {
467             return;
468         }
469         boolean barModeChanged = updateStatusBarMode(
470                 mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
471         int numStacks = appearanceRegions.length;
472         boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks;
473         for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) {
474             stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]);
475         }
476         if (stackAppearancesChanged || barModeChanged) {
477             mAppearanceRegions = appearanceRegions;
478             updateStatusBarAppearance();
479         }
480         mCarSystemBarController.refreshSystemBarByLockTaskFeatures();
481     }
482 
483     @Override
disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2, boolean animate)484     public void disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2,
485             boolean animate) {
486         if (displayId != mDisplayId) {
487             return;
488         }
489         mCarSystemBarController.setStatusBarState(state1);
490     }
491 
updateStatusBarAppearance()492     private void updateStatusBarAppearance() {
493         int numStacks = mAppearanceRegions.length;
494         int numLightStacks = 0;
495 
496         // We can only have maximum one light stack.
497         int indexLightStack = -1;
498 
499         for (int i = 0; i < numStacks; i++) {
500             if (isLight(mAppearanceRegions[i].getAppearance())) {
501                 numLightStacks++;
502                 indexLightStack = i;
503             }
504         }
505 
506         // If all stacks are light, all icons become dark.
507         if (numLightStacks == numStacks) {
508             mStatusBarIconController.setIconsDarkArea(null);
509             mStatusBarIconController.getTransitionsController().setIconsDark(
510                     /* dark= */ true, /* animate= */ false);
511         } else if (numLightStacks == 0) {
512             // If no one is light, all icons become white.
513             mStatusBarIconController.getTransitionsController().setIconsDark(
514                     /* dark= */ false, /* animate= */ false);
515         } else {
516             // Not the same for every stack, update icons in area only.
517             mStatusBarIconController.setIconsDarkArea(
518                     mAppearanceRegions[indexLightStack].getBounds());
519             mStatusBarIconController.getTransitionsController().setIconsDark(
520                     /* dark= */ true, /* animate= */ false);
521         }
522     }
523 
isLight(int appearance)524     private static boolean isLight(int appearance) {
525         return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0;
526     }
527 
528     @Override
showTransient(int displayId, int[] types)529     public void showTransient(int displayId, int[] types) {
530         if (displayId != mDisplayId) {
531             return;
532         }
533         if (containsType(types, ITYPE_STATUS_BAR)) {
534             if (!mStatusBarTransientShown) {
535                 mStatusBarTransientShown = true;
536                 handleTransientChanged();
537             }
538         }
539         if (containsType(types, ITYPE_NAVIGATION_BAR)) {
540             if (!mNavBarTransientShown) {
541                 mNavBarTransientShown = true;
542                 handleTransientChanged();
543             }
544         }
545     }
546 
547     @Override
abortTransient(int displayId, int[] types)548     public void abortTransient(int displayId, int[] types) {
549         if (displayId != mDisplayId) {
550             return;
551         }
552         if (!containsType(types, ITYPE_STATUS_BAR) && !containsType(types, ITYPE_NAVIGATION_BAR)) {
553             return;
554         }
555         clearTransient();
556     }
557 
clearTransient()558     private void clearTransient() {
559         if (mStatusBarTransientShown) {
560             mStatusBarTransientShown = false;
561             handleTransientChanged();
562         }
563         if (mNavBarTransientShown) {
564             mNavBarTransientShown = false;
565             handleTransientChanged();
566         }
567     }
568 
569     @VisibleForTesting
isStatusBarTransientShown()570     boolean isStatusBarTransientShown() {
571         return mStatusBarTransientShown;
572     }
573 
574     @VisibleForTesting
isNavBarTransientShown()575     boolean isNavBarTransientShown() {
576         return mNavBarTransientShown;
577     }
578 
579     @VisibleForTesting
setSignalPolicy(StatusBarSignalPolicy signalPolicy)580     void setSignalPolicy(StatusBarSignalPolicy signalPolicy) {
581         mSignalPolicy = signalPolicy;
582     }
583 
584     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)585     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
586         pw.print("  mTaskStackListener=");
587         pw.println(mButtonSelectionStateListener);
588         pw.print("  mBottomSystemBarView=");
589         pw.println(mBottomSystemBarView);
590     }
591 
handleTransientChanged()592     private void handleTransientChanged() {
593         updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
594         updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT);
595     }
596 
597     // Returns true if the status bar mode has changed.
updateStatusBarMode(int barMode)598     private boolean updateStatusBarMode(int barMode) {
599         if (mStatusBarMode != barMode) {
600             mStatusBarMode = barMode;
601             mAutoHideController.touchAutoHide();
602             return true;
603         }
604         return false;
605     }
606 
607     // Returns true if the nav bar mode has changed.
updateNavBarMode(int barMode)608     private boolean updateNavBarMode(int barMode) {
609         if (mSystemBarMode != barMode) {
610             mSystemBarMode = barMode;
611             mAutoHideController.touchAutoHide();
612             return true;
613         }
614         return false;
615     }
616 }
617