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:
Eric Berglund
2020-01-21 15:28:35 -08:00
parent 91b4f26c5b
commit 89edc87971
9 changed files with 386 additions and 115 deletions

View File

@@ -72,11 +72,6 @@
android:layout_marginBottom="@dimen/navigation_bar_height"
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"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -18,6 +18,7 @@ package com.android.systemui;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.car.notification.CarNotificationModule;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
@@ -49,7 +50,8 @@ import dagger.multibindings.IntoMap;
/** Binder for car specific {@link SystemUI} modules. */
@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 {
/** Inject into AuthController. */
@Binds

View File

@@ -22,6 +22,7 @@ import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import android.content.Context;
import com.android.keyguard.KeyguardViewController;
import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
import com.android.systemui.car.CarNotificationInterruptionStateProvider;
import com.android.systemui.dagger.SystemUIRootComponent;
@@ -143,4 +144,8 @@ abstract class CarSystemUIModule {
@Binds
abstract DeviceProvisionedController bindDeviceProvisionedController(
CarDeviceProvisionedControllerImpl deviceProvisionedController);
@Binds
abstract CarDeviceProvisionedController bindCarDeviceProvisionedController(
CarDeviceProvisionedControllerImpl deviceProvisionedController);
}

View File

@@ -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();
}
}

View File

@@ -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);
}

View File

@@ -49,7 +49,6 @@ import com.android.systemui.statusbar.NavigationBarController;
import com.android.systemui.statusbar.SuperStatusBarViewFactory;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.FileDescriptor;
@@ -105,7 +104,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
public CarNavigationBar(Context context,
CarNavigationBarController carNavigationBarController,
WindowManager windowManager,
DeviceProvisionedController deviceProvisionedController,
CarDeviceProvisionedController deviceProvisionedController,
CommandQueue commandQueue,
AutoHideController autoHideController,
ButtonSelectionStateListener buttonSelectionStateListener,
@@ -117,8 +116,7 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
super(context);
mCarNavigationBarController = carNavigationBarController;
mWindowManager = windowManager;
mCarDeviceProvisionedController = (CarDeviceProvisionedController)
deviceProvisionedController;
mCarDeviceProvisionedController = deviceProvisionedController;
mCommandQueue = commandQueue;
mAutoHideController = autoHideController;
mButtonSelectionStateListener = buttonSelectionStateListener;

View File

@@ -43,11 +43,9 @@ import android.view.ViewTreeObserver;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.android.car.notification.CarHeadsUpNotificationManager;
import com.android.car.notification.CarNotificationListener;
import com.android.car.notification.CarNotificationView;
import com.android.car.notification.CarUxRestrictionManagerWrapper;
import com.android.car.notification.HeadsUpEntry;
import com.android.car.notification.NotificationClickHandlerFactory;
import com.android.car.notification.NotificationDataManager;
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.policy.BatteryController;
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.KeyguardStateController;
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 ShadeController mShadeController;
private final CarServiceProvider mCarServiceProvider;
private final NotificationDataManager mNotificationDataManager;
private final CarDeviceProvisionedController mCarDeviceProvisionedController;
private final ScreenLifecycle mScreenLifecycle;
private final CarNotificationListener mCarNotificationListener;
private boolean mDeviceIsSetUpForUser = true;
private boolean mIsUserSetupInProgress = false;
private PowerManagerHelper mPowerManagerHelper;
private FlingAnimationUtils mFlingAnimationUtils;
private NotificationDataManager mNotificationDataManager;
private NotificationClickHandlerFactory mNotificationClickHandlerFactory;
// The container for the notifications.
@@ -229,24 +227,8 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
private boolean mIsNotificationCardSwiping;
// If notification shade is being swiped vertically to close.
private boolean mIsSwipingVerticallyToClose;
// Whether heads-up notifications should be shown when shade is open.
private boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
private 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();
}
}
};
private final CarUxRestrictionManagerWrapper mCarUxRestrictionManagerWrapper;
public CarStatusBar(
Context context,
@@ -288,7 +270,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
BubbleController bubbleController,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
CarDeviceProvisionedController carDeviceProvisionedController,
NavigationBarController navigationBarController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
@@ -330,7 +312,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
NotificationDataManager notificationDataManager,
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper,
CarNotificationListener carNotificationListener) {
super(
context,
notificationsController,
@@ -371,7 +356,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
bubbleController,
groupManager,
visualStabilityManager,
deviceProvisionedController,
carDeviceProvisionedController,
navigationBarController,
assistManagerLazy,
configurationController,
@@ -412,14 +397,16 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mUserSwitcherController = userSwitcherController;
mScrimController = scrimController;
mLockscreenLockIconController = lockscreenLockIconController;
mCarDeviceProvisionedController =
(CarDeviceProvisionedController) deviceProvisionedController;
mCarDeviceProvisionedController = carDeviceProvisionedController;
mShadeController = shadeController;
mCarServiceProvider = carServiceProvider;
mPowerManagerHelperLazy = powerManagerHelperLazy;
mCarNavigationBarController = carNavigationBarController;
mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder;
mScreenLifecycle = screenLifecycle;
mNotificationDataManager = notificationDataManager;
mCarUxRestrictionManagerWrapper = carUxRestrictionManagerWrapper;
mCarNotificationListener = carNotificationListener;
}
@Override
@@ -462,7 +449,17 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mCarBatteryController.startListening();
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();
mCarDeviceProvisionedController.addCallback(
@@ -597,27 +594,13 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mShadeController.animateCollapsePanels();
}
});
CarNotificationListener carNotificationListener = new CarNotificationListener();
mCarUxRestrictionManagerWrapper = new CarUxRestrictionManagerWrapper();
mNotificationDataManager = new NotificationDataManager();
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);
carNotificationListener.registerAsSystemService(mContext, mCarUxRestrictionManagerWrapper,
carHeadsUpNotificationManager, mNotificationDataManager);
final View glassPane = mNotificationShadeWindowView.findViewById(R.id.glass_pane);
mNotificationView = mNotificationShadeWindowView.findViewById(R.id.notification_view);
mHandleBar = mNotificationShadeWindowView.findViewById(R.id.handle_bar);
@@ -720,7 +703,7 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
mNotificationViewController = new NotificationViewController(
mNotificationView,
PreprocessingManager.getInstance(mContext),
carNotificationListener,
mCarNotificationListener,
mCarUxRestrictionManagerWrapper,
mNotificationDataManager);
mNotificationViewController.enable();
@@ -1206,61 +1189,4 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt
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);
}
}
}
}

