summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-09-03 17:52:36 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-09-03 17:52:36 +0000
commit782ffd0bc9ca647b0fec87afe7d779399605df0a (patch)
tree730d77bb7eb926a10f87ac79216ab8cec4a8ac1d
parent9e6ddb47d6b833e81061087de2f75b670a391b69 (diff)
parentde0b1074196f089ec0d1ee01d01671bc14fed186 (diff)
Merge "Allow multiple annotated configuration controllers in sysui" into main
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt77
-rw-r--r--packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt61
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt72
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java18
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt5
9 files changed, 183 insertions, 63 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
index 578389b57a99..13f6bba01135 100644
--- a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationState.kt
@@ -23,31 +23,72 @@ import androidx.annotation.ColorInt
import androidx.annotation.DimenRes
import androidx.annotation.LayoutRes
import com.android.settingslib.Utils
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.onDensityOrFontScaleChanged
import com.android.systemui.statusbar.policy.onThemeChanged
import com.android.systemui.util.kotlin.emitOnStart
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
+interface ConfigurationState {
+ /**
+ * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+ * configuration.
+ *
+ * @see android.content.res.Resources.getDimensionPixelSize
+ */
+ fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int>
+
+ /**
+ * Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
+ * configuration.
+ *
+ * @see android.content.res.Resources.getDimensionPixelSize
+ */
+ fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int>
+
+ /**
+ * Returns a [Flow] that emits a color that is kept in sync with the device theme.
+ *
+ * @see Utils.getColorAttrDefaultColor
+ */
+ fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int>
+
+ /**
+ * Returns a [Flow] that emits a [View] that is re-inflated as necessary to remain in sync with
+ * the device configuration.
+ *
+ * @see LayoutInflater.inflate
+ */
+ @Suppress("UNCHECKED_CAST")
+ fun <T : View> inflateLayout(
+ @LayoutRes id: Int,
+ root: ViewGroup?,
+ attachToRoot: Boolean,
+ ): Flow<T>
+}
+
/** Configuration-aware-state-tracking utilities. */
-class ConfigurationState
-@Inject
+class ConfigurationStateImpl
+@AssistedInject
constructor(
- private val configurationController: ConfigurationController,
- @Application private val context: Context,
- private val layoutInflater: LayoutInflater,
-) {
+ @Assisted private val configurationController: ConfigurationController,
+ @Assisted private val context: Context,
+) : ConfigurationState {
+
+ private val layoutInflater = LayoutInflater.from(context)
+
/**
* Returns a [Flow] that emits a dimension pixel size that is kept in sync with the device
* configuration.
*
* @see android.content.res.Resources.getDimensionPixelSize
*/
- fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int> {
+ override fun getDimensionPixelSize(@DimenRes id: Int): Flow<Int> {
return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
context.resources.getDimensionPixelSize(id)
}
@@ -59,7 +100,7 @@ constructor(
*
* @see android.content.res.Resources.getDimensionPixelSize
*/
- fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int> {
+ override fun getDimensionPixelOffset(@DimenRes id: Int): Flow<Int> {
return configurationController.onDensityOrFontScaleChanged.emitOnStart().map {
context.resources.getDimensionPixelOffset(id)
}
@@ -70,7 +111,7 @@ constructor(
*
* @see Utils.getColorAttrDefaultColor
*/
- fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int> {
+ override fun getColorAttr(@AttrRes id: Int, @ColorInt defaultValue: Int): Flow<Int> {
return configurationController.onThemeChanged.emitOnStart().map {
Utils.getColorAttrDefaultColor(context, id, defaultValue)
}
@@ -83,7 +124,7 @@ constructor(
* @see LayoutInflater.inflate
*/
@Suppress("UNCHECKED_CAST")
- fun <T : View> inflateLayout(
+ override fun <T : View> inflateLayout(
@LayoutRes id: Int,
root: ViewGroup?,
attachToRoot: Boolean,
@@ -97,4 +138,16 @@ constructor(
.emitOnStart()
.map { layoutInflater.inflate(id, root, attachToRoot) as T }
}
+
+ @AssistedFactory
+ interface Factory {
+ /**
+ * Creates a configurationState for a given context. The [configurationController] is
+ * supposed to give config events specific for that context.
+ */
+ fun create(
+ context: Context,
+ configurationController: ConfigurationController
+ ): ConfigurationStateImpl
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt
new file mode 100644
index 000000000000..b36da3bfcd26
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/common/ui/ConfigurationStateModule.kt
@@ -0,0 +1,61 @@
+/*
+ * 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.common.ui
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.statusbar.policy.ConfigurationController
+import dagger.Binds
+import dagger.Module
+import dagger.Provides
+import javax.inject.Qualifier
+
+/**
+ * Annotates elements that provide information from the global configuration.
+ *
+ * The global configuration is the one associted with the main display. Secondary displays will
+ * apply override to the global configuration. Elements annotated with this shouldn't be used for
+ * secondary displays.
+ */
+@Qualifier @Retention(AnnotationRetention.RUNTIME) annotation class GlobalConfig
+
+@Module
+interface ConfigurationStateModule {
+
+ /**
+ * Deprecated: [ConfigurationState] should be injected only with the correct annotation. For
+ * now, without annotation the global config associated state is provided.
+ */
+ @Binds
+ fun provideGlobalConfigurationState(
+ @GlobalConfig configurationState: ConfigurationState
+ ): ConfigurationState
+
+ companion object {
+ @SysUISingleton
+ @Provides
+ @GlobalConfig
+ fun provideGlobalConfigurationState(
+ configStateFactory: ConfigurationStateImpl.Factory,
+ configurationController: ConfigurationController,
+ @Application context: Context,
+ ): ConfigurationState {
+ return configStateFactory.create(context, configurationController)
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index 1dd37222f29b..3fe6669de556 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -21,6 +21,7 @@ import com.android.systemui.CoreStartable;
import com.android.systemui.Dependency;
import com.android.systemui.InitController;
import com.android.systemui.SystemUIAppComponentFactoryBase;
+import com.android.systemui.common.ui.GlobalConfig;
import com.android.systemui.dagger.qualifiers.PerUser;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.KeyguardSliceProvider;
@@ -127,6 +128,7 @@ public interface SysUIComponent {
* Creates a ContextComponentHelper.
*/
@SysUISingleton
+ @GlobalConfig
ConfigurationController getConfigurationController();
/**
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 411cbd511a22..b55108d6ab1d 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,6 +48,7 @@ import com.android.systemui.brightness.dagger.ScreenBrightnessModule;
import com.android.systemui.classifier.FalsingModule;
import com.android.systemui.clipboardoverlay.dagger.ClipboardOverlayModule;
import com.android.systemui.common.data.CommonDataLayerModule;
+import com.android.systemui.common.ui.ConfigurationStateModule;
import com.android.systemui.common.usagestats.data.CommonUsageStatsDataLayerModule;
import com.android.systemui.communal.dagger.CommunalModule;
import com.android.systemui.complication.dagger.ComplicationComponent;
@@ -207,6 +208,7 @@ import javax.inject.Named;
ClockRegistryModule.class,
CommunalModule.class,
CommonDataLayerModule.class,
+ ConfigurationStateModule.class,
CommonUsageStatsDataLayerModule.class,
ConfigurationControllerModule.class,
ConnectivityModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
index 9b1ca1ec0558..64402052c984 100644
--- a/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/mediaprojection/appselector/MediaProjectionAppSelectorComponent.kt
@@ -122,8 +122,10 @@ interface MediaProjectionAppSelectorModule {
@Provides
@MediaProjectionAppSelector
@MediaProjectionAppSelectorScope
- fun bindConfigurationController(context: Context): ConfigurationController =
- ConfigurationControllerImpl(context)
+ fun bindConfigurationController(
+ context: Context,
+ configurationControlleFactory: ConfigurationControllerImpl.Factory
+ ): ConfigurationController = configurationControlleFactory.create(context)
@Provides fun bindIconFactory(context: Context): IconFactory = IconFactory.obtain(context)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
index 2e1ab383538f..bb5aa23fee28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt
@@ -20,16 +20,17 @@ import android.content.res.Configuration
import android.graphics.Rect
import android.os.LocaleList
import android.view.View.LAYOUT_DIRECTION_RTL
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
-import javax.inject.Inject
+import dagger.assisted.Assisted
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
-@SysUISingleton
-class ConfigurationControllerImpl @Inject constructor(
- @Application context: Context,
- ) : ConfigurationController {
+class ConfigurationControllerImpl
+@AssistedInject
+constructor(
+ @Assisted private val context: Context,
+) : ConfigurationController {
private val listeners: MutableList<ConfigurationListener> = ArrayList()
private val lastConfig = Configuration()
@@ -40,18 +41,17 @@ class ConfigurationControllerImpl @Inject constructor(
private val inCarMode: Boolean
private var uiMode: Int = 0
private var localeList: LocaleList? = null
- private val context: Context
private var layoutDirection: Int
private var orientation = Configuration.ORIENTATION_UNDEFINED
init {
val currentConfig = context.resources.configuration
- this.context = context
fontScale = currentConfig.fontScale
density = currentConfig.densityDpi
smallestScreenWidth = currentConfig.smallestScreenWidthDp
maxBounds.set(currentConfig.windowConfiguration.maxBounds)
- inCarMode = currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
+ inCarMode =
+ currentConfig.uiMode and Configuration.UI_MODE_TYPE_MASK ==
Configuration.UI_MODE_TYPE_CAR
uiMode = currentConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
localeList = currentConfig.locales
@@ -60,29 +60,20 @@ class ConfigurationControllerImpl @Inject constructor(
override fun notifyThemeChanged() {
// Avoid concurrent modification exception
- val listeners = synchronized(this.listeners) {
- ArrayList(this.listeners)
- }
+ val listeners = synchronized(this.listeners) { ArrayList(this.listeners) }
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onThemeChanged()
- }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onThemeChanged() }
}
override fun onConfigurationChanged(newConfig: Configuration) {
// Avoid concurrent modification exception
- val listeners = synchronized(this.listeners) {
- ArrayList(this.listeners)
- }
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onConfigChanged(newConfig)
- }
+ val listeners = synchronized(this.listeners) { ArrayList(this.listeners) }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onConfigChanged(newConfig) }
val fontScale = newConfig.fontScale
val density = newConfig.densityDpi
val uiMode = newConfig.uiMode and Configuration.UI_MODE_NIGHT_MASK
val uiModeChanged = uiMode != this.uiMode
- if (density != this.density || fontScale != this.fontScale ||
- inCarMode && uiModeChanged) {
+ if (density != this.density || fontScale != this.fontScale || inCarMode && uiModeChanged) {
listeners.filterForEach({ this.listeners.contains(it) }) {
it.onDensityOrFontScaleChanged()
}
@@ -105,17 +96,13 @@ class ConfigurationControllerImpl @Inject constructor(
// would be a direct reference to windowConfiguration.maxBounds, so the if statement
// above would always fail. See b/245799099 for more information.
this.maxBounds.set(maxBounds)
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onMaxBoundsChanged()
- }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onMaxBoundsChanged() }
}
val localeList = newConfig.locales
if (localeList != this.localeList) {
this.localeList = localeList
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onLocaleListChanged()
- }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onLocaleListChanged() }
}
if (uiModeChanged) {
@@ -124,9 +111,7 @@ class ConfigurationControllerImpl @Inject constructor(
context.theme.applyStyle(context.themeResId, true)
this.uiMode = uiMode
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onUiModeChanged()
- }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onUiModeChanged() }
}
if (layoutDirection != newConfig.layoutDirection) {
@@ -137,9 +122,7 @@ class ConfigurationControllerImpl @Inject constructor(
}
if (lastConfig.updateFrom(newConfig) and ActivityInfo.CONFIG_ASSETS_PATHS != 0) {
- listeners.filterForEach({ this.listeners.contains(it) }) {
- it.onThemeChanged()
- }
+ listeners.filterForEach({ this.listeners.contains(it) }) { it.onThemeChanged() }
}
val newOrientation = newConfig.orientation
@@ -152,16 +135,12 @@ class ConfigurationControllerImpl @Inject constructor(
}
override fun addCallback(listener: ConfigurationListener) {
- synchronized(listeners) {
- listeners.add(listener)
- }
+ synchronized(listeners) { listeners.add(listener) }
listener.onDensityOrFontScaleChanged()
}
override fun removeCallback(listener: ConfigurationListener) {
- synchronized(listeners) {
- listeners.remove(listener)
- }
+ synchronized(listeners) { listeners.remove(listener) }
}
override fun isLayoutRtl(): Boolean {
@@ -176,6 +155,15 @@ class ConfigurationControllerImpl @Inject constructor(
else -> "err"
}
}
+
+ @AssistedFactory
+ interface Factory {
+ /**
+ * Creates a [ConfigurationController] that uses [context] to resolve the current
+ * configuration and resources.
+ */
+ fun create(context: Context): ConfigurationControllerImpl
+ }
}
// This could be done with a Collection.filter and Collection.forEach, but Collection.filter
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
index 90ebaf269a39..8f4279e80376 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerStartable.kt
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone
import com.android.systemui.CoreStartable
+import com.android.systemui.common.ui.GlobalConfig
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
@@ -26,7 +27,7 @@ import javax.inject.Inject
class ConfigurationControllerStartable
@Inject
constructor(
- private val configurationController: ConfigurationController,
+ @GlobalConfig private val configurationController: ConfigurationController,
private val listeners: Set<@JvmSuppressWildcards ConfigurationListener>
) : CoreStartable {
override fun start() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
index 6cebcbd2731a..b81af86b0779 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/StatusBarPolicyModule.java
@@ -23,7 +23,9 @@ import android.os.UserManager;
import com.android.internal.R;
import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManager;
import com.android.settingslib.notification.modes.ZenIconLoader;
+import com.android.systemui.common.ui.GlobalConfig;
import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.log.LogBuffer;
@@ -103,9 +105,12 @@ public interface StatusBarPolicyModule {
@Binds
CastController provideCastController(CastControllerImpl controllerImpl);
- /** */
+ /**
+ * @deprecated: unscoped configuration controller shouldn't be injected as it might lead to
+ * wrong updates in case of secondary displays.
+ */
@Binds
- ConfigurationController bindConfigurationController(ConfigurationControllerImpl impl);
+ ConfigurationController bindConfigurationController(@GlobalConfig ConfigurationController impl);
/** */
@Binds
@@ -181,6 +186,15 @@ public interface StatusBarPolicyModule {
DevicePostureControllerImpl devicePostureControllerImpl);
/** */
+ @Provides
+ @SysUISingleton
+ @GlobalConfig
+ static ConfigurationController provideGlobalConfigurationController(
+ @Application Context context, ConfigurationControllerImpl.Factory factory) {
+ return factory.create(context);
+ }
+
+ /** */
@SysUISingleton
@Provides
static AccessPointControllerImpl provideAccessPointControllerImpl(
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
index 86a8ae5f9cf4..1ef3464e2b99 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/common/ui/ConfigurationStateKosmos.kt
@@ -17,11 +17,8 @@
package com.android.systemui.common.ui
import android.content.applicationContext
-import android.view.layoutInflater
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.statusbar.policy.configurationController
val Kosmos.configurationState: ConfigurationState by
- Kosmos.Fixture {
- ConfigurationState(configurationController, applicationContext, layoutInflater)
- }
+ Kosmos.Fixture { ConfigurationStateImpl(configurationController, applicationContext) }