Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +12 −5 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ open class ClockRegistry( fun onAvailableClocksChanged() {} } private val replacementMap = ConcurrentHashMap<ClockId, ClockId>() private val availableClocks = ConcurrentHashMap<ClockId, ClockInfo>() private val clockChangeListeners = mutableListOf<ClockChangeListener>() private val settingObserver = Loading Loading @@ -209,6 +210,7 @@ open class ClockRegistry( continue } clock.replacementTarget?.let { replacementMap[id] = it } info.provider = plugin onLoaded(info) } Loading Loading @@ -393,10 +395,11 @@ open class ClockRegistry( // TODO: Merge w/ CurrentClockId when we convert to a flow. We shouldn't need both behaviors. val activeClockId: String get() { if (!availableClocks.containsKey(currentClockId)) { var id = currentClockId if (!availableClocks.containsKey(id)) { return DEFAULT_CLOCK_ID } return currentClockId return replacementMap[id] ?: id } init { Loading @@ -404,6 +407,7 @@ open class ClockRegistry( defaultClockProvider.initialize(clockBuffers) for (clock in defaultClockProvider.getClocks()) { availableClocks[clock.clockId] = ClockInfo(clock, defaultClockProvider, null) clock.replacementTarget?.let { replacementMap[clock.clockId] = it } } // Something has gone terribly wrong if the default clock isn't present Loading Loading @@ -562,9 +566,12 @@ open class ClockRegistry( } } fun getClocks(): List<ClockMetadata> { if (!isEnabled) return listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata) return availableClocks.map { (_, clock) -> clock.metadata } fun getClocks(includeDeprecated: Boolean = false): List<ClockMetadata> { return when { !isEnabled -> listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata) includeDeprecated -> availableClocks.map { (_, clock) -> clock.metadata } else -> availableClocks.map { (_, clock) -> clock.metadata }.filter { !it.isDeprecated } } } fun getClockPickerConfig(clockId: ClockId): ClockPickerConfig? { Loading packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +8 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,14 @@ class DefaultClockProvider( override fun getClocks(): List<ClockMetadata> { var clocks = listOf(ClockMetadata(DEFAULT_CLOCK_ID)) if (isClockReactiveVariantsEnabled) clocks += ClockMetadata(FLEX_CLOCK_ID) if (isClockReactiveVariantsEnabled) { clocks += ClockMetadata( FLEX_CLOCK_ID, isDeprecated = true, replacementTarget = DEFAULT_CLOCK_ID, ) } return clocks } Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt +35 −15 Original line number Diff line number Diff line Loading @@ -151,9 +151,17 @@ class ClockRegistryTest : SysuiTestCase() { create: (ClockId) -> ClockController = ::failFactory, getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig, ): FakeClockPlugin { metadata.add(ClockMetadata(id)) createCallbacks[id] = create pickerConfigs[id] = getPickerConfig return addClock(ClockMetadata(id), create, getPickerConfig) } fun addClock( metadata: ClockMetadata, create: (ClockId) -> ClockController = ::failFactory, getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig, ): FakeClockPlugin { this.metadata.add(metadata) createCallbacks[metadata.clockId] = create pickerConfigs[metadata.clockId] = getPickerConfig return this } } Loading Loading @@ -203,28 +211,40 @@ class ClockRegistryTest : SysuiTestCase() { val plugin1 = FakeClockPlugin().addClock("clock_1").addClock("clock_2") val lifecycle1 = FakeLifecycle("1", plugin1) val plugin2 = FakeClockPlugin().addClock("clock_3").addClock("clock_4") val plugin2 = FakeClockPlugin() .addClock(ClockMetadata("clock_3", isDeprecated = false)) .addClock(ClockMetadata("clock_4", isDeprecated = true)) val lifecycle2 = FakeLifecycle("2", plugin2) pluginListener.onPluginLoaded(plugin1, mockContext, lifecycle1) pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2) val list = registry.getClocks() assertEquals( list.toSet(), setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4"), ), registry.getClocks().toSet(), ) assertEquals( setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4", isDeprecated = true), ), registry.getClocks(includeDeprecated = true).toSet(), ) } @Test fun noPlugins_createDefaultClock() { val clock = registry.createCurrentClock() assertEquals(clock, mockDefaultClock) assertEquals(mockDefaultClock, clock) } @Test Loading @@ -242,18 +262,18 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2) val list = registry.getClocks() assertEquals( list.toSet(), setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ), list.toSet(), ) assertEquals(registry.createExampleClock("clock_1"), mockClock) assertEquals(registry.createExampleClock("clock_2"), mockClock) assertEquals(registry.getClockPickerConfig("clock_1"), pickerConfig) assertEquals(registry.getClockPickerConfig("clock_2"), pickerConfig) assertEquals(mockClock, registry.createExampleClock("clock_1")) assertEquals(mockClock, registry.createExampleClock("clock_2")) assertEquals(pickerConfig, registry.getClockPickerConfig("clock_1")) assertEquals(pickerConfig, registry.getClockPickerConfig("clock_2")) verify(lifecycle1, never()).unloadPlugin() verify(lifecycle2, times(2)).unloadPlugin() } Loading Loading @@ -305,7 +325,7 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginUnloaded(plugin2, lifecycle2) val clock = registry.createCurrentClock() assertEquals(clock, mockDefaultClock) assertEquals(mockDefaultClock, clock) } @Test Loading Loading @@ -482,13 +502,13 @@ class ClockRegistryTest : SysuiTestCase() { // Verify all plugins were correctly loaded into the registry assertEquals( registry.getClocks().toSet(), setOf( ClockMetadata("DEFAULT"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4"), ), registry.getClocks().toSet(), ) } Loading packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt +18 −2 Original line number Diff line number Diff line Loading @@ -53,5 +53,21 @@ interface ClockProvider { /** Identifies a clock design */ typealias ClockId = String /** Some data about a clock design */ data class ClockMetadata(val clockId: ClockId) /** Some metadata about a clock design */ data class ClockMetadata( /** Id for the clock design. */ val clockId: ClockId, /** * true if this clock is deprecated and should not be used. The ID may still show up in certain * locations to help migrations, but it will not be selectable by new users. */ val isDeprecated: Boolean = false, /** * Optional mapping of a legacy clock to a new id. This will map users that already are using * `clockId` to the `replacementTarget` instead. The provider should still support the old id * w/o crashing, but can consider it deprecated and the id reserved. */ val replacementTarget: ClockId? = null, ) Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/ClockRegistry.kt +12 −5 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ open class ClockRegistry( fun onAvailableClocksChanged() {} } private val replacementMap = ConcurrentHashMap<ClockId, ClockId>() private val availableClocks = ConcurrentHashMap<ClockId, ClockInfo>() private val clockChangeListeners = mutableListOf<ClockChangeListener>() private val settingObserver = Loading Loading @@ -209,6 +210,7 @@ open class ClockRegistry( continue } clock.replacementTarget?.let { replacementMap[id] = it } info.provider = plugin onLoaded(info) } Loading Loading @@ -393,10 +395,11 @@ open class ClockRegistry( // TODO: Merge w/ CurrentClockId when we convert to a flow. We shouldn't need both behaviors. val activeClockId: String get() { if (!availableClocks.containsKey(currentClockId)) { var id = currentClockId if (!availableClocks.containsKey(id)) { return DEFAULT_CLOCK_ID } return currentClockId return replacementMap[id] ?: id } init { Loading @@ -404,6 +407,7 @@ open class ClockRegistry( defaultClockProvider.initialize(clockBuffers) for (clock in defaultClockProvider.getClocks()) { availableClocks[clock.clockId] = ClockInfo(clock, defaultClockProvider, null) clock.replacementTarget?.let { replacementMap[clock.clockId] = it } } // Something has gone terribly wrong if the default clock isn't present Loading Loading @@ -562,9 +566,12 @@ open class ClockRegistry( } } fun getClocks(): List<ClockMetadata> { if (!isEnabled) return listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata) return availableClocks.map { (_, clock) -> clock.metadata } fun getClocks(includeDeprecated: Boolean = false): List<ClockMetadata> { return when { !isEnabled -> listOf(availableClocks[DEFAULT_CLOCK_ID]!!.metadata) includeDeprecated -> availableClocks.map { (_, clock) -> clock.metadata } else -> availableClocks.map { (_, clock) -> clock.metadata }.filter { !it.isDeprecated } } } fun getClockPickerConfig(clockId: ClockId): ClockPickerConfig? { Loading
packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +8 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,14 @@ class DefaultClockProvider( override fun getClocks(): List<ClockMetadata> { var clocks = listOf(ClockMetadata(DEFAULT_CLOCK_ID)) if (isClockReactiveVariantsEnabled) clocks += ClockMetadata(FLEX_CLOCK_ID) if (isClockReactiveVariantsEnabled) { clocks += ClockMetadata( FLEX_CLOCK_ID, isDeprecated = true, replacementTarget = DEFAULT_CLOCK_ID, ) } return clocks } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shared/clocks/ClockRegistryTest.kt +35 −15 Original line number Diff line number Diff line Loading @@ -151,9 +151,17 @@ class ClockRegistryTest : SysuiTestCase() { create: (ClockId) -> ClockController = ::failFactory, getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig, ): FakeClockPlugin { metadata.add(ClockMetadata(id)) createCallbacks[id] = create pickerConfigs[id] = getPickerConfig return addClock(ClockMetadata(id), create, getPickerConfig) } fun addClock( metadata: ClockMetadata, create: (ClockId) -> ClockController = ::failFactory, getPickerConfig: (ClockSettings) -> ClockPickerConfig = ::failPickerConfig, ): FakeClockPlugin { this.metadata.add(metadata) createCallbacks[metadata.clockId] = create pickerConfigs[metadata.clockId] = getPickerConfig return this } } Loading Loading @@ -203,28 +211,40 @@ class ClockRegistryTest : SysuiTestCase() { val plugin1 = FakeClockPlugin().addClock("clock_1").addClock("clock_2") val lifecycle1 = FakeLifecycle("1", plugin1) val plugin2 = FakeClockPlugin().addClock("clock_3").addClock("clock_4") val plugin2 = FakeClockPlugin() .addClock(ClockMetadata("clock_3", isDeprecated = false)) .addClock(ClockMetadata("clock_4", isDeprecated = true)) val lifecycle2 = FakeLifecycle("2", plugin2) pluginListener.onPluginLoaded(plugin1, mockContext, lifecycle1) pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2) val list = registry.getClocks() assertEquals( list.toSet(), setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4"), ), registry.getClocks().toSet(), ) assertEquals( setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4", isDeprecated = true), ), registry.getClocks(includeDeprecated = true).toSet(), ) } @Test fun noPlugins_createDefaultClock() { val clock = registry.createCurrentClock() assertEquals(clock, mockDefaultClock) assertEquals(mockDefaultClock, clock) } @Test Loading @@ -242,18 +262,18 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginLoaded(plugin2, mockContext, lifecycle2) val list = registry.getClocks() assertEquals( list.toSet(), setOf( ClockMetadata(DEFAULT_CLOCK_ID), ClockMetadata("clock_1"), ClockMetadata("clock_2"), ), list.toSet(), ) assertEquals(registry.createExampleClock("clock_1"), mockClock) assertEquals(registry.createExampleClock("clock_2"), mockClock) assertEquals(registry.getClockPickerConfig("clock_1"), pickerConfig) assertEquals(registry.getClockPickerConfig("clock_2"), pickerConfig) assertEquals(mockClock, registry.createExampleClock("clock_1")) assertEquals(mockClock, registry.createExampleClock("clock_2")) assertEquals(pickerConfig, registry.getClockPickerConfig("clock_1")) assertEquals(pickerConfig, registry.getClockPickerConfig("clock_2")) verify(lifecycle1, never()).unloadPlugin() verify(lifecycle2, times(2)).unloadPlugin() } Loading Loading @@ -305,7 +325,7 @@ class ClockRegistryTest : SysuiTestCase() { pluginListener.onPluginUnloaded(plugin2, lifecycle2) val clock = registry.createCurrentClock() assertEquals(clock, mockDefaultClock) assertEquals(mockDefaultClock, clock) } @Test Loading Loading @@ -482,13 +502,13 @@ class ClockRegistryTest : SysuiTestCase() { // Verify all plugins were correctly loaded into the registry assertEquals( registry.getClocks().toSet(), setOf( ClockMetadata("DEFAULT"), ClockMetadata("clock_2"), ClockMetadata("clock_3"), ClockMetadata("clock_4"), ), registry.getClocks().toSet(), ) } Loading
packages/SystemUI/plugin/src/com/android/systemui/plugins/clocks/ClockProviderPlugin.kt +18 −2 Original line number Diff line number Diff line Loading @@ -53,5 +53,21 @@ interface ClockProvider { /** Identifies a clock design */ typealias ClockId = String /** Some data about a clock design */ data class ClockMetadata(val clockId: ClockId) /** Some metadata about a clock design */ data class ClockMetadata( /** Id for the clock design. */ val clockId: ClockId, /** * true if this clock is deprecated and should not be used. The ID may still show up in certain * locations to help migrations, but it will not be selectable by new users. */ val isDeprecated: Boolean = false, /** * Optional mapping of a legacy clock to a new id. This will map users that already are using * `clockId` to the `replacementTarget` instead. The provider should still support the old id * w/o crashing, but can consider it deprecated and the id reserved. */ val replacementTarget: ClockId? = null, )