View File

@@ -23,6 +23,9 @@ import android.os.Handler;
import android.os.PowerManager;
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.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
@@ -30,6 +33,7 @@ import com.android.systemui.InitController;
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.CarServiceProvider;
import com.android.systemui.colorextraction.SysuiColorExtractor;
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.policy.BatteryController;
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.KeyguardStateController;
import com.android.systemui.statusbar.policy.NetworkController;
@@ -164,7 +167,7 @@ public class CarStatusBarModule {
BubbleController bubbleController,
NotificationGroupManager groupManager,
VisualStabilityManager visualStabilityManager,
DeviceProvisionedController deviceProvisionedController,
CarDeviceProvisionedController carDeviceProvisionedController,
NavigationBarController navigationBarController,
Lazy<AssistManager> assistManagerLazy,
ConfigurationController configurationController,
@@ -205,7 +208,10 @@ public class CarStatusBarModule {
CarServiceProvider carServiceProvider,
Lazy<PowerManagerHelper> powerManagerHelperLazy,
CarNavigationBarController carNavigationBarController,
FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
NotificationDataManager notificationDataManager,
CarUxRestrictionManagerWrapper carUxRestrictionManagerWrapper,
CarNotificationListener carNotificationListener) {
return new CarStatusBar(
context,
notificationsController,
@@ -246,7 +252,7 @@ public class CarStatusBarModule {
bubbleController,
groupManager,
visualStabilityManager,
deviceProvisionedController,
carDeviceProvisionedController,
navigationBarController,
assistManagerLazy,
configurationController,
@@ -286,6 +292,9 @@ public class CarStatusBarModule {
carServiceProvider,
powerManagerHelperLazy,
carNavigationBarController,
flingAnimationUtilsBuilder);
flingAnimationUtilsBuilder,
notificationDataManager,
carUxRestrictionManagerWrapper,
carNotificationListener);
}
}

View File

@@ -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();
}
}