diff --git a/packages/CarSystemUI/res/layout/super_notification_shade.xml b/packages/CarSystemUI/res/layout/super_notification_shade.xml index cb65045533f8b..e36d8caa67f3a 100644 --- a/packages/CarSystemUI/res/layout/super_notification_shade.xml +++ b/packages/CarSystemUI/res/layout/super_notification_shade.xml @@ -72,11 +72,6 @@ android:layout_marginBottom="@dimen/navigation_bar_height" android:visibility="invisible"/> - - 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 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(); + } +} diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java new file mode 100644 index 0000000000000..b7bc63150ea9b --- /dev/null +++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/CarNotificationModule.java @@ -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); +} diff --git a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java index 204552727e22a..b63162ba80904 100644 --- a/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/navigationbar/car/CarNavigationBar.java @@ -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; diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java index 83248f4d867b6..b2e21045f2a9b 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java @@ -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 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 assistManagerLazy, ConfigurationController configurationController, @@ -330,7 +312,10 @@ public class CarStatusBar extends StatusBar implements CarBatteryController.Batt CarServiceProvider carServiceProvider, Lazy 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); - } - } - } } diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java index aea4bd4975273..4754118e7a646 100644 --- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java +++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java @@ -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 assistManagerLazy, ConfigurationController configurationController, @@ -205,7 +208,10 @@ public class CarStatusBarModule { CarServiceProvider carServiceProvider, Lazy 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); } } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainerTest.java new file mode 100644 index 0000000000000..05b8e6a540990 --- /dev/null +++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/notification/CarHeadsUpNotificationSystemContainerTest.java @@ -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(); + } +}