blob: 663a4012c503d753e794b5f6fee8a3a3ccb44e60 [file] [log] [blame]
/*
* 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 android.annotation.LayoutRes;
import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.Context;
import android.os.Build;
import android.util.ArraySet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import androidx.annotation.IdRes;
import androidx.annotation.Nullable;
import com.android.car.ui.FocusParkingView;
import com.android.car.ui.utils.ViewUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.car.CarServiceProvider;
import com.android.systemui.car.hvac.HvacPanelOverlayViewController;
import com.android.systemui.car.privacy.CameraPrivacyElementsProviderImpl;
import com.android.systemui.car.privacy.MicPrivacyElementsProviderImpl;
import com.android.systemui.car.qc.SystemUIQCViewController;
import com.android.systemui.car.statusbar.UserNameViewController;
import com.android.systemui.car.statusicon.StatusIconPanelController;
import com.android.systemui.car.users.CarSystemUIUserUtil;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.ConfigurationController;
import dagger.Lazy;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Provider;
/** A single class which controls the navigation bar views. */
@SysUISingleton
public class CarSystemBarController {
private static final boolean DEBUG = Build.IS_ENG || Build.IS_USERDEBUG;
private static final String TAG = CarSystemBarController.class.getSimpleName();
private final Context mContext;
private final UserTracker mUserTracker;
private final CarSystemBarViewFactory mCarSystemBarViewFactory;
private final CarServiceProvider mCarServiceProvider;
private final BroadcastDispatcher mBroadcastDispatcher;
private final ConfigurationController mConfigurationController;
private final ButtonSelectionStateController mButtonSelectionStateController;
private final ButtonRoleHolderController mButtonRoleHolderController;
private final Provider<SystemUIQCViewController> mQCViewControllerProvider;
private final Lazy<UserNameViewController> mUserNameViewControllerLazy;
private final Lazy<MicPrivacyChipViewController> mMicPrivacyChipViewControllerLazy;
private final Lazy<CameraPrivacyChipViewController> mCameraPrivacyChipViewControllerLazy;
private final Lazy<MicPrivacyElementsProviderImpl> mMicPrivacyElementsProviderLazy;
private final Lazy<CameraPrivacyElementsProviderImpl> mCameraPrivacyElementsProviderLazy;
private final SystemBarConfigs mSystemBarConfigs;
private boolean mShowTop;
private boolean mShowBottom;
private boolean mShowLeft;
private boolean mShowRight;
private final int mPrivacyChipXOffset;
@IdRes
private int mTopFocusedViewId;
@IdRes
private int mBottomFocusedViewId;
@IdRes
private int mLeftFocusedViewId;
@IdRes
private int mRightFocusedViewId;
private final Set<View.OnTouchListener> mTopBarTouchListeners = new ArraySet<>();
private final Set<View.OnTouchListener> mBottomBarTouchListeners = new ArraySet<>();
private final Set<View.OnTouchListener> mLeftBarTouchListeners = new ArraySet<>();
private final Set<View.OnTouchListener> mRightBarTouchListeners = new ArraySet<>();
private NotificationsShadeController mNotificationsShadeController;
private HvacPanelController mHvacPanelController;
private StatusIconPanelController mMicPanelController;
private StatusIconPanelController mCameraPanelController;
private StatusIconPanelController mProfilePanelController;
private HvacPanelOverlayViewController mHvacPanelOverlayViewController;
private CarSystemBarView mTopView;
private CarSystemBarView mBottomView;
private CarSystemBarView mLeftView;
private CarSystemBarView mRightView;
// Saved StatusBarManager.DisableFlags
private int mStatusBarState;
// Saved StatusBarManager.Disable2Flags
private int mStatusBarState2;
private int mLockTaskMode;
@Inject
public CarSystemBarController(Context context,
UserTracker userTracker,
CarSystemBarViewFactory carSystemBarViewFactory,
CarServiceProvider carServiceProvider,
BroadcastDispatcher broadcastDispatcher,
ConfigurationController configurationController,
ButtonSelectionStateController buttonSelectionStateController,
Lazy<UserNameViewController> userNameViewControllerLazy,
Lazy<MicPrivacyChipViewController> micPrivacyChipViewControllerLazy,
Lazy<CameraPrivacyChipViewController> cameraPrivacyChipViewControllerLazy,
ButtonRoleHolderController buttonRoleHolderController,
SystemBarConfigs systemBarConfigs,
Provider<SystemUIQCViewController> qcViewControllerProvider,
Lazy<MicPrivacyElementsProviderImpl> micPrivacyElementsProvider,
Lazy<CameraPrivacyElementsProviderImpl> cameraPrivacyElementsProvider) {
mContext = context;
mUserTracker = userTracker;
mCarSystemBarViewFactory = carSystemBarViewFactory;
mCarServiceProvider = carServiceProvider;
mBroadcastDispatcher = broadcastDispatcher;
mConfigurationController = configurationController;
mButtonSelectionStateController = buttonSelectionStateController;
mUserNameViewControllerLazy = userNameViewControllerLazy;
mMicPrivacyChipViewControllerLazy = micPrivacyChipViewControllerLazy;
mCameraPrivacyChipViewControllerLazy = cameraPrivacyChipViewControllerLazy;
mButtonRoleHolderController = buttonRoleHolderController;
mQCViewControllerProvider = qcViewControllerProvider;
mMicPrivacyElementsProviderLazy = micPrivacyElementsProvider;
mCameraPrivacyElementsProviderLazy = cameraPrivacyElementsProvider;
mSystemBarConfigs = systemBarConfigs;
// Read configuration.
readConfigs();
mPrivacyChipXOffset = -context.getResources()
.getDimensionPixelOffset(R.dimen.privacy_chip_horizontal_padding);
}
/**
* Invalidate SystemBarConfigs and fetch again from Resources.
* TODO(): b/260206944, Can remove this after we have a fix for overlaid resources not applied.
*/
void resetSystemBarConfigs() {
mSystemBarConfigs.resetSystemBarConfigs();
mCarSystemBarViewFactory.resetCache();
readConfigs();
}
private void readConfigs() {
mShowTop = mSystemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.TOP);
mShowBottom = mSystemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.BOTTOM);
mShowLeft = mSystemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.LEFT);
mShowRight = mSystemBarConfigs.getEnabledStatusBySide(SystemBarConfigs.RIGHT);
}
/**
* Hides all system bars.
*/
public void hideBars() {
setTopWindowVisibility(View.GONE);
setBottomWindowVisibility(View.GONE);
setLeftWindowVisibility(View.GONE);
setRightWindowVisibility(View.GONE);
}
/**
* Shows all system bars.
*/
public void showBars() {
setTopWindowVisibility(View.VISIBLE);
setBottomWindowVisibility(View.VISIBLE);
setLeftWindowVisibility(View.VISIBLE);
setRightWindowVisibility(View.VISIBLE);
}
/** Clean up */
public void removeAll() {
mButtonSelectionStateController.removeAll();
mButtonRoleHolderController.removeAll();
mUserNameViewControllerLazy.get().removeAll();
mMicPrivacyChipViewControllerLazy.get().removeAll();
mCameraPrivacyChipViewControllerLazy.get().removeAll();
if (mMicPanelController != null) {
mMicPanelController.destroyPanel();
}
if (mCameraPanelController != null) {
mCameraPanelController.destroyPanel();
}
if (mProfilePanelController != null) {
mProfilePanelController.destroyPanel();
}
mMicPanelController = null;
mCameraPanelController = null;
mProfilePanelController = null;
}
/** Gets the top window if configured to do so. */
@Nullable
public ViewGroup getTopWindow() {
return mShowTop ? mCarSystemBarViewFactory.getTopWindow() : null;
}
/** Gets the bottom window if configured to do so. */
@Nullable
public ViewGroup getBottomWindow() {
return mShowBottom ? mCarSystemBarViewFactory.getBottomWindow() : null;
}
/** Gets the left window if configured to do so. */
@Nullable
public ViewGroup getLeftWindow() {
return mShowLeft ? mCarSystemBarViewFactory.getLeftWindow() : null;
}
/** Gets the right window if configured to do so. */
@Nullable
public ViewGroup getRightWindow() {
return mShowRight ? mCarSystemBarViewFactory.getRightWindow() : null;
}
/** Toggles the top nav bar visibility. */
public boolean setTopWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getTopWindow(), visibility);
}
/** Toggles the bottom nav bar visibility. */
public boolean setBottomWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getBottomWindow(), visibility);
}
/** Toggles the left nav bar visibility. */
public boolean setLeftWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getLeftWindow(), visibility);
}
/** Toggles the right nav bar visibility. */
public boolean setRightWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getRightWindow(), visibility);
}
private boolean setWindowVisibility(ViewGroup window, @View.Visibility int visibility) {
if (window == null) {
return false;
}
if (window.getVisibility() == visibility) {
return false;
}
window.setVisibility(visibility);
return true;
}
/**
* Sets the system bar states - {@code StatusBarManager.DisableFlags},
* {@code StatusBarManager.Disable2Flags}, lock task mode. When there is a change in state,
* and refreshes the system bars.
*
* @param state {@code StatusBarManager.DisableFlags}
* @param state2 {@code StatusBarManager.Disable2Flags}
*/
public void setSystemBarStates(int state, int state2) {
int diff = (state ^ mStatusBarState) | (state2 ^ mStatusBarState2);
int lockTaskMode = getLockTaskModeState();
if (diff == 0 && mLockTaskMode == lockTaskMode) {
if (DEBUG) {
Log.d(TAG, "setSystemBarStates(): status bar states unchanged: state: "
+ state + " state2: " + state2 + " lockTaskMode: " + mLockTaskMode);
}
return;
}
mStatusBarState = state;
mStatusBarState2 = state2;
mLockTaskMode = lockTaskMode;
refreshSystemBar();
}
@VisibleForTesting
protected int getStatusBarState() {
return mStatusBarState;
}
@VisibleForTesting
protected int getStatusBarState2() {
return mStatusBarState2;
}
@VisibleForTesting
protected int getLockTaskMode() {
return mLockTaskMode;
}
/**
* Refreshes system bar views and sets the visibility of certain components based on
* {@link StatusBarManager} flags and lock task mode.
* <ul>
* <li>Home button will be disabled when {@code StatusBarManager.DISABLE_HOME} is set.
* <li>Phone call button will be disable in lock task mode.
* <li>App grid button will be disable when {@code StatusBarManager.DISABLE_HOME} is set.
* <li>Notification button will be disable when
* {@code StatusBarManager.DISABLE_NOTIFICATION_ICONS} is set.
* <li>Quick settings and user switcher will be hidden when in lock task mode or when
* {@code StatusBarManager.DISABLE2_QUICK_SETTINGS} is set.
* </ul>
*/
public void refreshSystemBar() {
boolean homeDisabled = ((mStatusBarState & StatusBarManager.DISABLE_HOME) > 0);
boolean notificationDisabled =
((mStatusBarState & StatusBarManager.DISABLE_NOTIFICATION_ICONS) > 0);
boolean locked = (mLockTaskMode == ActivityManager.LOCK_TASK_MODE_LOCKED);
boolean qcDisabled =
((mStatusBarState2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) > 0) || locked;
boolean systemIconsDisabled =
((mStatusBarState2 & StatusBarManager.DISABLE2_SYSTEM_ICONS) > 0) || locked;
setDisabledSystemBarButton(R.id.home, homeDisabled, "home");
setDisabledSystemBarButton(R.id.passenger_home, homeDisabled, "passenger_home");
setDisabledSystemBarButton(R.id.phone_nav, locked, "phone_nav");
setDisabledSystemBarButton(R.id.grid_nav, homeDisabled, "grid_nav");
setDisabledSystemBarButton(R.id.notifications, notificationDisabled, "notifications");
setDisabledSystemBarContainer(R.id.qc_entry_points_container, qcDisabled,
"qc_entry_points_container");
setDisabledSystemBarContainer(R.id.user_name_container, qcDisabled,
"user_name_container");
setDisabledSystemBarContainer(R.id.read_only_icons_container, systemIconsDisabled,
"read_only_icons_container");
if (DEBUG) {
Log.d(TAG, "refreshSystemBar: locked?: " + locked
+ " homeDisabled: " + homeDisabled
+ " notificationDisabled: " + notificationDisabled
+ " qcDisabled: " + qcDisabled
+ " systemIconsDisabled: " + systemIconsDisabled);
}
}
private int getLockTaskModeState() {
return mContext.getSystemService(ActivityManager.class).getLockTaskModeState();
}
private void setDisabledSystemBarButton(int viewId, boolean disabled,
@Nullable String buttonName) {
for (CarSystemBarView barView : getAllAvailableSystemBarViews()) {
barView.setDisabledSystemBarButton(viewId, disabled,
() -> showAdminSupportDetailsDialog(), buttonName);
}
}
private void setDisabledSystemBarContainer(int viewId, boolean disabled,
@Nullable String viewName) {
for (CarSystemBarView barView : getAllAvailableSystemBarViews()) {
barView.setVisibilityByViewId(viewId, viewName,
disabled ? View.INVISIBLE : View.VISIBLE);
}
}
private void showAdminSupportDetailsDialog() {
// TODO(b/205891123): launch AdminSupportDetailsDialog after moving
// AdminSupportDetailsDialog out of CarSettings since CarSettings is not and should not
// be allowlisted for lock task mode.
Toast.makeText(mContext, "This action is unavailable for your profile",
Toast.LENGTH_LONG).show();
}
/** Gets the top navigation bar with the appropriate listeners set. */
@Nullable
public CarSystemBarView getTopBar(boolean isSetUp) {
if (!mShowTop) {
return null;
}
mTopView = mCarSystemBarViewFactory.getTopBar(isSetUp);
setupBar(mTopView, mTopBarTouchListeners, mNotificationsShadeController,
mHvacPanelController, mHvacPanelOverlayViewController);
if (isSetUp) {
// We do not want the privacy chips or the profile picker to be clickable in
// unprovisioned mode.
mMicPanelController = setupSensorQcPanel(mMicPanelController, R.id.mic_privacy_chip,
R.layout.qc_mic_panel);
mCameraPanelController = setupSensorQcPanel(mCameraPanelController,
R.id.camera_privacy_chip, R.layout.qc_camera_panel);
setupProfilePanel();
}
return mTopView;
}
/** Gets the bottom navigation bar with the appropriate listeners set. */
@Nullable
public CarSystemBarView getBottomBar(boolean isSetUp) {
if (!mShowBottom) {
return null;
}
mBottomView = mCarSystemBarViewFactory.getBottomBar(isSetUp);
setupBar(mBottomView, mBottomBarTouchListeners, mNotificationsShadeController,
mHvacPanelController, mHvacPanelOverlayViewController);
return mBottomView;
}
/** Gets the left navigation bar with the appropriate listeners set. */
@Nullable
public CarSystemBarView getLeftBar(boolean isSetUp) {
if (!mShowLeft) {
return null;
}
mLeftView = mCarSystemBarViewFactory.getLeftBar(isSetUp);
setupBar(mLeftView, mLeftBarTouchListeners, mNotificationsShadeController,
mHvacPanelController, mHvacPanelOverlayViewController);
return mLeftView;
}
/** Gets the right navigation bar with the appropriate listeners set. */
@Nullable
public CarSystemBarView getRightBar(boolean isSetUp) {
if (!mShowRight) {
return null;
}
mRightView = mCarSystemBarViewFactory.getRightBar(isSetUp);
setupBar(mRightView, mRightBarTouchListeners, mNotificationsShadeController,
mHvacPanelController, mHvacPanelOverlayViewController);
return mRightView;
}
private void setupBar(CarSystemBarView view, Set<View.OnTouchListener> statusBarTouchListeners,
NotificationsShadeController notifShadeController,
HvacPanelController hvacPanelController,
HvacPanelOverlayViewController hvacPanelOverlayViewController) {
view.updateHomeButtonVisibility(CarSystemUIUserUtil.isSecondaryMUMDSystemUI());
view.setStatusBarWindowTouchListeners(statusBarTouchListeners);
view.setNotificationsPanelController(notifShadeController);
view.setHvacPanelController(hvacPanelController);
view.registerHvacPanelOverlayViewController(hvacPanelOverlayViewController);
view.updateControlCenterButtonVisibility(CarSystemUIUserUtil.isMUMDSystemUI());
mButtonSelectionStateController.addAllButtonsWithSelectionState(view);
mButtonRoleHolderController.addAllButtonsWithRoleName(view);
mUserNameViewControllerLazy.get().addUserNameView(view);
mMicPrivacyChipViewControllerLazy.get().addPrivacyChipView(view);
mCameraPrivacyChipViewControllerLazy.get().addPrivacyChipView(view);
}
private StatusIconPanelController setupSensorQcPanel(
@Nullable StatusIconPanelController panelController, int chipId,
@LayoutRes int panelLayoutRes) {
if (panelController == null) {
panelController = new StatusIconPanelController(mContext, mUserTracker,
mCarServiceProvider, mBroadcastDispatcher, mConfigurationController,
mQCViewControllerProvider);
panelController.attachPanel(mTopView.requireViewById(chipId), panelLayoutRes,
R.dimen.car_sensor_qc_panel_width, mPrivacyChipXOffset,
panelController.getDefaultYOffset(), Gravity.TOP | Gravity.END);
}
return panelController;
}
private void setupProfilePanel() {
View profilePickerView = mTopView.findViewById(R.id.user_name);
if (mProfilePanelController == null && profilePickerView != null) {
boolean profilePanelDisabledWhileDriving = mContext.getResources().getBoolean(
R.bool.config_profile_panel_disabled_while_driving);
mProfilePanelController = new StatusIconPanelController(mContext, mUserTracker,
mCarServiceProvider, mBroadcastDispatcher, mConfigurationController,
mQCViewControllerProvider, profilePanelDisabledWhileDriving);
mProfilePanelController.attachPanel(profilePickerView, R.layout.qc_profile_switcher,
R.dimen.car_profile_quick_controls_panel_width, Gravity.TOP | Gravity.END);
}
}
/** Sets a touch listener for the top navigation bar. */
public void registerTopBarTouchListener(View.OnTouchListener listener) {
boolean setModified = mTopBarTouchListeners.add(listener);
if (setModified && mTopView != null) {
mTopView.setStatusBarWindowTouchListeners(mTopBarTouchListeners);
}
}
/** Sets a touch listener for the bottom navigation bar. */
public void registerBottomBarTouchListener(View.OnTouchListener listener) {
boolean setModified = mBottomBarTouchListeners.add(listener);
if (setModified && mBottomView != null) {
mBottomView.setStatusBarWindowTouchListeners(mBottomBarTouchListeners);
}
}
/** Sets a touch listener for the left navigation bar. */
public void registerLeftBarTouchListener(View.OnTouchListener listener) {
boolean setModified = mLeftBarTouchListeners.add(listener);
if (setModified && mLeftView != null) {
mLeftView.setStatusBarWindowTouchListeners(mLeftBarTouchListeners);
}
}
/** Sets a touch listener for the right navigation bar. */
public void registerRightBarTouchListener(View.OnTouchListener listener) {
boolean setModified = mRightBarTouchListeners.add(listener);
if (setModified && mRightView != null) {
mRightView.setStatusBarWindowTouchListeners(mRightBarTouchListeners);
}
}
/** Sets a notification controller which toggles the notification panel. */
public void registerNotificationController(
NotificationsShadeController notificationsShadeController) {
mNotificationsShadeController = notificationsShadeController;
if (mTopView != null) {
mTopView.setNotificationsPanelController(mNotificationsShadeController);
}
if (mBottomView != null) {
mBottomView.setNotificationsPanelController(mNotificationsShadeController);
}
if (mLeftView != null) {
mLeftView.setNotificationsPanelController(mNotificationsShadeController);
}
if (mRightView != null) {
mRightView.setNotificationsPanelController(mNotificationsShadeController);
}
}
/** Sets an HVAC controller which toggles the HVAC panel. */
public void registerHvacPanelController(HvacPanelController hvacPanelController) {
mHvacPanelController = hvacPanelController;
if (mTopView != null) {
mTopView.setHvacPanelController(mHvacPanelController);
}
if (mBottomView != null) {
mBottomView.setHvacPanelController(mHvacPanelController);
}
if (mLeftView != null) {
mLeftView.setHvacPanelController(mHvacPanelController);
}
if (mRightView != null) {
mRightView.setHvacPanelController(mHvacPanelController);
}
}
/** Sets the HVACPanelOverlayViewController for views to listen to the panel's state. */
public void registerHvacPanelOverlayViewController(
HvacPanelOverlayViewController hvacPanelOverlayViewController) {
mHvacPanelOverlayViewController = hvacPanelOverlayViewController;
if (mTopView != null) {
mTopView.registerHvacPanelOverlayViewController(mHvacPanelOverlayViewController);
}
if (mBottomView != null) {
mBottomView.registerHvacPanelOverlayViewController(mHvacPanelOverlayViewController);
}
if (mLeftView != null) {
mLeftView.registerHvacPanelOverlayViewController(mHvacPanelOverlayViewController);
}
if (mRightView != null) {
mRightView.registerHvacPanelOverlayViewController(mHvacPanelOverlayViewController);
}
}
/**
* Shows all of the navigation buttons on the valid instances of {@link CarSystemBarView}.
*/
public void showAllNavigationButtons(boolean isSetUp) {
checkAllBars(isSetUp);
if (mTopView != null) {
mTopView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_NAVIGATION);
}
if (mBottomView != null) {
mBottomView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_NAVIGATION);
}
if (mLeftView != null) {
mLeftView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_NAVIGATION);
}
if (mRightView != null) {
mRightView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_NAVIGATION);
}
}
/**
* Shows all of the keyguard specific buttons on the valid instances of
* {@link CarSystemBarView}.
*/
public void showAllKeyguardButtons(boolean isSetUp) {
checkAllBars(isSetUp);
if (mTopView != null) {
mTopView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_KEYGUARD);
}
if (mBottomView != null) {
mBottomView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_KEYGUARD);
}
if (mLeftView != null) {
mLeftView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_KEYGUARD);
}
if (mRightView != null) {
mRightView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_KEYGUARD);
}
}
/**
* Shows all of the occlusion state buttons on the valid instances of
* {@link CarSystemBarView}.
*/
public void showAllOcclusionButtons(boolean isSetUp) {
checkAllBars(isSetUp);
if (mTopView != null) {
mTopView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_OCCLUSION);
}
if (mBottomView != null) {
mBottomView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_OCCLUSION);
}
if (mLeftView != null) {
mLeftView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_OCCLUSION);
}
if (mRightView != null) {
mRightView.showButtonsOfType(CarSystemBarView.BUTTON_TYPE_OCCLUSION);
}
}
/** Toggles whether the notifications icon has an unseen indicator or not. */
public void toggleAllNotificationsUnseenIndicator(boolean isSetUp, boolean hasUnseen) {
checkAllBars(isSetUp);
if (mTopView != null) {
mTopView.toggleNotificationUnseenIndicator(hasUnseen);
}
if (mBottomView != null) {
mBottomView.toggleNotificationUnseenIndicator(hasUnseen);
}
if (mLeftView != null) {
mLeftView.toggleNotificationUnseenIndicator(hasUnseen);
}
if (mRightView != null) {
mRightView.toggleNotificationUnseenIndicator(hasUnseen);
}
}
/** Interface for controlling the notifications shade. */
public interface NotificationsShadeController {
/** Toggles the visibility of the notifications shade. */
void togglePanel();
/** Returns {@code true} if the panel is open. */
boolean isNotificationPanelOpen();
}
/** Interface for controlling the HVAC panel. */
public interface HvacPanelController {
/** Toggles the visibility of the HVAC shade. */
void togglePanel();
/** Returns {@code true} if the panel is open. */
boolean isHvacPanelOpen();
}
private void checkAllBars(boolean isSetUp) {
mTopView = getTopBar(isSetUp);
mBottomView = getBottomBar(isSetUp);
mLeftView = getLeftBar(isSetUp);
mRightView = getRightBar(isSetUp);
}
private List<CarSystemBarView> getAllAvailableSystemBarViews() {
List<CarSystemBarView> barViews = new ArrayList<>();
if (mTopView != null) {
barViews.add(mTopView);
}
if (mBottomView != null) {
barViews.add(mBottomView);
}
if (mLeftView != null) {
barViews.add(mLeftView);
}
if (mRightView != null) {
barViews.add(mRightView);
}
return barViews;
}
/** Gets the selected Quick Controls class name. */
protected String getSelectedQuickControlsClassName() {
return mCarSystemBarViewFactory.getSelectedQuickControlsClassName();
}
/** Calls onClick for the given Quick Controls class name. */
protected void callQuickControlsOnClickFromClassName(String clsName) {
mCarSystemBarViewFactory.callQuickControlsOnClickFromClassName(clsName);
}
/** Resets the cached Views. */
protected void resetCache() {
mCarSystemBarViewFactory.resetCache();
}
/** Stores the ID of the View that is currently focused and hides the focus. */
protected void cacheAndHideFocus() {
mTopFocusedViewId = cacheAndHideFocus(mTopView);
if (mTopFocusedViewId != View.NO_ID) return;
mBottomFocusedViewId = cacheAndHideFocus(mBottomView);
if (mBottomFocusedViewId != View.NO_ID) return;
mLeftFocusedViewId = cacheAndHideFocus(mLeftView);
if (mLeftFocusedViewId != View.NO_ID) return;
mRightFocusedViewId = cacheAndHideFocus(mRightView);
}
@VisibleForTesting
int cacheAndHideFocus(@Nullable View rootView) {
if (rootView == null) return View.NO_ID;
View focusedView = rootView.findFocus();
if (focusedView == null || focusedView instanceof FocusParkingView) return View.NO_ID;
int focusedViewId = focusedView.getId();
ViewUtils.hideFocus(rootView);
return focusedViewId;
}
/** Requests focus on the View that matches the cached ID. */
protected void restoreFocus() {
if (restoreFocus(mTopView, mTopFocusedViewId)) return;
if (restoreFocus(mBottomView, mBottomFocusedViewId)) return;
if (restoreFocus(mLeftView, mLeftFocusedViewId)) return;
restoreFocus(mRightView, mRightFocusedViewId);
}
private boolean restoreFocus(@Nullable View rootView, @IdRes int viewToFocusId) {
if (rootView == null || viewToFocusId == View.NO_ID) return false;
View focusedView = rootView.findViewById(viewToFocusId);
if (focusedView == null) return false;
focusedView.requestFocus();
return true;
}
}