summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chris Göllner <chrisgollner@google.com> 2024-11-04 14:12:47 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-04 14:12:47 +0000
commitf2cd7492526014034ca8af99b1c6fb17d92f5cc1 (patch)
tree02c92967c4340ae1e12f47a1697aff4da180fc5a
parent7cf1bb4801147f5a22e28a143023be94a0e1614e (diff)
parent88228a8a16a6624d450e31be07d920828b11a726 (diff)
Merge "Prepare LightBarController for multi display" into main
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java8
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt76
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt77
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.kt69
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java)173
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt19
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreKosmos.kt34
11 files changed, 394 insertions, 132 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
index 2905a7329d21..646722bee35f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/navigationbar/views/NavigationBarTest.java
@@ -116,6 +116,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.data.repository.LightBarControllerStore;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.LightBarController;
@@ -208,7 +209,7 @@ public class NavigationBarTest extends SysuiTestCase {
@Mock
private LightBarController mLightBarController;
@Mock
- private LightBarController.Factory mLightBarcontrollerFactory;
+ private LightBarControllerStore mLightBarControllerStore;
@Mock
private AutoHideController mAutoHideController;
@Mock
@@ -257,7 +258,7 @@ public class NavigationBarTest extends SysuiTestCase {
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- when(mLightBarcontrollerFactory.create(any(Context.class))).thenReturn(mLightBarController);
+ when(mLightBarControllerStore.forDisplay(anyInt())).thenReturn(mLightBarController);
when(mAutoHideControllerFactory.create(any(Context.class))).thenReturn(mAutoHideController);
when(mNavigationBarView.getHomeButton()).thenReturn(mHomeButton);
when(mNavigationBarView.getRecentsButton()).thenReturn(mRecentsButton);
@@ -649,8 +650,7 @@ public class NavigationBarTest extends SysuiTestCase {
mFakeExecutor,
mUiEventLogger,
mNavBarHelper,
- mLightBarController,
- mLightBarcontrollerFactory,
+ mLightBarControllerStore,
mAutoHideController,
mAutoHideControllerFactory,
Optional.of(mTelecomManager),
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt
new file mode 100644
index 000000000000..18eef33813f6
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreImplTest.kt
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2024 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 android.view.Display.DEFAULT_DISPLAY
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.display.data.repository.displayRepository
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.kosmos.useUnconfinedTestDispatcher
+import com.android.systemui.testKosmos
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class LightBarControllerStoreImplTest : SysuiTestCase() {
+ private val kosmos = testKosmos().useUnconfinedTestDispatcher()
+ private val testScope = kosmos.testScope
+ private val fakeDisplayRepository = kosmos.displayRepository
+
+ private val underTest = kosmos.lightBarControllerStoreImpl
+
+ @Before
+ fun start() {
+ underTest.start()
+ }
+
+ @Before fun addDisplays() = runBlocking { fakeDisplayRepository.addDisplay(DEFAULT_DISPLAY) }
+
+ @Test
+ fun forDisplay_startsInstance() =
+ testScope.runTest {
+ val instance = underTest.forDisplay(DEFAULT_DISPLAY)
+
+ verify(instance).start()
+ }
+
+ @Test
+ fun beforeDisplayRemoved_doesNotStopInstances() =
+ testScope.runTest {
+ val instance = underTest.forDisplay(DEFAULT_DISPLAY)
+
+ verify(instance, never()).stop()
+ }
+
+ @Test
+ fun displayRemoved_stopsInstance() =
+ testScope.runTest {
+ val instance = underTest.forDisplay(DEFAULT_DISPLAY)
+
+ fakeDisplayRepository.removeDisplay(DEFAULT_DISPLAY)
+
+ verify(instance).stop()
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
index 88ec18dd65f3..12f6825b462e 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/phone/LightBarControllerTest.java
@@ -48,12 +48,10 @@ import com.android.keyguard.TestScopeProvider;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
-import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.statusbar.data.model.StatusBarAppearance;
import com.android.systemui.statusbar.data.model.StatusBarMode;
-import com.android.systemui.statusbar.data.repository.FakeStatusBarModeRepository;
+import com.android.systemui.statusbar.data.repository.FakeStatusBarModePerDisplayRepository;
import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.util.kotlin.JavaAdapter;
import kotlinx.coroutines.test.TestScope;
@@ -81,8 +79,8 @@ public class LightBarControllerTest extends SysuiTestCase {
private SysuiDarkIconDispatcher mStatusBarIconController;
private LightBarController mLightBarController;
private final TestScope mTestScope = TestScopeProvider.getTestScope();
- private final FakeStatusBarModeRepository mStatusBarModeRepository =
- new FakeStatusBarModeRepository();
+ private final FakeStatusBarModePerDisplayRepository mStatusBarModeRepository =
+ new FakeStatusBarModePerDisplayRepository();
@Before
public void setup() {
@@ -92,15 +90,15 @@ public class LightBarControllerTest extends SysuiTestCase {
mLightBarTransitionsController = mock(LightBarTransitionsController.class);
when(mStatusBarIconController.getTransitionsController()).thenReturn(
mLightBarTransitionsController);
- mLightBarController = new LightBarController(
- mContext,
- new JavaAdapter(mTestScope),
+ mLightBarController = new LightBarControllerImpl(
+ mContext.getDisplayId(),
+ mTestScope,
mStatusBarIconController,
mock(BatteryController.class),
mock(NavigationModeController.class),
mStatusBarModeRepository,
mock(DumpManager.class),
- new FakeDisplayTracker(mContext));
+ mTestScope.getCoroutineContext());
mLightBarController.start();
}
@@ -121,7 +119,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, secondBounds)
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -142,7 +140,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(0 /* appearance */, secondBounds)
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -165,7 +163,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, secondBounds)
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -190,7 +188,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, thirdBounds)
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -214,7 +212,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(0 /* appearance */, secondBounds)
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -231,7 +229,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -249,7 +247,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(0, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -266,7 +264,7 @@ public class LightBarControllerTest extends SysuiTestCase {
new AppearanceRegion(APPEARANCE_LIGHT_STATUS_BARS, new Rect(0, 0, 1, 1))
);
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -276,7 +274,7 @@ public class LightBarControllerTest extends SysuiTestCase {
reset(mStatusBarIconController);
// WHEN the same appearance regions but different status bar mode is sent
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.LIGHTS_OUT_TRANSPARENT,
STATUS_BAR_BOUNDS,
@@ -298,7 +296,7 @@ public class LightBarControllerTest extends SysuiTestCase {
/* start= */ new Rect(0, 0, 10, 10),
/* end= */ new Rect(0, 0, 20, 20));
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
startingBounds,
@@ -311,7 +309,7 @@ public class LightBarControllerTest extends SysuiTestCase {
BoundsPair newBounds = new BoundsPair(
/* start= */ new Rect(0, 0, 30, 30),
/* end= */ new Rect(0, 0, 40, 40));
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance().setValue(
+ mStatusBarModeRepository.getStatusBarAppearance().setValue(
new StatusBarAppearance(
StatusBarMode.TRANSPARENT,
newBounds,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
index 96c0cac53908..40613c0edc68 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/views/NavigationBar.java
@@ -149,6 +149,7 @@ import com.android.systemui.statusbar.CommandQueue.Callbacks;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShadeDepthController;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.data.repository.LightBarControllerStore;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
@@ -258,8 +259,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
private boolean mTransientShownFromGestureOnSystemBar;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
private LightBarController mLightBarController;
- private final LightBarController mMainLightBarController;
- private final LightBarController.Factory mLightBarControllerFactory;
+ private final LightBarControllerStore mLightBarControllerStore;
private AutoHideController mAutoHideController;
private final AutoHideController mMainAutoHideController;
private final AutoHideController.Factory mAutoHideControllerFactory;
@@ -580,8 +580,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
@Background Executor bgExecutor,
UiEventLogger uiEventLogger,
NavBarHelper navBarHelper,
- LightBarController mainLightBarController,
- LightBarController.Factory lightBarControllerFactory,
+ LightBarControllerStore lightBarControllerStore,
AutoHideController mainAutoHideController,
AutoHideController.Factory autoHideControllerFactory,
Optional<TelecomManager> telecomManagerOptional,
@@ -628,8 +627,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
mUiEventLogger = uiEventLogger;
mNavBarHelper = navBarHelper;
mNotificationShadeDepthController = notificationShadeDepthController;
- mMainLightBarController = mainLightBarController;
- mLightBarControllerFactory = lightBarControllerFactory;
+ mLightBarControllerStore = lightBarControllerStore;
mMainAutoHideController = mainAutoHideController;
mAutoHideControllerFactory = autoHideControllerFactory;
mTelecomManagerOptional = telecomManagerOptional;
@@ -842,8 +840,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements
// Unfortunately, we still need it because status bar needs LightBarController
// before notifications creation. We cannot directly use getLightBarController()
// from NavigationBarFragment directly.
- LightBarController lightBarController = mIsOnDefaultDisplay
- ? mMainLightBarController : mLightBarControllerFactory.create(mContext);
+ LightBarController lightBarController = mLightBarControllerStore.forDisplay(mDisplayId);
setLightBarController(lightBarController);
// TODO(b/118592525): to support multi-display, we start to add something which is
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
index f65ae67efbf1..434120051039 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarModule.kt
@@ -26,6 +26,7 @@ import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.data.StatusBarDataLayerModule
+import com.android.systemui.statusbar.data.repository.LightBarControllerStore
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider
import com.android.systemui.statusbar.phone.StatusBarContentInsetsProviderImpl
@@ -55,26 +56,26 @@ import dagger.multibindings.IntoMap
* [com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule], etc.).
*/
@Module(includes = [StatusBarDataLayerModule::class, SystemBarUtilsProxyImpl.Module::class])
-abstract class StatusBarModule {
+interface StatusBarModule {
@Binds
@IntoMap
@ClassKey(OngoingCallController::class)
- abstract fun bindOngoingCallController(impl: OngoingCallController): CoreStartable
+ fun bindOngoingCallController(impl: OngoingCallController): CoreStartable
@Binds
@IntoMap
@ClassKey(LightBarController::class)
- abstract fun bindLightBarController(impl: LightBarController): CoreStartable
+ fun lightBarControllerAsCoreStartable(controller: LightBarController): CoreStartable
@Binds
@IntoMap
@ClassKey(StatusBarSignalPolicy::class)
- abstract fun bindStatusBarSignalPolicy(impl: StatusBarSignalPolicy): CoreStartable
+ fun bindStatusBarSignalPolicy(impl: StatusBarSignalPolicy): CoreStartable
@Binds
@SysUISingleton
- abstract fun statusBarWindowControllerFactory(
+ fun statusBarWindowControllerFactory(
implFactory: StatusBarWindowControllerImpl.Factory
): StatusBarWindowController.Factory
@@ -82,6 +83,12 @@ abstract class StatusBarModule {
@Provides
@SysUISingleton
+ fun lightBarController(store: LightBarControllerStore): LightBarController {
+ return store.defaultDisplay
+ }
+
+ @Provides
+ @SysUISingleton
fun windowControllerStore(
multiDisplayImplLazy: Lazy<MultiDisplayStatusBarWindowControllerStore>,
singleDisplayImplLazy: Lazy<SingleDisplayStatusBarWindowControllerStore>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
index f2d926fc22b1..39de28e7cb49 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/StatusBarDataLayerModule.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.data
import com.android.systemui.statusbar.data.repository.KeyguardStatusBarRepositoryModule
+import com.android.systemui.statusbar.data.repository.LightBarControllerStoreModule
import com.android.systemui.statusbar.data.repository.RemoteInputRepositoryModule
import com.android.systemui.statusbar.data.repository.StatusBarConfigurationControllerModule
import com.android.systemui.statusbar.data.repository.StatusBarContentInsetsProviderStoreModule
@@ -28,6 +29,7 @@ import dagger.Module
includes =
[
KeyguardStatusBarRepositoryModule::class,
+ LightBarControllerStoreModule::class,
RemoteInputRepositoryModule::class,
StatusBarConfigurationControllerModule::class,
StatusBarContentInsetsProviderStoreModule::class,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt
new file mode 100644
index 000000000000..ff50e3100672
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/data/repository/LightBarControllerStore.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2024 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.Background
+import com.android.systemui.display.data.repository.DisplayRepository
+import com.android.systemui.display.data.repository.DisplayScopeRepository
+import com.android.systemui.display.data.repository.PerDisplayStore
+import com.android.systemui.display.data.repository.PerDisplayStoreImpl
+import com.android.systemui.statusbar.phone.LightBarController
+import com.android.systemui.statusbar.phone.LightBarControllerImpl
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.ClassKey
+import dagger.multibindings.IntoMap
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+
+/** Provides per display instances of [LightBarController]. */
+interface LightBarControllerStore : PerDisplayStore<LightBarController>
+
+@SysUISingleton
+class LightBarControllerStoreImpl
+@Inject
+constructor(
+ @Background backgroundApplicationScope: CoroutineScope,
+ displayRepository: DisplayRepository,
+ private val factory: LightBarControllerImpl.Factory,
+ private val displayScopeRepository: DisplayScopeRepository,
+ private val statusBarModeRepositoryStore: StatusBarModeRepositoryStore,
+) :
+ LightBarControllerStore,
+ PerDisplayStoreImpl<LightBarController>(backgroundApplicationScope, displayRepository) {
+
+ override fun createInstanceForDisplay(displayId: Int): LightBarController {
+ return factory
+ .create(
+ displayId,
+ displayScopeRepository.scopeForDisplay(displayId),
+ statusBarModeRepositoryStore.forDisplay(displayId),
+ )
+ .also { it.start() }
+ }
+
+ override suspend fun onDisplayRemovalAction(instance: LightBarController) {
+ instance.stop()
+ }
+
+ override val instanceClass = LightBarController::class.java
+}
+
+@Module
+interface LightBarControllerStoreModule {
+
+ @Binds fun store(impl: LightBarControllerStoreImpl): LightBarControllerStore
+
+ @Binds
+ @IntoMap
+ @ClassKey(LightBarControllerStore::class)
+ fun storeAsCoreStartable(impl: LightBarControllerStoreImpl): CoreStartable
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.kt
new file mode 100644
index 000000000000..b5b3162233c0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2024 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
+
+import android.view.WindowInsetsController
+import com.android.internal.colorextraction.ColorExtractor
+import com.android.internal.view.AppearanceRegion
+import com.android.systemui.CoreStartable
+
+/** Controls how light status bar flag applies to the icons. */
+interface LightBarController : CoreStartable {
+
+ fun stop()
+
+ fun setNavigationBar(navigationBar: LightBarTransitionsController)
+
+ fun setBiometricUnlockController(biometricUnlockController: BiometricUnlockController)
+
+ fun onNavigationBarAppearanceChanged(
+ @WindowInsetsController.Appearance appearance: Int,
+ nbModeChanged: Boolean,
+ navigationBarMode: Int,
+ navbarColorManagedByIme: Boolean,
+ )
+
+ fun onNavigationBarModeChanged(newBarMode: Int)
+
+ fun setQsCustomizing(customizing: Boolean)
+
+ /** Set if Quick Settings is fully expanded, which affects notification scrim visibility. */
+ fun setQsExpanded(expanded: Boolean)
+
+ /** Set if Global Actions dialog is visible, which requires dark mode (light buttons). */
+ fun setGlobalActionsVisible(visible: Boolean)
+
+ /**
+ * Controls the light status bar temporarily for back navigation.
+ *
+ * @param appearance the customized appearance.
+ */
+ fun customizeStatusBarAppearance(appearance: AppearanceRegion)
+
+ /**
+ * Sets whether the direct-reply is in use or not.
+ *
+ * @param directReplying `true` when the direct-reply is in-use.
+ */
+ fun setDirectReplying(directReplying: Boolean)
+
+ fun setScrimState(
+ scrimState: ScrimState,
+ scrimBehindAlpha: Float,
+ scrimInFrontColor: ColorExtractor.GradientColors,
+ )
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java
index a33996b99900..6ff9f4c9c820 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarControllerImpl.java
@@ -11,7 +11,7 @@
* 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
+ * limitations under the License.
*/
package com.android.systemui.statusbar.phone;
@@ -22,9 +22,9 @@ import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
import static com.android.systemui.shared.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
-import android.content.Context;
import android.graphics.Rect;
import android.util.Log;
+import android.view.Display;
import android.view.InsetsFlags;
import android.view.ViewDebug;
import android.view.WindowInsetsController.Appearance;
@@ -34,30 +34,32 @@ import androidx.annotation.Nullable;
import com.android.internal.colorextraction.ColorExtractor.GradientColors;
import com.android.internal.view.AppearanceRegion;
-import com.android.systemui.CoreStartable;
-import com.android.systemui.Dumpable;
-import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
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.StatusBarModeRepositoryStore;
+import com.android.systemui.statusbar.data.repository.StatusBarModePerDisplayRepository;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.util.Compile;
-import com.android.systemui.util.kotlin.JavaAdapter;
+import com.android.systemui.util.kotlin.JavaAdapterKt;
+
+import dagger.assisted.Assisted;
+import dagger.assisted.AssistedFactory;
+import dagger.assisted.AssistedInject;
+
+import kotlin.coroutines.CoroutineContext;
+
+import kotlinx.coroutines.CoroutineScope;
import java.io.PrintWriter;
import java.util.ArrayList;
-import javax.inject.Inject;
-
/**
* Controls how light status bar flag applies to the icons.
*/
-@SysUISingleton
-public class LightBarController implements
- BatteryController.BatteryStateChangeCallback, Dumpable, CoreStartable {
+public class LightBarControllerImpl implements
+ BatteryController.BatteryStateChangeCallback, LightBarController {
private static final String TAG = "LightBarController";
private static final boolean DEBUG_NAVBAR = Compile.IS_DEBUG;
@@ -65,10 +67,13 @@ public class LightBarController implements
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
- private final JavaAdapter mJavaAdapter;
+ private final CoroutineScope mCoroutineScope;
private final SysuiDarkIconDispatcher mStatusBarIconController;
private final BatteryController mBatteryController;
- private final StatusBarModeRepositoryStore mStatusBarModeRepository;
+ private final NavigationModeController mNavModeController;
+ private final DumpManager mDumpManager;
+ private final StatusBarModePerDisplayRepository mStatusBarModeRepository;
+ private final CoroutineContext mMainContext;
private BiometricUnlockController mBiometricUnlockController;
private LightBarTransitionsController mNavigationBarController;
@@ -119,42 +124,59 @@ public class LightBarController implements
private String mLastNavigationBarAppearanceChangedLog;
private StringBuilder mLogStringBuilder = null;
- @Inject
- public LightBarController(
- Context ctx,
- JavaAdapter javaAdapter,
+ private final String mDumpableName;
+
+ private final NavigationModeController.ModeChangedListener mNavigationModeListener =
+ (mode) -> mNavigationMode = mode;
+
+ @AssistedInject
+ public LightBarControllerImpl(
+ @Assisted int displayId,
+ @Assisted CoroutineScope coroutineScope,
DarkIconDispatcher darkIconDispatcher,
BatteryController batteryController,
NavigationModeController navModeController,
- StatusBarModeRepositoryStore statusBarModeRepository,
+ @Assisted StatusBarModePerDisplayRepository statusBarModeRepository,
DumpManager dumpManager,
- DisplayTracker displayTracker) {
- mJavaAdapter = javaAdapter;
+ @Main CoroutineContext mainContext) {
+ mCoroutineScope = coroutineScope;
mStatusBarIconController = (SysuiDarkIconDispatcher) darkIconDispatcher;
mBatteryController = batteryController;
- mBatteryController.addCallback(this);
+ mNavModeController = navModeController;
+ mDumpManager = dumpManager;
mStatusBarModeRepository = statusBarModeRepository;
- mNavigationMode = navModeController.addListener((mode) -> {
- mNavigationMode = mode;
- });
-
- if (ctx.getDisplayId() == displayTracker.getDefaultDisplayId()) {
- dumpManager.registerDumpable(getClass().getSimpleName(), this);
- }
+ mMainContext = mainContext;
+ String dumpableNameSuffix =
+ displayId == Display.DEFAULT_DISPLAY ? "" : String.valueOf(displayId);
+ mDumpableName = getClass().getSimpleName() + dumpableNameSuffix;
}
@Override
public void start() {
- mJavaAdapter.alwaysCollectFlow(
- mStatusBarModeRepository.getDefaultDisplay().getStatusBarAppearance(),
+ mDumpManager.registerCriticalDumpable(mDumpableName, this);
+ mBatteryController.addCallback(this);
+ mNavigationMode = mNavModeController.addListener(mNavigationModeListener);
+ JavaAdapterKt.collectFlow(
+ mCoroutineScope,
+ mMainContext,
+ mStatusBarModeRepository.getStatusBarAppearance(),
this::onStatusBarAppearanceChanged);
}
+ @Override
+ public void stop() {
+ mDumpManager.unregisterDumpable(mDumpableName);
+ mBatteryController.removeCallback(this);
+ mNavModeController.removeListener(mNavigationModeListener);
+ }
+
+ @Override
public void setNavigationBar(LightBarTransitionsController navigationBar) {
mNavigationBarController = navigationBar;
updateNavigation();
}
+ @Override
public void setBiometricUnlockController(
BiometricUnlockController biometricUnlockController) {
mBiometricUnlockController = biometricUnlockController;
@@ -202,6 +224,7 @@ public class LightBarController implements
mNavbarColorManagedByIme = navbarColorManagedByIme;
}
+ @Override
public void onNavigationBarAppearanceChanged(@Appearance int appearance, boolean nbModeChanged,
int navigationBarMode, boolean navbarColorManagedByIme) {
int diff = appearance ^ mAppearance;
@@ -244,6 +267,7 @@ public class LightBarController implements
mNavbarColorManagedByIme = navbarColorManagedByIme;
}
+ @Override
public void onNavigationBarModeChanged(int newBarMode) {
mHasLightNavigationBar = isLight(mAppearance, newBarMode, APPEARANCE_LIGHT_NAVIGATION_BARS);
}
@@ -258,30 +282,28 @@ public class LightBarController implements
mNavigationBarMode, mNavbarColorManagedByIme);
}
+ @Override
public void setQsCustomizing(boolean customizing) {
if (mQsCustomizing == customizing) return;
mQsCustomizing = customizing;
reevaluate();
}
- /** Set if Quick Settings is fully expanded, which affects notification scrim visibility */
+ @Override
public void setQsExpanded(boolean expanded) {
if (mQsExpanded == expanded) return;
mQsExpanded = expanded;
reevaluate();
}
- /** Set if Global Actions dialog is visible, which requires dark mode (light buttons) */
+ @Override
public void setGlobalActionsVisible(boolean visible) {
if (mGlobalActionsVisible == visible) return;
mGlobalActionsVisible = visible;
reevaluate();
}
- /**
- * Controls the light status bar temporarily for back navigation.
- * @param appearance the custmoized appearance.
- */
+ @Override
public void customizeStatusBarAppearance(AppearanceRegion appearance) {
if (appearance != null) {
final ArrayList<AppearanceRegion> appearancesList = new ArrayList<>();
@@ -303,16 +325,14 @@ public class LightBarController implements
}
}
- /**
- * Sets whether the direct-reply is in use or not.
- * @param directReplying {@code true} when the direct-reply is in-use.
- */
+ @Override
public void setDirectReplying(boolean directReplying) {
if (mDirectReplying == directReplying) return;
mDirectReplying = directReplying;
reevaluate();
}
+ @Override
public void setScrimState(ScrimState scrimState, float scrimBehindAlpha,
GradientColors scrimInFrontColor) {
boolean bouncerVisibleLast = mBouncerVisible;
@@ -387,20 +407,17 @@ public class LightBarController implements
}
}
- // If no one is light, all icons become white.
if (lightBarBounds.isEmpty()) {
- mStatusBarIconController.getTransitionsController().setIconsDark(
- false, animateChange());
- }
-
- // If all stacks are light, all icons get dark.
- else if (lightBarBounds.size() == numStacks) {
+ // If no one is light, all icons become white.
+ mStatusBarIconController
+ .getTransitionsController()
+ .setIconsDark(false, animateChange());
+ } else if (lightBarBounds.size() == numStacks) {
+ // If all stacks are light, all icons get dark.
mStatusBarIconController.setIconsDarkArea(null);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
- }
-
- // Not the same for every stack, magic!
- else {
+ } else {
+ // Not the same for every stack, magic!
mStatusBarIconController.setIconsDarkArea(lightBarBounds);
mStatusBarIconController.getTransitionsController().setIconsDark(true, animateChange());
}
@@ -468,47 +485,15 @@ public class LightBarController implements
}
}
- /**
- * Injectable factory for creating a {@link LightBarController}.
- */
- public static class Factory {
- private final JavaAdapter mJavaAdapter;
- private final DarkIconDispatcher mDarkIconDispatcher;
- private final BatteryController mBatteryController;
- private final NavigationModeController mNavModeController;
- private final StatusBarModeRepositoryStore mStatusBarModeRepository;
- private final DumpManager mDumpManager;
- private final DisplayTracker mDisplayTracker;
-
- @Inject
- public Factory(
- JavaAdapter javaAdapter,
- DarkIconDispatcher darkIconDispatcher,
- BatteryController batteryController,
- NavigationModeController navModeController,
- StatusBarModeRepositoryStore statusBarModeRepository,
- DumpManager dumpManager,
- DisplayTracker displayTracker) {
- mJavaAdapter = javaAdapter;
- mDarkIconDispatcher = darkIconDispatcher;
- mBatteryController = batteryController;
- mNavModeController = navModeController;
- mStatusBarModeRepository = statusBarModeRepository;
- mDumpManager = dumpManager;
- mDisplayTracker = displayTracker;
- }
+ /** Injectable factory for creating a {@link LightBarControllerImpl}. */
+ @AssistedFactory
+ @FunctionalInterface
+ public interface Factory {
- /** Create an {@link LightBarController} */
- public LightBarController create(Context context) {
- return new LightBarController(
- context,
- mJavaAdapter,
- mDarkIconDispatcher,
- mBatteryController,
- mNavModeController,
- mStatusBarModeRepository,
- mDumpManager,
- mDisplayTracker);
- }
+ /** Creates a {@link LightBarControllerImpl}. */
+ LightBarControllerImpl create(
+ int displayId,
+ CoroutineScope coroutineScope,
+ StatusBarModePerDisplayRepository statusBarModePerDisplayRepository);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt
index 315912406b6d..63a5b3f1e6f6 100644
--- a/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/JavaAdapter.kt
@@ -20,6 +20,7 @@ import android.view.View
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.coroutineScope
import androidx.lifecycle.repeatOnLifecycle
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.lifecycle.repeatWhenAttached
@@ -35,7 +36,7 @@ import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
-import com.android.app.tracing.coroutines.launchTraced as launch
+import kotlinx.coroutines.plus
/** A class allowing Java classes to collect on Kotlin flows. */
@SysUISingleton
@@ -102,6 +103,22 @@ fun <T> collectFlow(
}
}
+/**
+ * Collect information for the given [flow], calling [consumer] for each emitted event on the
+ * specified [collectContext].
+ *
+ * Collection will continue until the given [scope] is cancelled.
+ */
+@JvmOverloads
+fun <T> collectFlow(
+ scope: CoroutineScope,
+ collectContext: CoroutineContext = scope.coroutineContext,
+ flow: Flow<T>,
+ consumer: Consumer<T>,
+): Job {
+ return scope.plus(collectContext).launch { flow.collect { consumer.accept(it) } }
+}
+
fun <A, B, R> combineFlows(flow1: Flow<A>, flow2: Flow<B>, bifunction: (A, B) -> R): Flow<R> {
return combine(flow1, flow2, bifunction)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreKosmos.kt
new file mode 100644
index 000000000000..5f337326b546
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/data/repository/LightBarControllerStoreKosmos.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2024 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.display.data.repository.displayRepository
+import com.android.systemui.display.data.repository.displayScopeRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.applicationCoroutineScope
+import org.mockito.kotlin.mock
+
+val Kosmos.lightBarControllerStoreImpl by
+ Kosmos.Fixture {
+ LightBarControllerStoreImpl(
+ backgroundApplicationScope = applicationCoroutineScope,
+ displayRepository = displayRepository,
+ factory = { _, _, _ -> mock() },
+ displayScopeRepository = displayScopeRepository,
+ statusBarModeRepositoryStore = statusBarModeRepository,
+ )
+ }