| /* |
| * 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.systembar; |
| |
| import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; |
| import static android.view.InsetsState.ITYPE_STATUS_BAR; |
| import static android.view.InsetsState.containsType; |
| import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS; |
| |
| import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT; |
| import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT; |
| |
| import android.app.StatusBarManager.Disable2Flags; |
| import android.app.StatusBarManager.DisableFlags; |
| import android.content.Context; |
| import android.inputmethodservice.InputMethodService; |
| import android.os.IBinder; |
| import android.os.RemoteException; |
| import android.view.Display; |
| import android.view.InsetsVisibilities; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.view.WindowInsetsController; |
| import android.view.WindowManager; |
| |
| 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.SystemUI; |
| import com.android.systemui.car.CarDeviceProvisionedController; |
| import com.android.systemui.car.CarDeviceProvisionedListener; |
| import com.android.systemui.car.hvac.HvacController; |
| import com.android.systemui.dagger.qualifiers.Main; |
| import com.android.systemui.dagger.qualifiers.UiBackground; |
| import com.android.systemui.plugins.DarkIconDispatcher; |
| import com.android.systemui.shared.system.ActivityManagerWrapper; |
| import com.android.systemui.shared.system.TaskStackChangeListener; |
| import com.android.systemui.statusbar.AutoHideUiElement; |
| import com.android.systemui.statusbar.CommandQueue; |
| import com.android.systemui.statusbar.phone.AutoHideController; |
| import com.android.systemui.statusbar.phone.BarTransitions; |
| import com.android.systemui.statusbar.phone.LightBarController; |
| import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy; |
| import com.android.systemui.statusbar.phone.StatusBarSignalPolicy; |
| import com.android.systemui.statusbar.phone.SysuiDarkIconDispatcher; |
| import com.android.systemui.statusbar.policy.KeyguardStateController; |
| import com.android.systemui.util.concurrency.DelayableExecutor; |
| |
| import java.io.FileDescriptor; |
| import java.io.PrintWriter; |
| import java.util.concurrent.Executor; |
| |
| import javax.inject.Inject; |
| |
| import dagger.Lazy; |
| |
| /** Navigation bars customized for the automotive use case. */ |
| public class CarSystemBar extends SystemUI implements CommandQueue.Callbacks { |
| private final CarSystemBarController mCarSystemBarController; |
| private final SysuiDarkIconDispatcher mStatusBarIconController; |
| private final WindowManager mWindowManager; |
| private final CarDeviceProvisionedController mCarDeviceProvisionedController; |
| private final CommandQueue mCommandQueue; |
| private final AutoHideController mAutoHideController; |
| private final ButtonSelectionStateListener mButtonSelectionStateListener; |
| private final DelayableExecutor mExecutor; |
| private final Executor mUiBgExecutor; |
| private final IStatusBarService mBarService; |
| private final Lazy<KeyguardStateController> mKeyguardStateControllerLazy; |
| private final Lazy<PhoneStatusBarPolicy> mIconPolicyLazy; |
| private final HvacController mHvacController; |
| private final int mDisplayId; |
| private final SystemBarConfigs mSystemBarConfigs; |
| |
| private StatusBarSignalPolicy mSignalPolicy; |
| private ActivityManagerWrapper mActivityManagerWrapper; |
| |
| // If the nav bar should be hidden when the soft keyboard is visible. |
| private boolean mHideTopBarForKeyboard; |
| private boolean mHideLeftBarForKeyboard; |
| private boolean mHideRightBarForKeyboard; |
| private boolean mHideBottomBarForKeyboard; |
| |
| private boolean mBottomNavBarVisible; |
| |
| // Nav bar views. |
| private ViewGroup mTopSystemBarWindow; |
| private ViewGroup mBottomSystemBarWindow; |
| private ViewGroup mLeftSystemBarWindow; |
| private ViewGroup mRightSystemBarWindow; |
| private CarSystemBarView mTopSystemBarView; |
| private CarSystemBarView mBottomSystemBarView; |
| private CarSystemBarView mLeftSystemBarView; |
| private CarSystemBarView mRightSystemBarView; |
| |
| // To be attached to the navigation bars such that they can close the notification panel if |
| // it's open. |
| private boolean mDeviceIsSetUpForUser = true; |
| private boolean mIsUserSetupInProgress = false; |
| |
| private AppearanceRegion[] mAppearanceRegions = new AppearanceRegion[0]; |
| @BarTransitions.TransitionMode |
| private int mStatusBarMode; |
| @BarTransitions.TransitionMode |
| private int mSystemBarMode; |
| private boolean mStatusBarTransientShown; |
| private boolean mNavBarTransientShown; |
| |
| @Inject |
| public CarSystemBar(Context context, |
| CarSystemBarController carSystemBarController, |
| // TODO(b/156052638): Should not need to inject LightBarController |
| 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 |
| ) { |
| super(context); |
| mCarSystemBarController = carSystemBarController; |
| mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher; |
| mWindowManager = windowManager; |
| mCarDeviceProvisionedController = deviceProvisionedController; |
| mCommandQueue = commandQueue; |
| mAutoHideController = autoHideController; |
| mButtonSelectionStateListener = buttonSelectionStateListener; |
| mExecutor = mainExecutor; |
| mUiBgExecutor = uiBgExecutor; |
| mBarService = barService; |
| mKeyguardStateControllerLazy = keyguardStateControllerLazy; |
| mIconPolicyLazy = iconPolicyLazy; |
| mHvacController = hvacController; |
| mSystemBarConfigs = systemBarConfigs; |
| mSignalPolicy = signalPolicy; |
| mDisplayId = context.getDisplayId(); |
| } |
| |
| @Override |
| public void start() { |
| // Set initial state. |
| mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP); |
| mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( |
| SystemBarConfigs.BOTTOM); |
| mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT); |
| mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide( |
| SystemBarConfigs.RIGHT); |
| |
| mBottomNavBarVisible = false; |
| |
| // Connect into the status bar manager service |
| mCommandQueue.addCallback(this); |
| |
| RegisterStatusBarResult result = null; |
| try { |
| result = mBarService.registerStatusBar(mCommandQueue); |
| } catch (RemoteException ex) { |
| ex.rethrowFromSystemServer(); |
| } |
| |
| onSystemBarAttributesChanged(mDisplayId, result.mAppearance, result.mAppearanceRegions, |
| result.mNavbarColorManagedByIme, result.mBehavior, result.mRequestedVisibilities, |
| result.mPackageName); |
| |
| // StatusBarManagerService has a back up of IME token and it's restored here. |
| setImeWindowStatus(mDisplayId, result.mImeToken, result.mImeWindowVis, |
| result.mImeBackDisposition, result.mShowImeSwitcher); |
| |
| // Set up the initial icon state |
| int numIcons = result.mIcons.size(); |
| for (int i = 0; i < numIcons; i++) { |
| mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i)); |
| } |
| |
| mAutoHideController.setStatusBar(new AutoHideUiElement() { |
| @Override |
| public void synchronizeState() { |
| // No op. |
| } |
| |
| @Override |
| public boolean isVisible() { |
| return mStatusBarTransientShown; |
| } |
| |
| @Override |
| public void hide() { |
| clearTransient(); |
| } |
| }); |
| |
| mAutoHideController.setNavigationBar(new AutoHideUiElement() { |
| @Override |
| public void synchronizeState() { |
| // No op. |
| } |
| |
| @Override |
| public boolean isVisible() { |
| return mNavBarTransientShown; |
| } |
| |
| @Override |
| public void hide() { |
| clearTransient(); |
| } |
| }); |
| |
| mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup(); |
| mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress(); |
| mCarDeviceProvisionedController.addCallback( |
| new CarDeviceProvisionedListener() { |
| @Override |
| public void onUserSetupInProgressChanged() { |
| mExecutor.execute(() -> restartNavBarsIfNecessary()); |
| } |
| |
| @Override |
| public void onUserSetupChanged() { |
| mExecutor.execute(() -> restartNavBarsIfNecessary()); |
| } |
| |
| @Override |
| public void onUserSwitched() { |
| mExecutor.execute(() -> restartNavBarsIfNecessary()); |
| } |
| }); |
| |
| createSystemBar(result); |
| |
| mActivityManagerWrapper = ActivityManagerWrapper.getInstance(); |
| mActivityManagerWrapper.registerTaskStackListener(mButtonSelectionStateListener); |
| mActivityManagerWrapper.registerTaskStackListener(new TaskStackChangeListener() { |
| @Override |
| public void onLockTaskModeChanged(int mode) { |
| mCarSystemBarController.refreshSystemBarByLockTaskFeatures(); |
| } |
| }); |
| |
| // Lastly, call to the icon policy to install/update all the icons. |
| // Must be called on the main thread due to the use of observeForever() in |
| // mIconPolicy.init(). |
| mExecutor.execute(() -> { |
| mIconPolicyLazy.get().init(); |
| }); |
| } |
| |
| private void restartNavBarsIfNecessary() { |
| boolean currentUserSetup = mCarDeviceProvisionedController.isCurrentUserSetup(); |
| boolean currentUserSetupInProgress = mCarDeviceProvisionedController |
| .isCurrentUserSetupInProgress(); |
| if (mIsUserSetupInProgress != currentUserSetupInProgress |
| || mDeviceIsSetUpForUser != currentUserSetup) { |
| mDeviceIsSetUpForUser = currentUserSetup; |
| mIsUserSetupInProgress = currentUserSetupInProgress; |
| restartNavBars(); |
| } |
| } |
| |
| /** |
| * Remove all content from navbars and rebuild them. Used to allow for different nav bars |
| * before and after the device is provisioned. . Also for change of density and font size. |
| */ |
| private void restartNavBars() { |
| // remove and reattach all components such that we don't keep a reference to unused ui |
| // elements |
| mCarSystemBarController.removeAll(); |
| |
| if (mTopSystemBarWindow != null) { |
| mTopSystemBarWindow.removeAllViews(); |
| mHvacController.unregisterViews(mTopSystemBarView); |
| mTopSystemBarView = null; |
| } |
| |
| if (mBottomSystemBarWindow != null) { |
| mBottomSystemBarWindow.removeAllViews(); |
| mHvacController.unregisterViews(mBottomSystemBarView); |
| mBottomSystemBarView = null; |
| } |
| |
| if (mLeftSystemBarWindow != null) { |
| mLeftSystemBarWindow.removeAllViews(); |
| mHvacController.unregisterViews(mLeftSystemBarView); |
| mLeftSystemBarView = null; |
| } |
| |
| if (mRightSystemBarWindow != null) { |
| mRightSystemBarWindow.removeAllViews(); |
| mHvacController.unregisterViews(mRightSystemBarView); |
| mRightSystemBarView = null; |
| } |
| |
| buildNavBarContent(); |
| // If the UI was rebuilt (day/night change or user change) while the keyguard was up we need |
| // to correctly respect that state. |
| if (mKeyguardStateControllerLazy.get().isShowing()) { |
| mCarSystemBarController.showAllKeyguardButtons(isDeviceSetupForUser()); |
| } else { |
| mCarSystemBarController.showAllNavigationButtons(isDeviceSetupForUser()); |
| } |
| |
| // Upon restarting the Navigation Bar, CarFacetButtonController should immediately apply the |
| // selection state that reflects the current task stack. |
| mButtonSelectionStateListener.onTaskStackChanged(); |
| } |
| |
| private boolean isDeviceSetupForUser() { |
| return mDeviceIsSetUpForUser && !mIsUserSetupInProgress; |
| } |
| |
| private void createSystemBar(RegisterStatusBarResult result) { |
| buildNavBarWindows(); |
| buildNavBarContent(); |
| attachNavBarWindows(); |
| |
| // Try setting up the initial state of the nav bar if applicable. |
| if (result != null) { |
| setImeWindowStatus(Display.DEFAULT_DISPLAY, result.mImeToken, |
| result.mImeWindowVis, result.mImeBackDisposition, |
| result.mShowImeSwitcher); |
| } |
| } |
| |
| private void buildNavBarWindows() { |
| mTopSystemBarWindow = mCarSystemBarController.getTopWindow(); |
| mBottomSystemBarWindow = mCarSystemBarController.getBottomWindow(); |
| mLeftSystemBarWindow = mCarSystemBarController.getLeftWindow(); |
| mRightSystemBarWindow = mCarSystemBarController.getRightWindow(); |
| } |
| |
| private void buildNavBarContent() { |
| mTopSystemBarView = mCarSystemBarController.getTopBar(isDeviceSetupForUser()); |
| if (mTopSystemBarView != null) { |
| mSystemBarConfigs.insetSystemBar(SystemBarConfigs.TOP, mTopSystemBarView); |
| mHvacController.registerHvacViews(mTopSystemBarView); |
| mTopSystemBarWindow.addView(mTopSystemBarView); |
| } |
| |
| mBottomSystemBarView = mCarSystemBarController.getBottomBar(isDeviceSetupForUser()); |
| if (mBottomSystemBarView != null) { |
| mSystemBarConfigs.insetSystemBar(SystemBarConfigs.BOTTOM, mBottomSystemBarView); |
| mHvacController.registerHvacViews(mBottomSystemBarView); |
| mBottomSystemBarWindow.addView(mBottomSystemBarView); |
| } |
| |
| mLeftSystemBarView = mCarSystemBarController.getLeftBar(isDeviceSetupForUser()); |
| if (mLeftSystemBarView != null) { |
| mSystemBarConfigs.insetSystemBar(SystemBarConfigs.LEFT, mLeftSystemBarView); |
| mHvacController.registerHvacViews(mLeftSystemBarView); |
| mLeftSystemBarWindow.addView(mLeftSystemBarView); |
| } |
| |
| mRightSystemBarView = mCarSystemBarController.getRightBar(isDeviceSetupForUser()); |
| if (mRightSystemBarView != null) { |
| mSystemBarConfigs.insetSystemBar(SystemBarConfigs.RIGHT, mRightSystemBarView); |
| mHvacController.registerHvacViews(mRightSystemBarView); |
| mRightSystemBarWindow.addView(mRightSystemBarView); |
| } |
| } |
| |
| private void attachNavBarWindows() { |
| mSystemBarConfigs.getSystemBarSidesByZOrder().forEach(this::attachNavBarBySide); |
| } |
| |
| private void attachNavBarBySide(int side) { |
| switch (side) { |
| case SystemBarConfigs.TOP: |
| if (mTopSystemBarWindow != null) { |
| mWindowManager.addView(mTopSystemBarWindow, |
| mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.TOP)); |
| } |
| break; |
| case SystemBarConfigs.BOTTOM: |
| if (mBottomSystemBarWindow != null && !mBottomNavBarVisible) { |
| mBottomNavBarVisible = true; |
| |
| mWindowManager.addView(mBottomSystemBarWindow, |
| mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.BOTTOM)); |
| } |
| break; |
| case SystemBarConfigs.LEFT: |
| if (mLeftSystemBarWindow != null) { |
| mWindowManager.addView(mLeftSystemBarWindow, |
| mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.LEFT)); |
| } |
| break; |
| case SystemBarConfigs.RIGHT: |
| if (mRightSystemBarWindow != null) { |
| mWindowManager.addView(mRightSystemBarWindow, |
| mSystemBarConfigs.getLayoutParamsBySide(SystemBarConfigs.RIGHT)); |
| } |
| break; |
| default: |
| return; |
| } |
| } |
| |
| /** |
| * We register for soft keyboard visibility events such that we can hide the navigation bar |
| * giving more screen space to the IME. Note: this is optional and controlled by |
| * {@code com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard}. |
| */ |
| @Override |
| public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition, |
| boolean showImeSwitcher) { |
| if (mContext.getDisplayId() != displayId) { |
| return; |
| } |
| |
| boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0; |
| |
| if (mHideTopBarForKeyboard) { |
| mCarSystemBarController.setTopWindowVisibility( |
| isKeyboardVisible ? View.GONE : View.VISIBLE); |
| } |
| |
| if (mHideBottomBarForKeyboard) { |
| mCarSystemBarController.setBottomWindowVisibility( |
| isKeyboardVisible ? View.GONE : View.VISIBLE); |
| } |
| |
| if (mHideLeftBarForKeyboard) { |
| mCarSystemBarController.setLeftWindowVisibility( |
| isKeyboardVisible ? View.GONE : View.VISIBLE); |
| } |
| if (mHideRightBarForKeyboard) { |
| mCarSystemBarController.setRightWindowVisibility( |
| isKeyboardVisible ? View.GONE : View.VISIBLE); |
| } |
| } |
| |
| @Override |
| public void onSystemBarAttributesChanged( |
| int displayId, |
| @WindowInsetsController.Appearance int appearance, |
| AppearanceRegion[] appearanceRegions, |
| boolean navbarColorManagedByIme, |
| @WindowInsetsController.Behavior int behavior, |
| InsetsVisibilities requestedVisibilities, |
| String packageName) { |
| if (displayId != mDisplayId) { |
| return; |
| } |
| boolean barModeChanged = updateStatusBarMode( |
| mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); |
| int numStacks = appearanceRegions.length; |
| boolean stackAppearancesChanged = mAppearanceRegions.length != numStacks; |
| for (int i = 0; i < numStacks && !stackAppearancesChanged; i++) { |
| stackAppearancesChanged |= !appearanceRegions[i].equals(mAppearanceRegions[i]); |
| } |
| if (stackAppearancesChanged || barModeChanged) { |
| mAppearanceRegions = appearanceRegions; |
| updateStatusBarAppearance(); |
| } |
| mCarSystemBarController.refreshSystemBarByLockTaskFeatures(); |
| } |
| |
| @Override |
| public void disable(int displayId, @DisableFlags int state1, @Disable2Flags int state2, |
| boolean animate) { |
| if (displayId != mDisplayId) { |
| return; |
| } |
| mCarSystemBarController.setStatusBarState(state1); |
| } |
| |
| private void updateStatusBarAppearance() { |
| int numStacks = mAppearanceRegions.length; |
| int numLightStacks = 0; |
| |
| // We can only have maximum one light stack. |
| int indexLightStack = -1; |
| |
| for (int i = 0; i < numStacks; i++) { |
| if (isLight(mAppearanceRegions[i].getAppearance())) { |
| numLightStacks++; |
| indexLightStack = i; |
| } |
| } |
| |
| // If all stacks are light, all icons become dark. |
| if (numLightStacks == numStacks) { |
| mStatusBarIconController.setIconsDarkArea(null); |
| mStatusBarIconController.getTransitionsController().setIconsDark( |
| /* dark= */ true, /* animate= */ false); |
| } else if (numLightStacks == 0) { |
| // If no one is light, all icons become white. |
| mStatusBarIconController.getTransitionsController().setIconsDark( |
| /* dark= */ false, /* animate= */ false); |
| } else { |
| // Not the same for every stack, update icons in area only. |
| mStatusBarIconController.setIconsDarkArea( |
| mAppearanceRegions[indexLightStack].getBounds()); |
| mStatusBarIconController.getTransitionsController().setIconsDark( |
| /* dark= */ true, /* animate= */ false); |
| } |
| } |
| |
| private static boolean isLight(int appearance) { |
| return (appearance & APPEARANCE_LIGHT_STATUS_BARS) != 0; |
| } |
| |
| @Override |
| public void showTransient(int displayId, int[] types) { |
| if (displayId != mDisplayId) { |
| return; |
| } |
| if (containsType(types, ITYPE_STATUS_BAR)) { |
| if (!mStatusBarTransientShown) { |
| mStatusBarTransientShown = true; |
| handleTransientChanged(); |
| } |
| } |
| if (containsType(types, ITYPE_NAVIGATION_BAR)) { |
| if (!mNavBarTransientShown) { |
| mNavBarTransientShown = true; |
| handleTransientChanged(); |
| } |
| } |
| } |
| |
| @Override |
| public void abortTransient(int displayId, int[] types) { |
| if (displayId != mDisplayId) { |
| return; |
| } |
| if (!containsType(types, ITYPE_STATUS_BAR) && !containsType(types, ITYPE_NAVIGATION_BAR)) { |
| return; |
| } |
| clearTransient(); |
| } |
| |
| private void clearTransient() { |
| if (mStatusBarTransientShown) { |
| mStatusBarTransientShown = false; |
| handleTransientChanged(); |
| } |
| if (mNavBarTransientShown) { |
| mNavBarTransientShown = false; |
| handleTransientChanged(); |
| } |
| } |
| |
| @VisibleForTesting |
| boolean isStatusBarTransientShown() { |
| return mStatusBarTransientShown; |
| } |
| |
| @VisibleForTesting |
| boolean isNavBarTransientShown() { |
| return mNavBarTransientShown; |
| } |
| |
| @VisibleForTesting |
| void setSignalPolicy(StatusBarSignalPolicy signalPolicy) { |
| mSignalPolicy = signalPolicy; |
| } |
| |
| @Override |
| public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { |
| pw.print(" mTaskStackListener="); |
| pw.println(mButtonSelectionStateListener); |
| pw.print(" mBottomSystemBarView="); |
| pw.println(mBottomSystemBarView); |
| } |
| |
| private void handleTransientChanged() { |
| updateStatusBarMode(mStatusBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); |
| updateNavBarMode(mNavBarTransientShown ? MODE_SEMI_TRANSPARENT : MODE_TRANSPARENT); |
| } |
| |
| // Returns true if the status bar mode has changed. |
| private boolean updateStatusBarMode(int barMode) { |
| if (mStatusBarMode != barMode) { |
| mStatusBarMode = barMode; |
| mAutoHideController.touchAutoHide(); |
| return true; |
| } |
| return false; |
| } |
| |
| // Returns true if the nav bar mode has changed. |
| private boolean updateNavBarMode(int barMode) { |
| if (mSystemBarMode != barMode) { |
| mSystemBarMode = barMode; |
| mAutoHideController.touchAutoHide(); |
| return true; |
| } |
| return false; |
| } |
| } |