blob: e2eb3fb5ddc66de27a6b9cad455e2bb8b0df5911 [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.statusbar;
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.annotation.Nullable;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.PowerManager;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.RegisterStatusBarResult;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.BatteryMeterView;
import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedListener;
import com.android.systemui.car.bluetooth.CarBatteryController;
import com.android.systemui.car.navigationbar.CarNavigationBarController;
import com.android.systemui.classifier.FalsingLog;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.fragments.FragmentHostManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.ScreenPinningRequest;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.stackdivider.Divider;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationViewHierarchyManager;
import com.android.systemui.statusbar.PulseExpansionHandler;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.DozeScrimController;
import com.android.systemui.statusbar.phone.DozeServiceHost;
import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightsOutNotifController;
import com.android.systemui.statusbar.phone.LockscreenLockIconController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarIconController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ExtensionController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.volume.VolumeComponent;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.Executor;
import javax.inject.Named;
import javax.inject.Provider;
import dagger.Lazy;
/**
* A status bar tailored for the automotive use case.
*/
public class CarStatusBar extends StatusBar implements CarBatteryController.BatteryViewHandler {
private static final String TAG = "CarStatusBar";
private final UserSwitcherController mUserSwitcherController;
private final ScrimController mScrimController;
private CarBatteryController mCarBatteryController;
private BatteryMeterView mBatteryMeterView;
private Drawable mNotificationPanelBackground;
private final Object mQueueLock = new Object();
private final CarNavigationBarController mCarNavigationBarController;
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final ScreenLifecycle mScreenLifecycle;
private boolean mDeviceIsSetUpForUser = true;
private boolean mIsUserSetupInProgress = false;
public CarStatusBar(
Context context,
NotificationsController notificationsController,
LightBarController lightBarController,
AutoHideController autoHideController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarIconController statusBarIconController,
PulseExpansionHandler pulseExpansionHandler,
NotificationWakeUpCoordinator notificationWakeUpCoordinator,
KeyguardBypassController keyguardBypassController,
KeyguardStateController keyguardStateController,
HeadsUpManagerPhone headsUpManagerPhone,
DynamicPrivacyController dynamicPrivacyController,
BypassHeadsUpNotifier bypassHeadsUpNotifier,
FalsingManager falsingManager,
BroadcastDispatcher broadcastDispatcher,
RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
NotificationGutsManager notificationGutsManager,
NotificationLogger notificationLogger,
NotificationInterruptStateProvider notificationInterruptStateProvider,
NotificationViewHierarchyManager notificationViewHierarchyManager,
KeyguardViewMediator keyguardViewMediator,
DisplayMetrics displayMetrics,
MetricsLogger metricsLogger,
@UiBackground Executor uiBgExecutor,
@Main Executor mainExecutor,
NotificationMediaManager notificationMediaManager,
NotificationLockscreenUserManager lockScreenUserManager,
NotificationRemoteInputManager remoteInputManager,
UserSwitcherController userSwitcherController,
NetworkController networkController,
BatteryController batteryController,
SysuiColorExtractor colorExtractor,
ScreenLifecycle screenLifecycle,
WakefulnessLifecycle wakefulnessLifecycle,
SysuiStatusBarStateController statusBarStateController,
VibratorHelper vibratorHelper,
BubbleController bubbleController,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
CarDeviceProvisionedController carDeviceProvisionedController,
NavigationBarController navigationBarController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
NotificationShadeWindowController notificationShadeWindowController,
LockscreenLockIconController lockscreenLockIconController,
DozeParameters dozeParameters,
ScrimController scrimController,
Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
DozeServiceHost dozeServiceHost,
PowerManager powerManager,
ScreenPinningRequest screenPinningRequest,
DozeScrimController dozeScrimController,
VolumeComponent volumeComponent,
CommandQueue commandQueue,
Optional<Recents> recents,
Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
PluginManager pluginManager,
Optional<Divider> dividerOptional,
SuperStatusBarViewFactory superStatusBarViewFactory,
LightsOutNotifController lightsOutNotifController,
StatusBarNotificationActivityStarter.Builder
statusBarNotificationActivityStarterBuilder,
ShadeController shadeController,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
ViewMediatorCallback viewMediatorCallback,
InitController initController,
DarkIconDispatcher darkIconDispatcher,
@Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
PluginDependencyProvider pluginDependencyProvider,
KeyguardDismissUtil keyguardDismissUtil,
ExtensionController extensionController,
UserInfoControllerImpl userInfoControllerImpl,
PhoneStatusBarPolicy phoneStatusBarPolicy,
KeyguardIndicationController keyguardIndicationController,
DismissCallbackRegistry dismissCallbackRegistry,
StatusBarTouchableRegionManager statusBarTouchableRegionManager,
Lazy<NotificationShadeDepthController> depthControllerLazy,
/* Car Settings injected components. */
CarNavigationBarController carNavigationBarController) {
super(
context,
notificationsController,
lightBarController,
autoHideController,
keyguardUpdateMonitor,
statusBarIconController,
pulseExpansionHandler,
notificationWakeUpCoordinator,
keyguardBypassController,
keyguardStateController,
headsUpManagerPhone,
dynamicPrivacyController,
bypassHeadsUpNotifier,
falsingManager,
broadcastDispatcher,
remoteInputQuickSettingsDisabler,
notificationGutsManager,
notificationLogger,
notificationInterruptStateProvider,
notificationViewHierarchyManager,
keyguardViewMediator,
displayMetrics,
metricsLogger,
uiBgExecutor,
mainExecutor,
notificationMediaManager,
lockScreenUserManager,
remoteInputManager,
userSwitcherController,
networkController,
batteryController,
colorExtractor,
screenLifecycle,
wakefulnessLifecycle,
statusBarStateController,
vibratorHelper,
bubbleController,
groupManager,
visualStabilityManager,
carDeviceProvisionedController,
navigationBarController,
assistManagerLazy,
configurationController,
notificationShadeWindowController,
lockscreenLockIconController,
dozeParameters,
scrimController,
null /* keyguardLiftController */,
lockscreenWallpaperLazy,
biometricUnlockControllerLazy,
dozeServiceHost,
powerManager,
screenPinningRequest,
dozeScrimController,
volumeComponent,
commandQueue,
recents,
statusBarComponentBuilder,
pluginManager,
dividerOptional,
lightsOutNotifController,
statusBarNotificationActivityStarterBuilder,
shadeController,
superStatusBarViewFactory,
statusBarKeyguardViewManager,
viewMediatorCallback,
initController,
darkIconDispatcher,
timeTickHandler,
pluginDependencyProvider,
keyguardDismissUtil,
extensionController,
userInfoControllerImpl,
phoneStatusBarPolicy,
keyguardIndicationController,
dismissCallbackRegistry,
depthControllerLazy,
statusBarTouchableRegionManager);
mUserSwitcherController = userSwitcherController;
mScrimController = scrimController;
mCarDeviceProvisionedController = carDeviceProvisionedController;
mCarNavigationBarController = carNavigationBarController;
mScreenLifecycle = screenLifecycle;
}
@Override
public void start() {
mDeviceIsSetUpForUser = mCarDeviceProvisionedController.isCurrentUserSetup();
mIsUserSetupInProgress = mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
super.start();
createBatteryController();
mCarBatteryController.startListening();
mCarDeviceProvisionedController.addCallback(
new CarDeviceProvisionedListener() {
@Override
public void onUserSetupInProgressChanged() {
mDeviceIsSetUpForUser = mCarDeviceProvisionedController
.isCurrentUserSetup();
mIsUserSetupInProgress = mCarDeviceProvisionedController
.isCurrentUserSetupInProgress();
}
@Override
public void onUserSetupChanged() {
mDeviceIsSetUpForUser = mCarDeviceProvisionedController
.isCurrentUserSetup();
mIsUserSetupInProgress = mCarDeviceProvisionedController
.isCurrentUserSetupInProgress();
}
@Override
public void onUserSwitched() {
mDeviceIsSetUpForUser = mCarDeviceProvisionedController
.isCurrentUserSetup();
mIsUserSetupInProgress = mCarDeviceProvisionedController
.isCurrentUserSetupInProgress();
}
});
mNotificationInterruptStateProvider.addSuppressor(new NotificationInterruptSuppressor() {
@Override
public String getName() {
return TAG;
}
@Override
public boolean suppressInterruptions(NotificationEntry entry) {
// Because space is usually constrained in the auto use-case, there should not be a
// pinned notification when the shade has been expanded.
// Ensure this by not allowing any interruptions (ie: pinning any notifications) if
// the shade is already opened.
return !getPresenter().isPresenterFullyCollapsed();
}
});
}
@Override
public boolean hideKeyguard() {
boolean result = super.hideKeyguard();
mCarNavigationBarController.hideAllKeyguardButtons(isDeviceSetupForUser());
return result;
}
@Override
public void showKeyguard() {
super.showKeyguard();
mCarNavigationBarController.showAllKeyguardButtons(isDeviceSetupForUser());
}
private boolean isDeviceSetupForUser() {
return mDeviceIsSetUpForUser && !mIsUserSetupInProgress;
}
@Override
protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
super.makeStatusBarView(result);
mNotificationPanelBackground = getDefaultWallpaper();
mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
FragmentHostManager manager = FragmentHostManager.get(mPhoneStatusBarWindow);
manager.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
mBatteryMeterView = fragment.getView().findViewById(R.id.battery);
// By default, the BatteryMeterView should not be visible. It will be toggled
// when a device has connected by bluetooth.
mBatteryMeterView.setVisibility(View.GONE);
});
}
@Override
public void animateExpandNotificationsPanel() {
// No op.
}
@Override
protected QS createDefaultQSFragment() {
return null;
}
private BatteryController createBatteryController() {
mCarBatteryController = new CarBatteryController(mContext);
mCarBatteryController.addBatteryViewHandler(this);
return mCarBatteryController;
}
@Override
protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
// No op.
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
//When executing dump() function simultaneously, we need to serialize them
//to get mStackScroller's position correctly.
synchronized (mQueueLock) {
pw.println(" mStackScroller: " + viewInfo(mStackScroller));
pw.println(" mStackScroller: " + viewInfo(mStackScroller)
+ " scroll " + mStackScroller.getScrollX()
+ "," + mStackScroller.getScrollY());
}
pw.print(" mCarBatteryController=");
pw.println(mCarBatteryController);
pw.print(" mBatteryMeterView=");
pw.println(mBatteryMeterView);
if (Dependency.get(KeyguardUpdateMonitor.class) != null) {
Dependency.get(KeyguardUpdateMonitor.class).dump(fd, pw, args);
}
FalsingLog.dump(pw);
pw.println("SharedPreferences:");
for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
pw.print(" ");
pw.print(entry.getKey());
pw.print("=");
pw.println(entry.getValue());
}
}
@Override
public void showBatteryView() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "showBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
}
if (mBatteryMeterView != null) {
mBatteryMeterView.setVisibility(View.VISIBLE);
}
}
@Override
public void hideBatteryView() {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "hideBatteryView(). mBatteryMeterView: " + mBatteryMeterView);
}
if (mBatteryMeterView != null) {
mBatteryMeterView.setVisibility(View.GONE);
}
}
@Override
protected void createUserSwitcher() {
if (!mUserSwitcherController.useFullscreenUserSwitcher()) {
super.createUserSwitcher();
}
}
/**
* Dismisses the keyguard and shows bouncer if authentication is necessary.
*/
public void dismissKeyguard() {
// Don't dismiss keyguard when the screen is off.
if (mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF) {
return;
}
executeRunnableDismissingKeyguard(null/* runnable */, null /* cancelAction */,
true /* dismissShade */, true /* afterKeyguardGone */, true /* deferred */);
}
/**
* Ensures that relevant child views are appropriately recreated when the device's density
* changes.
*/
@Override
public void onDensityOrFontScaleChanged() {
super.onDensityOrFontScaleChanged();
// Need to update the background on density changed in case the change was due to night
// mode.
mNotificationPanelBackground = getDefaultWallpaper();
mScrimController.setScrimBehindDrawable(mNotificationPanelBackground);
}
/**
* Returns the {@link Drawable} that represents the wallpaper that the user has currently set.
*/
private Drawable getDefaultWallpaper() {
return mContext.getDrawable(com.android.internal.R.drawable.default_wallpaper);
}
}