DO NOT MERGE Move Heads Up Notifications to their own window
Bug: 146901166 Test: manual, unit test Change-Id: I064cdf9cf2a8dd6844ec0daccdac909a85f6f73e
This commit is contained in:
@@ -72,11 +72,6 @@
|
|||||||
android:layout_marginBottom="@dimen/navigation_bar_height"
|
android:layout_marginBottom="@dimen/navigation_bar_height"
|
||||||
android:visibility="invisible"/>
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
<include layout="@layout/headsup_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:visibility="invisible"/>
|
|
||||||
|
|
||||||
<include layout="@layout/status_bar_expanded"
|
<include layout="@layout/status_bar_expanded"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.systemui;
|
|||||||
|
|
||||||
import com.android.systemui.biometrics.AuthController;
|
import com.android.systemui.biometrics.AuthController;
|
||||||
import com.android.systemui.bubbles.dagger.BubbleModule;
|
import com.android.systemui.bubbles.dagger.BubbleModule;
|
||||||
|
import com.android.systemui.car.notification.CarNotificationModule;
|
||||||
import com.android.systemui.globalactions.GlobalActionsComponent;
|
import com.android.systemui.globalactions.GlobalActionsComponent;
|
||||||
import com.android.systemui.keyguard.KeyguardViewMediator;
|
import com.android.systemui.keyguard.KeyguardViewMediator;
|
||||||
import com.android.systemui.keyguard.dagger.KeyguardModule;
|
import com.android.systemui.keyguard.dagger.KeyguardModule;
|
||||||
@@ -49,7 +50,8 @@ import dagger.multibindings.IntoMap;
|
|||||||
|
|
||||||
/** Binder for car specific {@link SystemUI} modules. */
|
/** Binder for car specific {@link SystemUI} modules. */
|
||||||
@Module(includes = {RecentsModule.class, CarStatusBarModule.class, NotificationsModule.class,
|
@Module(includes = {RecentsModule.class, CarStatusBarModule.class, NotificationsModule.class,
|
||||||
BubbleModule.class, KeyguardModule.class, OverlayWindowModule.class})
|
BubbleModule.class, KeyguardModule.class, OverlayWindowModule.class,
|
||||||
|
CarNotificationModule.class})
|
||||||
public abstract class CarSystemUIBinder {
|
public abstract class CarSystemUIBinder {
|
||||||
/** Inject into AuthController. */
|
/** Inject into AuthController. */
|
||||||
@Binds
|
@Binds
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import com.android.keyguard.KeyguardViewController;
|
import com.android.keyguard.KeyguardViewController;
|
||||||
|
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||||
import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
|
import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
|
||||||
import com.android.systemui.car.CarNotificationInterruptionStateProvider;
|
import com.android.systemui.car.CarNotificationInterruptionStateProvider;
|
||||||
import com.android.systemui.dagger.SystemUIRootComponent;
|
import com.android.systemui.dagger.SystemUIRootComponent;
|
||||||
@@ -143,4 +144,8 @@ abstract class CarSystemUIModule {
|
|||||||
@Binds
|
@Binds
|
||||||
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
abstract DeviceProvisionedController bindDeviceProvisionedController(
|
||||||
CarDeviceProvisionedControllerImpl deviceProvisionedController);
|
CarDeviceProvisionedControllerImpl deviceProvisionedController);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract CarDeviceProvisionedController bindCarDeviceProvisionedController(
|
||||||
|
CarDeviceProvisionedControllerImpl deviceProvisionedController);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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.notification;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
|
||||||
|
import com.android.car.notification.R;
|
||||||
|
import com.android.car.notification.headsup.CarHeadsUpNotificationContainer;
|
||||||
|
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||||
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
|
import com.android.systemui.statusbar.car.CarStatusBar;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Lazy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A controller for SysUI's HUN display.
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class CarHeadsUpNotificationSystemContainer implements CarHeadsUpNotificationContainer {
|
||||||
|
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
|
||||||
|
private final Lazy<CarStatusBar> mCarStatusBarLazy;
|
||||||
|
|
||||||
|
private final ViewGroup mWindow;
|
||||||
|
private final FrameLayout mHeadsUpContentFrame;
|
||||||
|
|
||||||
|
private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
CarHeadsUpNotificationSystemContainer(Context context,
|
||||||
|
@Main Resources resources,
|
||||||
|
CarDeviceProvisionedController deviceProvisionedController,
|
||||||
|
WindowManager windowManager,
|
||||||
|
// TODO: Remove dependency on CarStatusBar
|
||||||
|
Lazy<CarStatusBar> carStatusBarLazy) {
|
||||||
|
mCarDeviceProvisionedController = deviceProvisionedController;
|
||||||
|
mCarStatusBarLazy = carStatusBarLazy;
|
||||||
|
|
||||||
|
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
WindowManager.LayoutParams.WRAP_CONTENT,
|
||||||
|
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
|
||||||
|
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
|
||||||
|
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN,
|
||||||
|
PixelFormat.TRANSLUCENT);
|
||||||
|
|
||||||
|
lp.gravity = Gravity.TOP;
|
||||||
|
lp.setTitle("HeadsUpNotification");
|
||||||
|
|
||||||
|
mWindow = (ViewGroup) LayoutInflater.from(context)
|
||||||
|
.inflate(R.layout.headsup_container, null, false);
|
||||||
|
windowManager.addView(mWindow, lp);
|
||||||
|
mWindow.setVisibility(View.INVISIBLE);
|
||||||
|
mHeadsUpContentFrame = mWindow.findViewById(R.id.headsup_content);
|
||||||
|
|
||||||
|
mEnableHeadsUpNotificationWhenNotificationShadeOpen = resources.getBoolean(
|
||||||
|
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateShow() {
|
||||||
|
if ((mEnableHeadsUpNotificationWhenNotificationShadeOpen
|
||||||
|
|| !mCarStatusBarLazy.get().isPanelExpanded()) && isCurrentUserSetup()) {
|
||||||
|
mWindow.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void animateHide() {
|
||||||
|
mWindow.setVisibility(View.INVISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void displayNotification(View notificationView) {
|
||||||
|
mHeadsUpContentFrame.addView(notificationView);
|
||||||
|
animateShow();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeNotification(View notificationView) {
|
||||||
|
mHeadsUpContentFrame.removeView(notificationView);
|
||||||
|
if (mHeadsUpContentFrame.getChildCount() == 0) {
|
||||||
|
animateHide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisible() {
|
||||||
|
return mWindow.getVisibility() == View.VISIBLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCurrentUserSetup() {
|
||||||
|
return mCarDeviceProvisionedController.isCurrentUserSetup()
|
||||||
|
&& !mCarDeviceProvisionedController.isCurrentUserSetupInProgress();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* 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.notification;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.android.car.notification.CarHeadsUpNotificationManager;
|
||||||
|
import com.android.car.notification.CarNotificationListener;
|
||||||
|
import com.android.car.notification.CarUxRestrictionManagerWrapper;
|
||||||
|
import com.android.car.notification.NotificationClickHandlerFactory;
|
||||||
|
import com.android.car.notification.NotificationDataManager;
|
||||||
|
import com.android.car.notification.headsup.CarHeadsUpNotificationContainer;
|
||||||
|
import com.android.internal.statusbar.IStatusBarService;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import dagger.Binds;
|
||||||
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module for Car SysUI Notifications
|
||||||
|
*/
|
||||||
|
@Module
|
||||||
|
public abstract class CarNotificationModule {
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static NotificationClickHandlerFactory provideNotificationClickHandlerFactory(
|
||||||
|
IStatusBarService barService) {
|
||||||
|
return new NotificationClickHandlerFactory(barService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static NotificationDataManager provideNotificationDataManager() {
|
||||||
|
return new NotificationDataManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static CarUxRestrictionManagerWrapper provideCarUxRestrictionManagerWrapper() {
|
||||||
|
return new CarUxRestrictionManagerWrapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static CarNotificationListener provideCarNotificationListener(Context context,
|
||||||
|
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper,
|
||||||
|
CarHeadsUpNotificationManager carHeadsUpNotificationManager,
|
||||||
|
NotificationDataManager notificationDataManager) {
|
||||||
|
CarNotificationListener listener = new CarNotificationListener();
|
||||||
|
listener.registerAsSystemService(context, carUxRestrictionManagerWrapper,
|
||||||
|
carHeadsUpNotificationManager, notificationDataManager);
|
||||||
|
return listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
static CarHeadsUpNotificationManager provideCarHeadsUpNotificationManager(Context context,
|
||||||
|
NotificationClickHandlerFactory notificationClickHandlerFactory,
|
||||||
|
NotificationDataManager notificationDataManager,
|
||||||
|
CarHeadsUpNotificationContainer headsUpNotificationDisplay) {
|
||||||
|
return new CarHeadsUpNotificationManager(context, notificationClickHandlerFactory,
|
||||||
|
notificationDataManager, headsUpNotificationDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
abstract CarHeadsUpNotificationContainer bindsCarHeadsUpNotificationContainer(
|
||||||
|
CarHeadsUpNotificationSystemContainer carHeadsUpNotificationSystemContainer);
|
||||||
|
}
|
||||||
@@ -49,7 +49,6 @@ import com.android.systemui.statusbar.NavigationBarController;
|
|||||||
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
|
||||||
import com.android.systemui.statusbar.phone.AutoHideController;
|
import com.android.systemui.statusbar.phone.AutoHideController;
|
||||||
import com.android.systemui.statusbar.phone.BarTransitions;
|
import com.android.systemui.statusbar.phone.BarTransitions;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
@@ -105,7 +104,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
|
|||||||
public CarNavigationBar(Context context,
|
public CarNavigationBar(Context context,
|
||||||
CarNavigationBarController carNavigationBarController,
|
CarNavigationBarController carNavigationBarController,
|
||||||
WindowManager windowManager,
|
WindowManager windowManager,
|
||||||
DeviceProvisionedController deviceProvisionedController,
|
CarDeviceProvisionedController deviceProvisionedController,
|
||||||
CommandQueue commandQueue,
|
CommandQueue commandQueue,
|
||||||
AutoHideController autoHideController,
|
AutoHideController autoHideController,
|
||||||
ButtonSelectionStateListener buttonSelectionStateListener,
|
ButtonSelectionStateListener buttonSelectionStateListener,
|
||||||
@@ -117,8 +116,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
|
|||||||
super(context);
|
super(context);
|
||||||
mCarNavigationBarController = carNavigationBarController;
|
mCarNavigationBarController = carNavigationBarController;
|
||||||
mWindowManager = windowManager;
|
mWindowManager = windowManager;
|
||||||
mCarDeviceProvisionedController = (CarDeviceProvisionedController)
|
mCarDeviceProvisionedController = deviceProvisionedController;
|
||||||
deviceProvisionedController;
|
|
||||||
mCommandQueue = commandQueue;
|
mCommandQueue = commandQueue;
|
||||||
mAutoHideController = autoHideController;
|
mAutoHideController = autoHideController;
|
||||||
mButtonSelectionStateListener = buttonSelectionStateListener;
|
mButtonSelectionStateListener = buttonSelectionStateListener;
|
||||||
|
|||||||
@@ -43,11 +43,9 @@ import android.view.ViewTreeObserver;
|
|||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.android.car.notification.CarHeadsUpNotificationManager;
|
|
||||||
import com.android.car.notification.CarNotificationListener;
|
import com.android.car.notification.CarNotificationListener;
|
||||||
import com.android.car.notification.CarNotificationView;
|
import com.android.car.notification.CarNotificationView;
|
||||||
import com.android.car.notification.CarUxRestrictionManagerWrapper;
|
import com.android.car.notification.CarUxRestrictionManagerWrapper;
|
||||||
import com.android.car.notification.HeadsUpEntry;
|
|
||||||
import com.android.car.notification.NotificationClickHandlerFactory;
|
import com.android.car.notification.NotificationClickHandlerFactory;
|
||||||
import com.android.car.notification.NotificationDataManager;
|
import com.android.car.notification.NotificationDataManager;
|
||||||
import com.android.car.notification.NotificationViewController;
|
import com.android.car.notification.NotificationViewController;
|
||||||
@@ -132,7 +130,6 @@ import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
|
|||||||
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
||||||
import com.android.systemui.statusbar.policy.BatteryController;
|
import com.android.systemui.statusbar.policy.BatteryController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
|
||||||
import com.android.systemui.statusbar.policy.ExtensionController;
|
import com.android.systemui.statusbar.policy.ExtensionController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.statusbar.policy.NetworkController;
|
import com.android.systemui.statusbar.policy.NetworkController;
|
||||||
@@ -184,14 +181,15 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
private final Lazy<PowerManagerHelper> mPowerManagerHelperLazy;
|
private final Lazy<PowerManagerHelper> mPowerManagerHelperLazy;
|
||||||
private final ShadeController mShadeController;
|
private final ShadeController mShadeController;
|
||||||
private final CarServiceProvider mCarServiceProvider;
|
private final CarServiceProvider mCarServiceProvider;
|
||||||
|
private final NotificationDataManager mNotificationDataManager;
|
||||||
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
|
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
|
||||||
private final ScreenLifecycle mScreenLifecycle;
|
private final ScreenLifecycle mScreenLifecycle;
|
||||||
|
private final CarNotificationListener mCarNotificationListener;
|
||||||
|
|
||||||
private boolean mDeviceIsSetUpForUser = true;
|
private boolean mDeviceIsSetUpForUser = true;
|
||||||
private boolean mIsUserSetupInProgress = false;
|
private boolean mIsUserSetupInProgress = false;
|
||||||
private PowerManagerHelper mPowerManagerHelper;
|
private PowerManagerHelper mPowerManagerHelper;
|
||||||
private FlingAnimationUtils mFlingAnimationUtils;
|
private FlingAnimationUtils mFlingAnimationUtils;
|
||||||
private NotificationDataManager mNotificationDataManager;
|
|
||||||
private NotificationClickHandlerFactory mNotificationClickHandlerFactory;
|
private NotificationClickHandlerFactory mNotificationClickHandlerFactory;
|
||||||
|
|
||||||
// The container for the notifications.
|
// The container for the notifications.
|
||||||
@@ -229,24 +227,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
private boolean mIsNotificationCardSwiping;
|
private boolean mIsNotificationCardSwiping;
|
||||||
// If notification shade is being swiped vertically to close.
|
// If notification shade is being swiped vertically to close.
|
||||||
private boolean mIsSwipingVerticallyToClose;
|
private boolean mIsSwipingVerticallyToClose;
|
||||||
// Whether heads-up notifications should be shown when shade is open.
|
|
||||||
private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
|
|
||||||
|
|
||||||
private CarUxRestrictionManagerWrapper mCarUxRestrictionManagerWrapper;
|
private final CarUxRestrictionManagerWrapper mCarUxRestrictionManagerWrapper;
|
||||||
|
|
||||||
private final CarPowerStateListener mCarPowerStateListener =
|
|
||||||
(int state) -> {
|
|
||||||
// When the car powers on, clear all notifications and mute/unread states.
|
|
||||||
Log.d(TAG, "New car power state: " + state);
|
|
||||||
if (state == CarPowerStateListener.ON) {
|
|
||||||
if (mNotificationClickHandlerFactory != null) {
|
|
||||||
mNotificationClickHandlerFactory.clearAllNotifications();
|
|
||||||
}
|
|
||||||
if (mNotificationDataManager != null) {
|
|
||||||
mNotificationDataManager.clearAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public CarStatusBar(
|
public CarStatusBar(
|
||||||
Context context,
|
Context context,
|
||||||
@@ -288,7 +270,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
BubbleController bubbleController,
|
BubbleController bubbleController,
|
||||||
NotificationGroupManager groupManager,
|
NotificationGroupManager groupManager,
|
||||||
VisualStabilityManager visualStabilityManager,
|
VisualStabilityManager visualStabilityManager,
|
||||||
DeviceProvisionedController deviceProvisionedController,
|
CarDeviceProvisionedController carDeviceProvisionedController,
|
||||||
NavigationBarController navigationBarController,
|
NavigationBarController navigationBarController,
|
||||||
Lazy<AssistManager> assistManagerLazy,
|
Lazy<AssistManager> assistManagerLazy,
|
||||||
ConfigurationController configurationController,
|
ConfigurationController configurationController,
|
||||||
@@ -330,7 +312,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
CarServiceProvider carServiceProvider,
|
CarServiceProvider carServiceProvider,
|
||||||
Lazy<PowerManagerHelper> powerManagerHelperLazy,
|
Lazy<PowerManagerHelper> powerManagerHelperLazy,
|
||||||
CarNavigationBarController carNavigationBarController,
|
CarNavigationBarController carNavigationBarController,
|
||||||
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
|
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
|
||||||
|
NotificationDataManager notificationDataManager,
|
||||||
|
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper,
|
||||||
|
CarNotificationListener carNotificationListener) {
|
||||||
super(
|
super(
|
||||||
context,
|
context,
|
||||||
notificationsController,
|
notificationsController,
|
||||||
@@ -371,7 +356,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
bubbleController,
|
bubbleController,
|
||||||
groupManager,
|
groupManager,
|
||||||
visualStabilityManager,
|
visualStabilityManager,
|
||||||
deviceProvisionedController,
|
carDeviceProvisionedController,
|
||||||
navigationBarController,
|
navigationBarController,
|
||||||
assistManagerLazy,
|
assistManagerLazy,
|
||||||
configurationController,
|
configurationController,
|
||||||
@@ -412,14 +397,16 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
mUserSwitcherController = userSwitcherController;
|
mUserSwitcherController = userSwitcherController;
|
||||||
mScrimController = scrimController;
|
mScrimController = scrimController;
|
||||||
mLockscreenLockIconController = lockscreenLockIconController;
|
mLockscreenLockIconController = lockscreenLockIconController;
|
||||||
mCarDeviceProvisionedController =
|
mCarDeviceProvisionedController = carDeviceProvisionedController;
|
||||||
(CarDeviceProvisionedController) deviceProvisionedController;
|
|
||||||
mShadeController = shadeController;
|
mShadeController = shadeController;
|
||||||
mCarServiceProvider = carServiceProvider;
|
mCarServiceProvider = carServiceProvider;
|
||||||
mPowerManagerHelperLazy = powerManagerHelperLazy;
|
mPowerManagerHelperLazy = powerManagerHelperLazy;
|
||||||
mCarNavigationBarController = carNavigationBarController;
|
mCarNavigationBarController = carNavigationBarController;
|
||||||
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
|
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
|
||||||
mScreenLifecycle = screenLifecycle;
|
mScreenLifecycle = screenLifecycle;
|
||||||
|
mNotificationDataManager = notificationDataManager;
|
||||||
|
mCarUxRestrictionManagerWrapper = carUxRestrictionManagerWrapper;
|
||||||
|
mCarNotificationListener = carNotificationListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -462,7 +449,17 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
mCarBatteryController.startListening();
|
mCarBatteryController.startListening();
|
||||||
|
|
||||||
mPowerManagerHelper = mPowerManagerHelperLazy.get();
|
mPowerManagerHelper = mPowerManagerHelperLazy.get();
|
||||||
mPowerManagerHelper.setCarPowerStateListener(mCarPowerStateListener);
|
mPowerManagerHelper.setCarPowerStateListener(
|
||||||
|
state -> {
|
||||||
|
// When the car powers on, clear all notifications and mute/unread states.
|
||||||
|
Log.d(TAG, "New car power state: " + state);
|
||||||
|
if (state == CarPowerStateListener.ON) {
|
||||||
|
if (mNotificationClickHandlerFactory != null) {
|
||||||
|
mNotificationClickHandlerFactory.clearAllNotifications();
|
||||||
|
}
|
||||||
|
mNotificationDataManager.clearAll();
|
||||||
|
}
|
||||||
|
});
|
||||||
mPowerManagerHelper.connectToCarService();
|
mPowerManagerHelper.connectToCarService();
|
||||||
|
|
||||||
mCarDeviceProvisionedController.addCallback(
|
mCarDeviceProvisionedController.addCallback(
|
||||||
@@ -597,27 +594,13 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
mShadeController.animateCollapsePanels();
|
mShadeController.animateCollapsePanels();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
CarNotificationListener carNotificationListener = new CarNotificationListener();
|
|
||||||
mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper();
|
|
||||||
|
|
||||||
mNotificationDataManager = new NotificationDataManager();
|
|
||||||
|
|
||||||
mNotificationDataManager.setOnUnseenCountUpdateListener(() -> {
|
mNotificationDataManager.setOnUnseenCountUpdateListener(() -> {
|
||||||
if (mNotificationDataManager != null) {
|
|
||||||
onUseenCountUpdate(mNotificationDataManager.getUnseenNotificationCount());
|
onUseenCountUpdate(mNotificationDataManager.getUnseenNotificationCount());
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mEnableHeadsUpNotificationWhenNotificationShadeOpen = mContext.getResources().getBoolean(
|
|
||||||
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen);
|
|
||||||
CarHeadsUpNotificationManager carHeadsUpNotificationManager =
|
|
||||||
new CarSystemUIHeadsUpNotificationManager(mContext,
|
|
||||||
mNotificationClickHandlerFactory, mNotificationDataManager);
|
|
||||||
mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager);
|
mNotificationClickHandlerFactory.setNotificationDataManager(mNotificationDataManager);
|
||||||
|
|
||||||
carNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
|
|
||||||
carHeadsUpNotificationManager, mNotificationDataManager);
|
|
||||||
|
|
||||||
final View glassPane = mNotificationShadeWindowView.findViewById(R.id.glass_pane);
|
final View glassPane = mNotificationShadeWindowView.findViewById(R.id.glass_pane);
|
||||||
mNotificationView = mNotificationShadeWindowView.findViewById(R.id.notification_view);
|
mNotificationView = mNotificationShadeWindowView.findViewById(R.id.notification_view);
|
||||||
mHandleBar = mNotificationShadeWindowView.findViewById(R.id.handle_bar);
|
mHandleBar = mNotificationShadeWindowView.findViewById(R.id.handle_bar);
|
||||||
@@ -720,7 +703,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
mNotificationViewController = new NotificationViewController(
|
mNotificationViewController = new NotificationViewController(
|
||||||
mNotificationView,
|
mNotificationView,
|
||||||
PreprocessingManager.getInstance(mContext),
|
PreprocessingManager.getInstance(mContext),
|
||||||
carNotificationListener,
|
mCarNotificationListener,
|
||||||
mCarUxRestrictionManagerWrapper,
|
mCarUxRestrictionManagerWrapper,
|
||||||
mNotificationDataManager);
|
mNotificationDataManager);
|
||||||
mNotificationViewController.enable();
|
mNotificationViewController.enable();
|
||||||
@@ -1206,61 +1189,4 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* SystemUi version of the notification manager that overrides methods such that the
|
|
||||||
* notifications end up in the status bar layouts instead of a standalone window.
|
|
||||||
*/
|
|
||||||
private class CarSystemUIHeadsUpNotificationManager extends CarHeadsUpNotificationManager {
|
|
||||||
|
|
||||||
CarSystemUIHeadsUpNotificationManager(Context context,
|
|
||||||
NotificationClickHandlerFactory clickHandlerFactory,
|
|
||||||
NotificationDataManager notificationDataManager) {
|
|
||||||
super(context, clickHandlerFactory, notificationDataManager);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected View createHeadsUpPanel() {
|
|
||||||
// In SystemUi the view is already in the window so just return a reference.
|
|
||||||
return mNotificationShadeWindowView.findViewById(R.id.notification_headsup);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void addHeadsUpPanelToDisplay() {
|
|
||||||
// Set the panel initial state to invisible
|
|
||||||
mHeadsUpPanel.setVisibility(View.INVISIBLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setInternalInsetsInfo(ViewTreeObserver.InternalInsetsInfo info,
|
|
||||||
HeadsUpEntry currentNotification, boolean panelExpanded) {
|
|
||||||
super.setInternalInsetsInfo(info, currentNotification, mPanelExpanded);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setHeadsUpVisible() {
|
|
||||||
// if the Notifications panel is showing or SUW for user is in progress then don't show
|
|
||||||
// heads up notifications
|
|
||||||
if ((!mEnableHeadsUpNotificationWhenNotificationShadeOpen && mPanelExpanded)
|
|
||||||
|| !isDeviceSetupForUser()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setHeadsUpVisible();
|
|
||||||
if (mHeadsUpPanel.getVisibility() == View.VISIBLE) {
|
|
||||||
mNotificationShadeWindowController.setHeadsUpShowing(true);
|
|
||||||
mStatusBarWindowController.setForceStatusBarVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void removeNotificationFromPanel(HeadsUpEntry currentHeadsUpNotification) {
|
|
||||||
super.removeNotificationFromPanel(currentHeadsUpNotification);
|
|
||||||
// If the panel ended up empty and hidden we can remove it from SystemUi
|
|
||||||
if (mHeadsUpPanel.getVisibility() != View.VISIBLE) {
|
|
||||||
mNotificationShadeWindowController.setHeadsUpShowing(false);
|
|
||||||
mStatusBarWindowController.setForceStatusBarVisible(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,9 @@ import android.os.Handler;
|
|||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
|
|
||||||
|
import com.android.car.notification.CarNotificationListener;
|
||||||
|
import com.android.car.notification.CarUxRestrictionManagerWrapper;
|
||||||
|
import com.android.car.notification.NotificationDataManager;
|
||||||
import com.android.internal.logging.MetricsLogger;
|
import com.android.internal.logging.MetricsLogger;
|
||||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||||
import com.android.keyguard.ViewMediatorCallback;
|
import com.android.keyguard.ViewMediatorCallback;
|
||||||
@@ -30,6 +33,7 @@ import com.android.systemui.InitController;
|
|||||||
import com.android.systemui.assist.AssistManager;
|
import com.android.systemui.assist.AssistManager;
|
||||||
import com.android.systemui.broadcast.BroadcastDispatcher;
|
import com.android.systemui.broadcast.BroadcastDispatcher;
|
||||||
import com.android.systemui.bubbles.BubbleController;
|
import com.android.systemui.bubbles.BubbleController;
|
||||||
|
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||||
import com.android.systemui.car.CarServiceProvider;
|
import com.android.systemui.car.CarServiceProvider;
|
||||||
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
import com.android.systemui.colorextraction.SysuiColorExtractor;
|
||||||
import com.android.systemui.dagger.qualifiers.UiBackground;
|
import com.android.systemui.dagger.qualifiers.UiBackground;
|
||||||
@@ -93,7 +97,6 @@ import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
|
|||||||
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneDependenciesModule;
|
import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneDependenciesModule;
|
||||||
import com.android.systemui.statusbar.policy.BatteryController;
|
import com.android.systemui.statusbar.policy.BatteryController;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
|
||||||
import com.android.systemui.statusbar.policy.ExtensionController;
|
import com.android.systemui.statusbar.policy.ExtensionController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.statusbar.policy.NetworkController;
|
import com.android.systemui.statusbar.policy.NetworkController;
|
||||||
@@ -164,7 +167,7 @@ public class CarStatusBarModule {
|
|||||||
BubbleController bubbleController,
|
BubbleController bubbleController,
|
||||||
NotificationGroupManager groupManager,
|
NotificationGroupManager groupManager,
|
||||||
VisualStabilityManager visualStabilityManager,
|
VisualStabilityManager visualStabilityManager,
|
||||||
DeviceProvisionedController deviceProvisionedController,
|
CarDeviceProvisionedController carDeviceProvisionedController,
|
||||||
NavigationBarController navigationBarController,
|
NavigationBarController navigationBarController,
|
||||||
Lazy<AssistManager> assistManagerLazy,
|
Lazy<AssistManager> assistManagerLazy,
|
||||||
ConfigurationController configurationController,
|
ConfigurationController configurationController,
|
||||||
@@ -205,7 +208,10 @@ public class CarStatusBarModule {
|
|||||||
CarServiceProvider carServiceProvider,
|
CarServiceProvider carServiceProvider,
|
||||||
Lazy<PowerManagerHelper> powerManagerHelperLazy,
|
Lazy<PowerManagerHelper> powerManagerHelperLazy,
|
||||||
CarNavigationBarController carNavigationBarController,
|
CarNavigationBarController carNavigationBarController,
|
||||||
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
|
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
|
||||||
|
NotificationDataManager notificationDataManager,
|
||||||
|
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper,
|
||||||
|
CarNotificationListener carNotificationListener) {
|
||||||
return new CarStatusBar(
|
return new CarStatusBar(
|
||||||
context,
|
context,
|
||||||
notificationsController,
|
notificationsController,
|
||||||
@@ -246,7 +252,7 @@ public class CarStatusBarModule {
|
|||||||
bubbleController,
|
bubbleController,
|
||||||
groupManager,
|
groupManager,
|
||||||
visualStabilityManager,
|
visualStabilityManager,
|
||||||
deviceProvisionedController,
|
carDeviceProvisionedController,
|
||||||
navigationBarController,
|
navigationBarController,
|
||||||
assistManagerLazy,
|
assistManagerLazy,
|
||||||
configurationController,
|
configurationController,
|
||||||
@@ -286,6 +292,9 @@ public class CarStatusBarModule {
|
|||||||
carServiceProvider,
|
carServiceProvider,
|
||||||
powerManagerHelperLazy,
|
powerManagerHelperLazy,
|
||||||
carNavigationBarController,
|
carNavigationBarController,
|
||||||
flingAnimationUtilsBuilder);
|
flingAnimationUtilsBuilder,
|
||||||
|
notificationDataManager,
|
||||||
|
carUxRestrictionManagerWrapper,
|
||||||
|
carNotificationListener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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.notification;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.testing.AndroidTestingRunner;
|
||||||
|
import android.testing.TestableLooper;
|
||||||
|
import android.testing.TestableResources;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.SysuiTestCase;
|
||||||
|
import com.android.systemui.car.CarDeviceProvisionedController;
|
||||||
|
import com.android.systemui.statusbar.car.CarStatusBar;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
@RunWith(AndroidTestingRunner.class)
|
||||||
|
@TestableLooper.RunWithLooper
|
||||||
|
@SmallTest
|
||||||
|
public class CarHeadsUpNotificationSystemContainerTest extends SysuiTestCase {
|
||||||
|
private CarHeadsUpNotificationSystemContainer mDefaultController;
|
||||||
|
private CarHeadsUpNotificationSystemContainer mOverrideEnabledController;
|
||||||
|
@Mock
|
||||||
|
private CarDeviceProvisionedController mCarDeviceProvisionedController;
|
||||||
|
@Mock
|
||||||
|
private CarStatusBar mCarStatusBar;
|
||||||
|
@Mock
|
||||||
|
private WindowManager mWindowManager;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private View mNotificationView;
|
||||||
|
@Mock
|
||||||
|
private View mNotificationView2;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
when(mCarStatusBar.isPanelExpanded()).thenReturn(false);
|
||||||
|
when(mCarDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
|
||||||
|
when(mCarDeviceProvisionedController.isCurrentUserSetupInProgress()).thenReturn(false);
|
||||||
|
|
||||||
|
TestableResources testableResources = mContext.getOrCreateTestableResources();
|
||||||
|
|
||||||
|
testableResources.addOverride(
|
||||||
|
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen, false);
|
||||||
|
|
||||||
|
mDefaultController = new CarHeadsUpNotificationSystemContainer(mContext,
|
||||||
|
testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager,
|
||||||
|
() -> mCarStatusBar);
|
||||||
|
|
||||||
|
testableResources.addOverride(
|
||||||
|
R.bool.config_enableHeadsUpNotificationWhenNotificationShadeOpen, true);
|
||||||
|
|
||||||
|
mOverrideEnabledController = new CarHeadsUpNotificationSystemContainer(mContext,
|
||||||
|
testableResources.getResources(), mCarDeviceProvisionedController, mWindowManager,
|
||||||
|
() -> mCarStatusBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisplayNotification_firstNotification_isVisible() {
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveNotification_lastNotification_isInvisible() {
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
mDefaultController.removeNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemoveNotification_nonLastNotification_isVisible() {
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
mDefaultController.displayNotification(mNotificationView2);
|
||||||
|
mDefaultController.removeNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisplayNotification_userSetupInProgress_isInvisible() {
|
||||||
|
when(mCarDeviceProvisionedController.isCurrentUserSetupInProgress()).thenReturn(true);
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isFalse();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisplayNotification_userSetupIncomplete_isInvisible() {
|
||||||
|
when(mCarDeviceProvisionedController.isCurrentUserSetup()).thenReturn(false);
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisplayNotification_notificationPanelExpanded_isInvisible() {
|
||||||
|
when(mCarStatusBar.isPanelExpanded()).thenReturn(true);
|
||||||
|
mDefaultController.displayNotification(mNotificationView);
|
||||||
|
assertThat(mDefaultController.isVisible()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDisplayNotification_notificationPanelExpandedEnabledHUNWhenOpen_isVisible() {
|
||||||
|
when(mCarStatusBar.isPanelExpanded()).thenReturn(true);
|
||||||
|
mOverrideEnabledController.displayNotification(mNotificationView);
|
||||||
|
assertThat(mOverrideEnabledController.isVisible()).isTrue();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user