Merge "Modernize LightsOutNotifController" into main
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
index 83c16ae..6a0e882 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/FlagDependencies.kt
@@ -19,6 +19,7 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.notification.footer.shared.FooterViewRefactor
import com.android.systemui.statusbar.notification.shared.NotificationIconContainerRefactor
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import javax.inject.Inject
/** A class in which engineers can define flag dependencies */
@@ -26,6 +27,7 @@
class FlagDependencies @Inject constructor(featureFlags: FeatureFlagsClassic, handler: Handler) :
FlagDependenciesBase(featureFlags, handler) {
override fun defineDependencies() {
+ NotificationsLiveDataStoreRefactor.token dependsOn NotificationIconContainerRefactor.token
FooterViewRefactor.token dependsOn NotificationIconContainerRefactor.token
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/model/StatusBarMode.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/model/StatusBarMode.kt
index 747efe3..933d0ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/model/StatusBarMode.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/model/StatusBarMode.kt
@@ -36,7 +36,8 @@
/**
* A mode where notification icons in the status bar are hidden and replaced by a dot (this mode
* can be requested by apps). See
- * [com.android.systemui.statusbar.phone.LightsOutNotifController].
+ * [com.android.systemui.statusbar.phone.LegacyLightsOutNotifController] and
+ * [com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor].
*/
LIGHTS_OUT,
/** Similar to [LIGHTS_OUT], but also with a transparent background for the status bar. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
index d1594ef..0415212 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/KeyguardStatusBarRepository.kt
@@ -33,7 +33,7 @@
/**
* Repository for data that's specific to the status bar **on keyguard**. For data that applies to
- * all status bars, use [StatusBarModeRepository].
+ * all status bars, use [StatusBarModeRepositoryStore].
*/
interface KeyguardStatusBarRepository {
/** True if we can show the user switcher on keyguard and false otherwise. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
index 47994d9..6429815 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModePerDisplayRepository.kt
@@ -25,10 +25,8 @@
import android.view.WindowInsetsController.Appearance
import com.android.internal.statusbar.LetterboxDetails
import com.android.internal.view.AppearanceRegion
-import com.android.systemui.CoreStartable
-import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.Dumpable
import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.dagger.qualifiers.DisplayId
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.core.StatusBarInitializer.OnStatusBarViewInitializedListener
import com.android.systemui.statusbar.data.model.StatusBarAppearance
@@ -38,13 +36,10 @@
import com.android.systemui.statusbar.phone.StatusBarBoundsProvider
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
import com.android.systemui.statusbar.phone.ongoingcall.data.repository.OngoingCallRepository
-import dagger.Binds
-import dagger.Module
-import dagger.multibindings.ClassKey
-import dagger.multibindings.IntoMap
-import dagger.multibindings.IntoSet
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
import java.io.PrintWriter
-import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -61,7 +56,7 @@
* Note: These status bar modes are status bar *window* states that are sent to us from
* WindowManager, not determined internally.
*/
-interface StatusBarModeRepository {
+interface StatusBarModePerDisplayRepository {
/**
* True if the status bar window is showing transiently and will disappear soon, and false
* otherwise. ("Otherwise" in this case means the status bar is persistently hidden OR
@@ -108,16 +103,15 @@
fun clearTransient()
}
-@SysUISingleton
-class StatusBarModeRepositoryImpl
-@Inject
+class StatusBarModePerDisplayRepositoryImpl
+@AssistedInject
constructor(
@Application scope: CoroutineScope,
- @DisplayId thisDisplayId: Int,
+ @Assisted("displayId") thisDisplayId: Int,
private val commandQueue: CommandQueue,
private val letterboxAppearanceCalculator: LetterboxAppearanceCalculator,
ongoingCallRepository: OngoingCallRepository,
-) : StatusBarModeRepository, CoreStartable, OnStatusBarViewInitializedListener {
+) : StatusBarModePerDisplayRepository, OnStatusBarViewInitializedListener, Dumpable {
private val commandQueueCallback =
object : CommandQueue.Callbacks {
@@ -166,7 +160,7 @@
}
}
- override fun start() {
+ fun start() {
commandQueue.addCallback(commandQueueCallback)
}
@@ -340,16 +334,7 @@
)
}
-@Module
-interface StatusBarModeRepositoryModule {
- @Binds fun bindImpl(impl: StatusBarModeRepositoryImpl): StatusBarModeRepository
-
- @Binds
- @IntoMap
- @ClassKey(StatusBarModeRepositoryImpl::class)
- fun bindCoreStartable(impl: StatusBarModeRepositoryImpl): CoreStartable
-
- @Binds
- @IntoSet
- fun bindViewInitListener(impl: StatusBarModeRepositoryImpl): OnStatusBarViewInitializedListener
+@AssistedFactory
+interface StatusBarModePerDisplayRepositoryFactory {
+ fun create(@Assisted("displayId") displayId: Int): StatusBarModePerDisplayRepositoryImpl
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt
new file mode 100644
index 0000000..962cb095
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryStore.kt
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2023 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.statusbar.data.repository
+
+import com.android.systemui.CoreStartable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.DisplayId
+import com.android.systemui.statusbar.core.StatusBarInitializer
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import dagger.multibindings.IntoSet
+import java.io.PrintWriter
+import javax.inject.Inject
+
+interface StatusBarModeRepositoryStore {
+ val defaultDisplay: StatusBarModePerDisplayRepository
+ fun forDisplay(displayId: Int): StatusBarModePerDisplayRepository
+}
+
+@SysUISingleton
+class StatusBarModeRepositoryImpl
+@Inject
+constructor(
+ @DisplayId private val displayId: Int,
+ factory: StatusBarModePerDisplayRepositoryFactory
+) :
+ StatusBarModeRepositoryStore,
+ CoreStartable,
+ StatusBarInitializer.OnStatusBarViewInitializedListener {
+ override val defaultDisplay = factory.create(displayId)
+
+ override fun forDisplay(displayId: Int) =
+ if (this.displayId == displayId) {
+ defaultDisplay
+ } else {
+ TODO("b/127878649 implement multi-display state management")
+ }
+
+ override fun start() {
+ defaultDisplay.start()
+ }
+
+ override fun onStatusBarViewInitialized(component: StatusBarFragmentComponent) {
+ defaultDisplay.onStatusBarViewInitialized(component)
+ }
+
+ override fun dump(pw: PrintWriter, args: Array<out String>) {
+ defaultDisplay.dump(pw, args)
+ }
+}
+
+@Module
+interface StatusBarModeRepositoryModule {
+ @Binds fun bindImpl(impl: StatusBarModeRepositoryImpl): StatusBarModeRepositoryStore
+
+ @Binds
+ @IntoMap
+ @ClassKey(StatusBarModeRepositoryStore::class)
+ fun bindCoreStartable(impl: StatusBarModeRepositoryImpl): CoreStartable
+
+ @Binds
+ @IntoSet
+ fun bindViewInitListener(
+ impl: StatusBarModeRepositoryImpl
+ ): StatusBarInitializer.OnStatusBarViewInitializedListener
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataRefactor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataStoreRefactor.kt
similarity index 99%
rename from packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataRefactor.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataStoreRefactor.kt
index 44387c2..8fc7106 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataRefactor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/shared/NotificationsLiveDataStoreRefactor.kt
@@ -50,4 +50,4 @@
*/
@JvmStatic
inline fun assertInLegacyMode() = RefactorFlagUtils.assertInLegacyMode(isEnabled, FLAG_NAME)
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index 645769c..2d5fe18 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -200,7 +200,7 @@
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.core.StatusBarInitializer;
import com.android.systemui.statusbar.data.model.StatusBarMode;
-import com.android.systemui.statusbar.data.repository.StatusBarModeRepository;
+import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore;
import com.android.systemui.statusbar.notification.DynamicPrivacyController;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
@@ -388,7 +388,7 @@
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final StatusBarInitializer mStatusBarInitializer;
private final StatusBarWindowController mStatusBarWindowController;
- private final StatusBarModeRepository mStatusBarModeRepository;
+ private final StatusBarModeRepositoryStore mStatusBarModeRepository;
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@VisibleForTesting
DozeServiceHost mDozeServiceHost;
@@ -606,7 +606,7 @@
StatusBarInitializer statusBarInitializer,
StatusBarWindowController statusBarWindowController,
StatusBarWindowStateController statusBarWindowStateController,
- StatusBarModeRepository statusBarModeRepository,
+ StatusBarModeRepositoryStore statusBarModeRepository,
KeyguardUpdateMonitor keyguardUpdateMonitor,
StatusBarSignalPolicy statusBarSignalPolicy,
PulseExpansionHandler pulseExpansionHandler,
@@ -900,7 +900,7 @@
setUpPresenter();
if ((result.mTransientBarTypes & WindowInsets.Type.statusBars()) != 0) {
- mStatusBarModeRepository.showTransient();
+ mStatusBarModeRepository.getDefaultDisplay().showTransient();
}
mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior,
@@ -1147,9 +1147,10 @@
mDemoModeController.addCallback(mDemoModeCallback);
mJavaAdapter.alwaysCollectFlow(
- mStatusBarModeRepository.isTransientShown(), this::onTransientShownChanged);
+ mStatusBarModeRepository.getDefaultDisplay().isTransientShown(),
+ this::onTransientShownChanged);
mJavaAdapter.alwaysCollectFlow(
- mStatusBarModeRepository.getStatusBarMode(),
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarMode(),
this::updateBarMode);
mCommandQueueCallbacks = mCommandQueueCallbacksLazy.get();
@@ -1209,7 +1210,7 @@
@Override
public void hide() {
- mStatusBarModeRepository.clearTransient();
+ mStatusBarModeRepository.getDefaultDisplay().clearTransient();
}
});
@@ -1657,7 +1658,7 @@
if (mDemoModeController.isInDemoMode()) return;
if (mStatusBarTransitions != null) {
checkBarMode(
- mStatusBarModeRepository.getStatusBarMode().getValue(),
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarMode().getValue(),
mStatusBarWindowState,
mStatusBarTransitions);
}
@@ -1668,7 +1669,8 @@
/** Temporarily hides Bubbles if the status bar is hidden. */
@Override
public void updateBubblesVisibility() {
- StatusBarMode mode = mStatusBarModeRepository.getStatusBarMode().getValue();
+ StatusBarMode mode =
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarMode().getValue();
mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged(
mode != StatusBarMode.LIGHTS_OUT
&& mode != StatusBarMode.LIGHTS_OUT_TRANSPARENT
@@ -2993,7 +2995,7 @@
// End Extra BaseStatusBarMethods.
boolean isTransientShown() {
- return mStatusBarModeRepository.isTransientShown().getValue();
+ return mStatusBarModeRepository.getDefaultDisplay().isTransientShown().getValue();
}
private void updateLightRevealScrimVisibility() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
index eba7fe0..7c871e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifController.java
@@ -36,6 +36,7 @@
import com.android.internal.view.AppearanceRegion;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.collection.NotifLiveDataStore;
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor;
import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
import com.android.systemui.util.ViewController;
@@ -51,7 +52,7 @@
* whether there are notifications when the device is in {@link View#SYSTEM_UI_FLAG_LOW_PROFILE}.
*/
@StatusBarFragmentScope
-public class LightsOutNotifController extends ViewController<View> {
+public class LegacyLightsOutNotifController extends ViewController<View> {
private final CommandQueue mCommandQueue;
private final NotifLiveDataStore mNotifDataStore;
private final WindowManager mWindowManager;
@@ -63,7 +64,7 @@
private int mDisplayId;
@Inject
- LightsOutNotifController(
+ LegacyLightsOutNotifController(
@Named(LIGHTS_OUT_NOTIF_VIEW) View lightsOutNotifView,
WindowManager windowManager,
NotifLiveDataStore notifDataStore,
@@ -72,7 +73,12 @@
mWindowManager = windowManager;
mNotifDataStore = notifDataStore;
mCommandQueue = commandQueue;
+ }
+ @Override
+ protected void onInit() {
+ super.onInit();
+ NotificationsLiveDataStoreRefactor.assertInLegacyMode();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 4d3e2ad..eec617b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -42,7 +42,7 @@
import com.android.systemui.plugins.DarkIconDispatcher;
import com.android.systemui.settings.DisplayTracker;
import com.android.systemui.statusbar.data.model.StatusBarAppearance;
-import com.android.systemui.statusbar.data.repository.StatusBarModeRepository;
+import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.Compile;
import com.android.systemui.util.kotlin.JavaAdapter;
@@ -68,7 +68,7 @@
private final JavaAdapter mJavaAdapter;
private final SysuiDarkIconDispatcher mStatusBarIconController;
private final BatteryController mBatteryController;
- private final StatusBarModeRepository mStatusBarModeRepository;
+ private final StatusBarModeRepositoryStore mStatusBarModeRepository;
private BiometricUnlockController mBiometricUnlockController;
private LightBarTransitionsController mNavigationBarController;
@@ -126,7 +126,7 @@
DarkIconDispatcher darkIconDispatcher,
BatteryController batteryController,
NavigationModeController navModeController,
- StatusBarModeRepository statusBarModeRepository,
+ StatusBarModeRepositoryStore statusBarModeRepository,
DumpManager dumpManager,
DisplayTracker displayTracker) {
mJavaAdapter = javaAdapter;
@@ -146,7 +146,7 @@
@Override
public void start() {
mJavaAdapter.alwaysCollectFlow(
- mStatusBarModeRepository.getStatusBarAppearance(),
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance(),
this::onStatusBarAppearanceChanged);
}
@@ -476,7 +476,7 @@
private final DarkIconDispatcher mDarkIconDispatcher;
private final BatteryController mBatteryController;
private final NavigationModeController mNavModeController;
- private final StatusBarModeRepository mStatusBarModeRepository;
+ private final StatusBarModeRepositoryStore mStatusBarModeRepository;
private final DumpManager mDumpManager;
private final DisplayTracker mDisplayTracker;
@@ -486,7 +486,7 @@
DarkIconDispatcher darkIconDispatcher,
BatteryController batteryController,
NavigationModeController navModeController,
- StatusBarModeRepository statusBarModeRepository,
+ StatusBarModeRepositoryStore statusBarModeRepository,
DumpManager dumpManager,
DisplayTracker displayTracker) {
mJavaAdapter = javaAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt
new file mode 100644
index 0000000..ed8b3e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractor.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2023 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.statusbar.phone.domain.interactor
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.data.model.StatusBarMode
+import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.map
+
+/**
+ * Apps can request a low profile mode [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE] where status
+ * bar and navigation icons dim. In this mode, a notification dot appears where the notification
+ * icons would appear if they would be shown outside of this mode.
+ *
+ * This interactor knows whether the device is in [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE].
+ */
+@SysUISingleton
+class LightsOutInteractor
+@Inject
+constructor(private val repository: StatusBarModeRepositoryStore) {
+
+ fun isLowProfile(displayId: Int): Flow<Boolean> =
+ repository.forDisplay(displayId).statusBarMode.map {
+ when (it) {
+ StatusBarMode.LIGHTS_OUT,
+ StatusBarMode.LIGHTS_OUT_TRANSPARENT -> true
+ else -> false
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 7adc08c..49880d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -43,7 +43,6 @@
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.res.R;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -139,7 +138,6 @@
private final OngoingCallController mOngoingCallController;
private final SystemStatusAnimationScheduler mAnimationScheduler;
private final StatusBarLocationPublisher mLocationPublisher;
- private final FeatureFlagsClassic mFeatureFlags;
private final NotificationIconAreaController mNotificationIconAreaController;
private final ShadeExpansionStateManager mShadeExpansionStateManager;
private final StatusBarIconController mStatusBarIconController;
@@ -228,7 +226,6 @@
StatusBarLocationPublisher locationPublisher,
NotificationIconAreaController notificationIconAreaController,
ShadeExpansionStateManager shadeExpansionStateManager,
- FeatureFlagsClassic featureFlags,
StatusBarIconController statusBarIconController,
DarkIconManager.Factory darkIconManagerFactory,
CollapsedStatusBarViewModel collapsedStatusBarViewModel,
@@ -258,7 +255,6 @@
mLocationPublisher = locationPublisher;
mNotificationIconAreaController = notificationIconAreaController;
mShadeExpansionStateManager = shadeExpansionStateManager;
- mFeatureFlags = featureFlags;
mStatusBarIconController = statusBarIconController;
mCollapsedStatusBarViewModel = collapsedStatusBarViewModel;
mCollapsedStatusBarViewBinder = collapsedStatusBarViewBinder;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
index 0618abb..96faa35 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
@@ -18,8 +18,9 @@
import com.android.systemui.battery.BatteryMeterViewController;
import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor;
import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
-import com.android.systemui.statusbar.phone.LightsOutNotifController;
+import com.android.systemui.statusbar.phone.LegacyLightsOutNotifController;
import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
import com.android.systemui.statusbar.phone.PhoneStatusBarView;
import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
@@ -78,7 +79,9 @@
getBatteryMeterViewController().init();
getHeadsUpAppearanceController().init();
getPhoneStatusBarViewController().init();
- getLightsOutNotifController().init();
+ if (!NotificationsLiveDataStoreRefactor.isEnabled()) {
+ getLegacyLightsOutNotifController().init();
+ }
getStatusBarDemoMode().init();
}
@@ -101,7 +104,7 @@
/** */
@StatusBarFragmentScope
- LightsOutNotifController getLightsOutNotifController();
+ LegacyLightsOutNotifController getLegacyLightsOutNotifController();
/** */
@StatusBarFragmentScope
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index b0532ce..0bdd1a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -36,7 +36,7 @@
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.data.repository.StatusBarModeRepository
+import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
@@ -68,7 +68,7 @@
private val dumpManager: DumpManager,
private val statusBarWindowController: StatusBarWindowController,
private val swipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler,
- private val statusBarModeRepository: StatusBarModeRepository,
+ private val statusBarModeRepository: StatusBarModeRepositoryStore,
) : CallbackController<OngoingCallListener>, Dumpable, CoreStartable {
private var isFullscreen: Boolean = false
/** Non-null if there's an active call notification. */
@@ -129,7 +129,7 @@
dumpManager.registerDumpable(this)
notifCollection.addCollectionListener(notifListener)
scope.launch {
- statusBarModeRepository.isInFullscreenMode.collect {
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.collect {
isFullscreen = it
updateChipClickListener()
updateGestureListening()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt
index da9c45a..9c78ab4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/data/repository/OngoingCallRepository.kt
@@ -27,7 +27,7 @@
*
* This class is used to break a dependency cycle between
* [com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController] and
- * [com.android.systemui.statusbar.data.repository.StatusBarModeRepository]. Instead, those two
+ * [com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore]. Instead, those two
* classes both refer to this repository.
*/
@SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index b9b88f4..7d7f49b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -16,11 +16,15 @@
package com.android.systemui.statusbar.pipeline.shared.ui.binder
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
import javax.inject.Inject
import kotlinx.coroutines.launch
@@ -61,9 +65,49 @@
listener.onTransitionFromLockscreenToDreamStarted()
}
}
+
+ if (NotificationsLiveDataStoreRefactor.isEnabled) {
+ val displayId = view.display.displayId
+ val lightsOutView: View = view.requireViewById(R.id.notification_lights_out)
+ launch {
+ viewModel.areNotificationsLightsOut(displayId).collect { show ->
+ animateLightsOutView(lightsOutView, show)
+ }
+ }
+ }
}
}
}
+
+ private fun animateLightsOutView(view: View, visible: Boolean) {
+ view.animate().cancel()
+
+ val alpha = if (visible) 1f else 0f
+ val duration = if (visible) 750L else 250L
+ val visibility = if (visible) View.VISIBLE else View.GONE
+
+ if (visible) {
+ view.alpha = 0f
+ view.visibility = View.VISIBLE
+ }
+
+ view
+ .animate()
+ .alpha(alpha)
+ .setDuration(duration)
+ .setListener(
+ object : AnimatorListenerAdapter() {
+ override fun onAnimationEnd(animation: Animator) {
+ view.alpha = alpha
+ view.visibility = visibility
+ // Unset the listener, otherwise this may persist for
+ // another view property animation
+ view.animate().setListener(null)
+ }
+ }
+ )
+ .start()
+ }
}
/** Listener for various events that may affect the status bar's visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
index 15ab143..52a6d8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
@@ -20,11 +20,17 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
+import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
+import com.android.systemui.statusbar.phone.domain.interactor.LightsOutInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -48,12 +54,25 @@
/** Emits whenever a transition from lockscreen to dream has started. */
val transitionFromLockscreenToDreamStartedEvent: Flow<Unit>
+
+ /**
+ * Apps can request a low profile mode [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE] where
+ * status bar and navigation icons dim. In this mode, a notification dot appears where the
+ * notification icons would appear if they would be shown outside of this mode.
+ *
+ * This flow tells when to show or hide the notification dot in the status bar to indicate
+ * whether there are notifications when the device is in
+ * [android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE].
+ */
+ fun areNotificationsLightsOut(displayId: Int): Flow<Boolean>
}
@SysUISingleton
class CollapsedStatusBarViewModelImpl
@Inject
constructor(
+ private val lightsOutInteractor: LightsOutInteractor,
+ private val notificationsInteractor: ActiveNotificationsInteractor,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
@Application coroutineScope: CoroutineScope,
) : CollapsedStatusBarViewModel {
@@ -69,4 +88,17 @@
keyguardTransitionInteractor.lockscreenToDreamingTransition
.filter { it.transitionState == TransitionState.STARTED }
.map {}
+
+ override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> =
+ if (NotificationsLiveDataStoreRefactor.isUnexpectedlyInLegacyMode()) {
+ emptyFlow()
+ } else {
+ combine(
+ notificationsInteractor.areAnyNotificationsPresent,
+ lightsOutInteractor.isLowProfile(displayId),
+ ) { hasNotifications, isLowProfile ->
+ hasNotifications && isLowProfile
+ }
+ .distinctUntilChanged()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
index d1a46fc..057dcb2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/data/repository/StatusBarModeRepositoryImplTest.kt
@@ -62,7 +62,7 @@
private val ongoingCallRepository = OngoingCallRepository()
private val underTest =
- StatusBarModeRepositoryImpl(
+ StatusBarModePerDisplayRepositoryImpl(
testScope.backgroundScope,
DISPLAY_ID,
commandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
index 287ebba..bde2243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightsOutNotifControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LegacyLightsOutNotifControllerTest.java
@@ -54,7 +54,7 @@
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
-public class LightsOutNotifControllerTest extends SysuiTestCase {
+public class LegacyLightsOutNotifControllerTest extends SysuiTestCase {
private static final int LIGHTS_ON = 0;
private static final int LIGHTS_OUT = APPEARANCE_LOW_PROFILE_BARS;
@@ -68,7 +68,7 @@
@Captor private ArgumentCaptor<CommandQueue.Callbacks> mCallbacksCaptor;
private View mLightsOutView;
- private LightsOutNotifController mLightsOutNotifController;
+ private LegacyLightsOutNotifController mLightsOutNotifController;
private int mDisplayId;
private Observer<Boolean> mHaActiveNotifsObserver;
private CommandQueue.Callbacks mCallbacks;
@@ -83,7 +83,7 @@
when(mNotifLiveDataStore.getHasActiveNotifs()).thenReturn(mHasActiveNotifs);
when(mHasActiveNotifs.getValue()).thenReturn(false);
- mLightsOutNotifController = new LightsOutNotifController(
+ mLightsOutNotifController = new LegacyLightsOutNotifController(
mLightsOutView,
mWindowManager,
mNotifLiveDataStore,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
index c45ecf3..f6419a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -121,7 +121,7 @@
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, secondBounds)
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -142,7 +142,7 @@
new AppearanceRegion(0 /* appearance */, secondBounds)
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -165,7 +165,7 @@
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, secondBounds)
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -190,7 +190,7 @@
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, thirdBounds)
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -214,7 +214,7 @@
new AppearanceRegion(0 /* appearance */, secondBounds)
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -231,7 +231,7 @@
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -249,7 +249,7 @@
new AppearanceRegion(0, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -266,7 +266,7 @@
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -276,7 +276,7 @@
reset(mStatusBarIconController);
// WHEN the same appearance regions but different status bar mode is sent
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.LIGHTS_OUT_TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -298,7 +298,7 @@
/* start= */ new Rect(0, 0, 10, 10),
/* end= */ new Rect(0, 0, 20, 20));
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
startingBounds,
@@ -311,7 +311,7 @@
BoundsPair newBounds = new BoundsPair(
/* start= */ new Rect(0, 0, 30, 30),
/* end= */ new Rect(0, 0, 40, 40));
- mStatusBarModeRepository.getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
newBounds,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt
new file mode 100644
index 0000000..5a0e13d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/domain/interactor/LightsOutInteractorTest.kt
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2023 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.statusbar.phone.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.statusbar.data.model.StatusBarMode
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository.Companion.DISPLAY_ID
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+
+@SmallTest
+class LightsOutInteractorTest : SysuiTestCase() {
+
+ private val statusBarModeRepository = FakeStatusBarModeRepository()
+ private val interactor: LightsOutInteractor = LightsOutInteractor(statusBarModeRepository)
+
+ @Test
+ fun isLowProfile_lightsOutStatusBarMode_false() = runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.LIGHTS_OUT
+
+ val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID))
+
+ assertThat(actual).isTrue()
+ }
+
+ @Test
+ fun isLowProfile_lightsOutTransparentStatusBarMode_true() = runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value =
+ StatusBarMode.LIGHTS_OUT_TRANSPARENT
+
+ val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID))
+
+ assertThat(actual).isTrue()
+ }
+
+ @Test
+ fun isLowProfile_transparentStatusBarMode_false() = runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT
+
+ val actual by collectLastValue(interactor.isLowProfile(DISPLAY_ID))
+
+ assertThat(actual).isFalse()
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index 0b87fe8..17c2938 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -46,7 +46,6 @@
import com.android.systemui.common.ui.ConfigurationState;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlagsClassic;
import com.android.systemui.log.LogBuffer;
import com.android.systemui.log.LogcatEchoTracker;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -695,7 +694,6 @@
mLocationPublisher,
mMockNotificationAreaController,
mShadeExpansionStateManager,
- mock(FeatureFlagsClassic.class),
mStatusBarIconController,
mIconManagerFactory,
mCollapsedStatusBarViewModel,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index 49de512..7b73528c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -549,7 +549,7 @@
@Test
fun fullscreenIsTrue_chipStillClickable() {
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
- statusBarModeRepository.isInFullscreenMode.value = true
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
testScope.runCurrent()
assertThat(chipView.hasOnClickListeners()).isTrue()
@@ -559,7 +559,7 @@
@Test
fun callStartedInImmersiveMode_swipeGestureCallbackAdded() {
- statusBarModeRepository.isInFullscreenMode.value = true
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
testScope.runCurrent()
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
@@ -570,7 +570,7 @@
@Test
fun callStartedNotInImmersiveMode_swipeGestureCallbackNotAdded() {
- statusBarModeRepository.isInFullscreenMode.value = false
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = false
testScope.runCurrent()
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
@@ -583,7 +583,7 @@
fun transitionToImmersiveMode_swipeGestureCallbackAdded() {
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
- statusBarModeRepository.isInFullscreenMode.value = true
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
testScope.runCurrent()
verify(mockSwipeStatusBarAwayGestureHandler)
@@ -592,11 +592,11 @@
@Test
fun transitionOutOfImmersiveMode_swipeGestureCallbackRemoved() {
- statusBarModeRepository.isInFullscreenMode.value = true
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
reset(mockSwipeStatusBarAwayGestureHandler)
- statusBarModeRepository.isInFullscreenMode.value = false
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = false
testScope.runCurrent()
verify(mockSwipeStatusBarAwayGestureHandler)
@@ -605,7 +605,7 @@
@Test
fun callEndedWhileInImmersiveMode_swipeGestureCallbackRemoved() {
- statusBarModeRepository.isInFullscreenMode.value = true
+ statusBarModeRepository.defaultDisplay.isInFullscreenMode.value = true
testScope.runCurrent()
val ongoingCallNotifEntry = createOngoingCallNotifEntry()
notifCollectionListener.onEntryAdded(ongoingCallNotifEntry)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index 688f739..09dc1e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -17,49 +17,77 @@
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
import androidx.test.filters.SmallTest
+import com.android.systemui.CoroutineTestScopeModule
+import com.android.systemui.Flags
+import com.android.systemui.SysUITestComponent
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectValues
+import com.android.systemui.collectLastValue
+import com.android.systemui.collectValues
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.runTest
+import com.android.systemui.statusbar.data.model.StatusBarMode
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository.Companion.DISPLAY_ID
+import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
+import com.android.systemui.statusbar.notification.shared.ActiveNotificationModel
import com.google.common.truth.Truth.assertThat
+import dagger.BindsInstance
+import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
-import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
- private lateinit var underTest: CollapsedStatusBarViewModel
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ ]
+ )
+ interface TestComponent : SysUITestComponent<CollapsedStatusBarViewModelImpl> {
+ val statusBarModeRepository: FakeStatusBarModeRepository
+ val activeNotificationListRepository: ActiveNotificationListRepository
+ val keyguardTransitionRepository: FakeKeyguardTransitionRepository
- private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
- private lateinit var testScope: TestScope
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ testScope: CoroutineTestScopeModule,
+ ): TestComponent
+ }
+ }
+
+ @OptIn(ExperimentalCoroutinesApi::class)
+ private val testComponent: TestComponent =
+ DaggerCollapsedStatusBarViewModelImplTest_TestComponent.factory()
+ .create(
+ test = this,
+ testScope = CoroutineTestScopeModule(TestScope(UnconfinedTestDispatcher())),
+ )
@Before
fun setUp() {
- testScope = TestScope(UnconfinedTestDispatcher())
-
- keyguardTransitionRepository = FakeKeyguardTransitionRepository()
- val interactor =
- KeyguardTransitionInteractorFactory.create(
- scope = TestScope().backgroundScope,
- repository = keyguardTransitionRepository,
- )
- .keyguardTransitionInteractor
- underTest = CollapsedStatusBarViewModelImpl(interactor, testScope.backgroundScope)
+ mSetFlagsRule.enableFlags(Flags.FLAG_NOTIFICATIONS_LIVE_DATA_STORE_REFACTOR)
}
@Test
fun isTransitioningFromLockscreenToOccluded_started_isTrue() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -77,8 +105,8 @@
@Test
fun isTransitioningFromLockscreenToOccluded_running_isTrue() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -96,13 +124,13 @@
@Test
fun isTransitioningFromLockscreenToOccluded_finished_isFalse() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.OCCLUDED,
- this.testScheduler,
+ testScope.testScheduler,
)
assertThat(underTest.isTransitioningFromLockscreenToOccluded.value).isFalse()
@@ -112,8 +140,8 @@
@Test
fun isTransitioningFromLockscreenToOccluded_canceled_isFalse() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -131,8 +159,8 @@
@Test
fun isTransitioningFromLockscreenToOccluded_irrelevantTransition_isFalse() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -150,8 +178,8 @@
@Test
fun isTransitioningFromLockscreenToOccluded_followsRepoUpdates() =
- testScope.runTest {
- val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(this)
+ testComponent.runTest {
+ val job = underTest.isTransitioningFromLockscreenToOccluded.launchIn(testScope)
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
@@ -182,7 +210,7 @@
@Test
fun transitionFromLockscreenToDreamStartedEvent_started_emitted() =
- testScope.runTest {
+ testComponent.runTest {
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
keyguardTransitionRepository.sendTransitionStep(
@@ -199,7 +227,7 @@
@Test
fun transitionFromLockscreenToDreamStartedEvent_startedMultiple_emittedMultiple() =
- testScope.runTest {
+ testComponent.runTest {
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
keyguardTransitionRepository.sendTransitionStep(
@@ -234,7 +262,7 @@
@Test
fun transitionFromLockscreenToDreamStartedEvent_startedThenRunning_emittedOnlyOne() =
- testScope.runTest {
+ testComponent.runTest {
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
keyguardTransitionRepository.sendTransitionStep(
@@ -283,7 +311,7 @@
@Test
fun transitionFromLockscreenToDreamStartedEvent_irrelevantTransition_notEmitted() =
- testScope.runTest {
+ testComponent.runTest {
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
keyguardTransitionRepository.sendTransitionStep(
@@ -300,7 +328,7 @@
@Test
fun transitionFromLockscreenToDreamStartedEvent_irrelevantTransitionState_notEmitted() =
- testScope.runTest {
+ testComponent.runTest {
val emissions by collectValues(underTest.transitionFromLockscreenToDreamStartedEvent)
keyguardTransitionRepository.sendTransitionStep(
@@ -317,4 +345,65 @@
assertThat(emissions).isEmpty()
}
+
+ @Test
+ fun areNotificationsLightsOut_lowProfileWithNotifications_true() =
+ testComponent.runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value =
+ StatusBarMode.LIGHTS_OUT_TRANSPARENT
+ activeNotificationListRepository.activeNotifications.value =
+ activeNotificationsStore(testNotifications)
+
+ val actual by collectLastValue(underTest.areNotificationsLightsOut(DISPLAY_ID))
+
+ assertThat(actual).isTrue()
+ }
+
+ @Test
+ fun areNotificationsLightsOut_lowProfileWithoutNotifications_false() =
+ testComponent.runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value =
+ StatusBarMode.LIGHTS_OUT_TRANSPARENT
+ activeNotificationListRepository.activeNotifications.value =
+ activeNotificationsStore(emptyList())
+
+ val actual by collectLastValue(underTest.areNotificationsLightsOut(DISPLAY_ID))
+
+ assertThat(actual).isFalse()
+ }
+
+ @Test
+ fun areNotificationsLightsOut_defaultStatusBarModeWithoutNotifications_false() =
+ testComponent.runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT
+ activeNotificationListRepository.activeNotifications.value =
+ activeNotificationsStore(emptyList())
+
+ val actual by collectLastValue(underTest.areNotificationsLightsOut(DISPLAY_ID))
+
+ assertThat(actual).isFalse()
+ }
+
+ @Test
+ fun areNotificationsLightsOut_defaultStatusBarModeWithNotifications_false() =
+ testComponent.runTest {
+ statusBarModeRepository.defaultDisplay.statusBarMode.value = StatusBarMode.TRANSPARENT
+ activeNotificationListRepository.activeNotifications.value =
+ activeNotificationsStore(testNotifications)
+
+ val actual by collectLastValue(underTest.areNotificationsLightsOut(DISPLAY_ID))
+
+ assertThat(actual).isFalse()
+ }
+
+ private fun activeNotificationsStore(notifications: List<ActiveNotificationModel>) =
+ ActiveNotificationsStore.Builder()
+ .apply { notifications.forEach(::addIndividualNotif) }
+ .build()
+
+ private val testNotifications =
+ listOf(
+ activeNotificationModel(key = "notif1"),
+ activeNotificationModel(key = "notif2"),
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
index 88587b2..bc50f79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
@@ -16,11 +16,20 @@
package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
class FakeCollapsedStatusBarViewModel : CollapsedStatusBarViewModel {
+ private val areNotificationLightsOut = MutableStateFlow(false)
+
override val isTransitioningFromLockscreenToOccluded = MutableStateFlow(false)
override val transitionFromLockscreenToDreamStartedEvent = MutableSharedFlow<Unit>()
+
+ override fun areNotificationsLightsOut(displayId: Int): Flow<Boolean> = areNotificationLightsOut
+
+ fun setNotificationLightsOut(lightsOut: Boolean) {
+ areNotificationLightsOut.value = lightsOut
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
index f25d282..6069083 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/FakeStatusBarModeRepository.kt
@@ -16,14 +16,33 @@
package com.android.systemui.statusbar.data.repository
+import android.view.Display
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.data.model.StatusBarAppearance
import com.android.systemui.statusbar.data.model.StatusBarMode
+import com.google.common.truth.Truth.assertThat
import dagger.Binds
import dagger.Module
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
-class FakeStatusBarModeRepository @Inject constructor() : StatusBarModeRepository {
+@SysUISingleton
+class FakeStatusBarModeRepository @Inject constructor() : StatusBarModeRepositoryStore {
+
+ companion object {
+ const val DISPLAY_ID = Display.DEFAULT_DISPLAY
+ }
+
+ override val defaultDisplay: FakeStatusBarModePerDisplayRepository =
+ FakeStatusBarModePerDisplayRepository()
+
+ override fun forDisplay(displayId: Int): FakeStatusBarModePerDisplayRepository {
+ assertThat(displayId).isEqualTo(DISPLAY_ID)
+ return defaultDisplay
+ }
+}
+
+class FakeStatusBarModePerDisplayRepository : StatusBarModePerDisplayRepository {
override val isTransientShown = MutableStateFlow(false)
override val isInFullscreenMode = MutableStateFlow(false)
override val statusBarAppearance = MutableStateFlow<StatusBarAppearance?>(null)
@@ -39,5 +58,5 @@
@Module
interface FakeStatusBarModeRepositoryModule {
- @Binds fun bindFake(fake: FakeStatusBarModeRepository): StatusBarModeRepository
+ @Binds fun bindFake(fake: FakeStatusBarModeRepository): StatusBarModeRepositoryStore
}