Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d95f52c authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Seperate Picker configuration from controller's clock config" into main

parents 42ebd5c0 bfc1ae36
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ import android.app.ActivityManager
import android.app.UserSwitchObserver
import android.content.Context
import android.database.ContentObserver
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.UserHandle
import android.provider.Settings
@@ -33,6 +32,7 @@ import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockPickerConfig
import com.android.systemui.plugins.clocks.ClockProvider
import com.android.systemui.plugins.clocks.ClockProviderPlugin
import com.android.systemui.plugins.clocks.ClockSettings
@@ -341,6 +341,7 @@ open class ClockRegistry(
    }

    private var isClockChanged = AtomicBoolean(false)

    private fun triggerOnCurrentClockChanged() {
        val shouldSchedule = isClockChanged.compareAndSet(false, true)
        if (!shouldSchedule) {
@@ -355,6 +356,7 @@ open class ClockRegistry(
    }

    private var isClockListChanged = AtomicBoolean(false)

    private fun triggerOnAvailableClocksChanged() {
        val shouldSchedule = isClockListChanged.compareAndSet(false, true)
        if (!shouldSchedule) {
@@ -458,6 +460,7 @@ open class ClockRegistry(
    }

    private var isQueued = AtomicBoolean(false)

    fun verifyLoadedProviders() {
        val shouldSchedule = isQueued.compareAndSet(false, true)
        if (!shouldSchedule) {
@@ -565,8 +568,8 @@ open class ClockRegistry(
        return availableClocks.map { (_, clock) -> clock.metadata }
    }

    fun getClockThumbnail(clockId: ClockId): Drawable? =
        availableClocks[clockId]?.provider?.getClockThumbnail(clockId)
    fun getClockPickerConfig(clockId: ClockId): ClockPickerConfig? =
        availableClocks[clockId]?.provider?.getClockPickerConfig(clockId)

    fun createExampleClock(clockId: ClockId): ClockController? = createClock(clockId)

+9 −4
Original line number Diff line number Diff line
@@ -15,13 +15,13 @@ package com.android.systemui.shared.clocks

import android.content.Context
import android.content.res.Resources
import android.graphics.drawable.Drawable
import android.view.LayoutInflater
import com.android.systemui.customization.R
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockPickerConfig
import com.android.systemui.plugins.clocks.ClockProvider
import com.android.systemui.plugins.clocks.ClockSettings

@@ -60,12 +60,17 @@ class DefaultClockProvider(
        )
    }

    override fun getClockThumbnail(id: ClockId): Drawable? {
    override fun getClockPickerConfig(id: ClockId): ClockPickerConfig {
        if (id != DEFAULT_CLOCK_ID) {
            throw IllegalArgumentException("$id is unsupported by $TAG")
        }

        return ClockPickerConfig(
            DEFAULT_CLOCK_ID,
            resources.getString(R.string.clock_default_name),
            resources.getString(R.string.clock_default_description),
            // TODO(b/352049256): Update placeholder to actual resource
        return resources.getDrawable(R.drawable.clock_default_thumbnail, null)
            resources.getDrawable(R.drawable.clock_default_thumbnail, null),
        )
    }
}
+23 −3
Original line number Diff line number Diff line
@@ -50,8 +50,8 @@ interface ClockProvider {
    /** Initializes and returns the target clock design */
    fun createClock(settings: ClockSettings): ClockController

    /** A static thumbnail for rendering in some examples */
    fun getClockThumbnail(id: ClockId): Drawable?
    /** Settings configuration parameters for the clock */
    fun getClockPickerConfig(id: ClockId): ClockPickerConfig
}

/** Interface for controlling an active clock */
@@ -133,6 +133,7 @@ class DefaultClockFaceLayout(val view: View) : ClockFaceLayout {
    // both small and large clock should have a container (RelativeLayout in
    // SimpleClockFaceController)
    override val views = listOf(view)

    override fun applyConstraints(constraints: ConstraintSet): ConstraintSet {
        if (views.size != 1) {
            throw IllegalArgumentException(
@@ -267,6 +268,25 @@ data class ClockMetadata(
    val clockId: ClockId,
)

data class ClockPickerConfig(
    val id: String,

    /** Localized name of the clock */
    val name: String,

    /** Localized accessibility description for the clock */
    val description: String,

    /* Static & lightweight thumbnail version of the clock */
    val thumbnail: Drawable,

    /** True if the clock will react to tone changes in the seed color */
    val isReactiveToTone: Boolean = true,

    /** True if the clock is capable of chagning style in reaction to touches */
    val isReactiveToTouch: Boolean = false,
)

/** Render configuration for the full clock. Modifies the way systemUI behaves with this clock. */
data class ClockConfig(
    val id: String,
@@ -280,7 +300,7 @@ data class ClockConfig(
    /** Transition to AOD should move smartspace like large clock instead of small clock */
    val useAlternateSmartspaceAODTransition: Boolean = false,

    /** True if the clock will react to tone changes in the seed color. */
    @Deprecated("TODO(b/352049256): Remove")
    val isReactiveToTone: Boolean = true,

    /** True if the clock is large frame clock, which will use weather in compose. */
+26 −14
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.plugins.clocks.ClockMessageBuffers
import com.android.systemui.plugins.clocks.ClockMetadata
import com.android.systemui.plugins.clocks.ClockPickerConfig
import com.android.systemui.plugins.clocks.ClockProviderPlugin
import com.android.systemui.plugins.clocks.ClockSettings
import com.android.systemui.plugins.PluginLifecycleManager
@@ -74,6 +75,7 @@ class ClockRegistryTest : SysuiTestCase() {
    private lateinit var fakeDefaultProvider: FakeClockPlugin
    private lateinit var pluginListener: PluginListener<ClockProviderPlugin>
    private lateinit var registry: ClockRegistry
    private lateinit var pickerConfig: ClockPickerConfig
    private val featureFlags = FakeFeatureFlags()

    companion object {
@@ -82,9 +84,9 @@ class ClockRegistryTest : SysuiTestCase() {
            return null!!
        }

        private fun failThumbnail(clockId: ClockId): Drawable? {
            fail("Unexpected call to getThumbnail: $clockId")
            return null
        private fun failPickerConfig(clockId: ClockId): ClockPickerConfig {
            fail("Unexpected call to getClockPickerConfig: $clockId")
            return null!!
        }
    }

@@ -123,22 +125,31 @@ class ClockRegistryTest : SysuiTestCase() {
    private class FakeClockPlugin : ClockProviderPlugin {
        private val metadata = mutableListOf<ClockMetadata>()
        private val createCallbacks = mutableMapOf<ClockId, (ClockId) -> ClockController>()
        private val thumbnailCallbacks = mutableMapOf<ClockId, (ClockId) -> Drawable?>()
        private val pickerConfigs = mutableMapOf<ClockId, (ClockId) -> ClockPickerConfig>()

        override fun getClocks() = metadata
        override fun createClock(settings: ClockSettings): ClockController =
            createCallbacks[settings.clockId!!]!!(settings.clockId!!)
        override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!(id)

        override fun createClock(settings: ClockSettings): ClockController {
            val clockId = settings.clockId ?: throw IllegalArgumentException("No clockId specified")
            return createCallbacks[clockId]?.invoke(clockId)
                ?: throw NotImplementedError("No callback for '$clockId'")
        }

        override fun getClockPickerConfig(clockId: ClockId): ClockPickerConfig {
            return pickerConfigs[clockId]?.invoke(clockId)
                ?: throw NotImplementedError("No picker config for '$clockId'")
        }

        override fun initialize(buffers: ClockMessageBuffers?) { }

        fun addClock(
            id: ClockId,
            create: (ClockId) -> ClockController = ::failFactory,
            getThumbnail: (ClockId) -> Drawable? = ::failThumbnail
            getPickerConfig: (ClockId) -> ClockPickerConfig = ::failPickerConfig
        ): FakeClockPlugin {
            metadata.add(ClockMetadata(id))
            createCallbacks[id] = create
            thumbnailCallbacks[id] = getThumbnail
            pickerConfigs[id] = getPickerConfig
            return this
        }
    }
@@ -148,9 +159,10 @@ class ClockRegistryTest : SysuiTestCase() {
        scheduler = TestCoroutineScheduler()
        dispatcher = StandardTestDispatcher(scheduler)
        scope = TestScope(dispatcher)
        pickerConfig = ClockPickerConfig("CLOCK_ID", "NAME", "DESC", mockThumbnail)

        fakeDefaultProvider = FakeClockPlugin()
            .addClock(DEFAULT_CLOCK_ID, { mockDefaultClock }, { mockThumbnail })
            .addClock(DEFAULT_CLOCK_ID, { mockDefaultClock }, { pickerConfig })
        whenever(mockContext.contentResolver).thenReturn(mockContentResolver)

        val captor = argumentCaptor<PluginListener<ClockProviderPlugin>>()
@@ -215,8 +227,8 @@ class ClockRegistryTest : SysuiTestCase() {
    @Test
    fun clockIdConflict_ErrorWithoutCrash_unloadDuplicate() {
        val plugin1 = FakeClockPlugin()
            .addClock("clock_1", { mockClock }, { mockThumbnail })
            .addClock("clock_2", { mockClock }, { mockThumbnail })
            .addClock("clock_1", { mockClock }, { pickerConfig })
            .addClock("clock_2", { mockClock }, { pickerConfig })
        val lifecycle1 = spy(FakeLifecycle("1", plugin1))

        val plugin2 = FakeClockPlugin()
@@ -238,8 +250,8 @@ class ClockRegistryTest : SysuiTestCase() {

        assertEquals(registry.createExampleClock("clock_1"), mockClock)
        assertEquals(registry.createExampleClock("clock_2"), mockClock)
        assertEquals(registry.getClockThumbnail("clock_1"), mockThumbnail)
        assertEquals(registry.getClockThumbnail("clock_2"), mockThumbnail)
        assertEquals(registry.getClockPickerConfig("clock_1"), pickerConfig)
        assertEquals(registry.getClockPickerConfig("clock_2"), pickerConfig)
        verify(lifecycle1, never()).unloadPlugin()
        verify(lifecycle2, times(2)).unloadPlugin()
    }
+5 −1
Original line number Diff line number Diff line
@@ -72,6 +72,10 @@ class DefaultClockProviderTest : SysuiTestCase() {
            .thenReturn(mockSmallClockView)
        whenever(layoutInflater.inflate(eq(R.layout.clock_default_large), any(), anyBoolean()))
            .thenReturn(mockLargeClockView)
        whenever(resources.getString(R.string.clock_default_name))
            .thenReturn("DEFAULT_CLOCK_NAME")
        whenever(resources.getString(R.string.clock_default_description))
            .thenReturn("DEFAULT_CLOCK_DESC")
        whenever(resources.getDrawable(R.drawable.clock_default_thumbnail, null))
            .thenReturn(mockClockThumbnail)
        whenever(mockSmallClockView.getLayoutParams()).thenReturn(FrameLayout.LayoutParams(10, 10))
@@ -85,7 +89,7 @@ class DefaultClockProviderTest : SysuiTestCase() {
        // All providers need to provide clocks & thumbnails for exposed clocks
        for (metadata in provider.getClocks()) {
            assertNotNull(provider.createClock(metadata.clockId))
            assertNotNull(provider.getClockThumbnail(metadata.clockId))
            assertNotNull(provider.getClockPickerConfig(metadata.clockId))
        }
    }