Merge "Seed color setting to override theme color from WPPG" into tm-qpr-dev am: 81a3308db9

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21097576

Change-Id: Ib6a9ac2e575c4f17351a2f4470ca5d56b78b8da7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Hawkwood Glazier
2023-02-01 18:55:01 +00:00
committed by Automerger Merge Worker
5 changed files with 120 additions and 64 deletions

View File

@@ -21,15 +21,14 @@ import android.os.Handler
import android.provider.Settings import android.provider.Settings
import android.util.Log import android.util.Log
import androidx.annotation.OpenForTesting import androidx.annotation.OpenForTesting
import com.android.internal.annotations.Keep
import com.android.systemui.plugins.ClockController import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata import com.android.systemui.plugins.ClockMetadata
import com.android.systemui.plugins.ClockProvider import com.android.systemui.plugins.ClockProvider
import com.android.systemui.plugins.ClockProviderPlugin import com.android.systemui.plugins.ClockProviderPlugin
import com.android.systemui.plugins.ClockSettings
import com.android.systemui.plugins.PluginListener import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager import com.android.systemui.plugins.PluginManager
import org.json.JSONObject
private val TAG = ClockRegistry::class.simpleName private val TAG = ClockRegistry::class.simpleName
private const val DEBUG = true private const val DEBUG = true
@@ -64,34 +63,54 @@ open class ClockRegistry(
disconnectClocks(plugin) disconnectClocks(plugin)
} }
open var currentClockId: ClockId open var settings: ClockSettings?
get() { get() {
return try { try {
val json = Settings.Secure.getString( val json = Settings.Secure.getString(
context.contentResolver, context.contentResolver,
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE
) )
if (json == null || json.isEmpty()) { if (json == null || json.isEmpty()) {
return fallbackClockId return null
} }
ClockSetting.deserialize(json).clockId return ClockSettings.deserialize(json)
} catch (ex: Exception) { } catch (ex: Exception) {
Log.e(TAG, "Failed to parse clock setting", ex) Log.e(TAG, "Failed to parse clock settings", ex)
fallbackClockId return null
} }
} }
set(value) { protected set(value) {
try { try {
val json = ClockSetting.serialize(ClockSetting(value, System.currentTimeMillis())) val json = if (value != null) {
value._applied_timestamp = System.currentTimeMillis()
ClockSettings.serialize(value)
} else {
""
}
Settings.Secure.putString( Settings.Secure.putString(
context.contentResolver, context.contentResolver,
Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, json Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE, json
) )
} catch (ex: Exception) { } catch (ex: Exception) {
Log.e(TAG, "Failed to set clock setting", ex) Log.e(TAG, "Failed to set clock settings", ex)
} }
} }
private fun mutateSetting(mutator: (ClockSettings) -> Unit) {
val settings = this.settings ?: ClockSettings()
mutator(settings)
this.settings = settings
}
var currentClockId: ClockId
get() = settings?.clockId ?: fallbackClockId
set(value) { mutateSetting { it.clockId = value } }
var seedColor: Int?
get() = settings?.seedColor
set(value) { mutateSetting { it.seedColor = value } }
init { init {
connectClocks(defaultClockProvider) connectClocks(defaultClockProvider)
if (!availableClocks.containsKey(DEFAULT_CLOCK_ID)) { if (!availableClocks.containsKey(DEFAULT_CLOCK_ID)) {
@@ -194,36 +213,16 @@ open class ClockRegistry(
return createClock(DEFAULT_CLOCK_ID)!! return createClock(DEFAULT_CLOCK_ID)!!
} }
private fun createClock(clockId: ClockId): ClockController? = private fun createClock(clockId: ClockId): ClockController? {
availableClocks[clockId]?.provider?.createClock(clockId) val settings = this.settings ?: ClockSettings()
if (clockId != settings.clockId) {
settings.clockId = clockId
}
return availableClocks[clockId]?.provider?.createClock(settings)
}
private data class ClockInfo( private data class ClockInfo(
val metadata: ClockMetadata, val metadata: ClockMetadata,
val provider: ClockProvider val provider: ClockProvider
) )
@Keep
data class ClockSetting(
val clockId: ClockId,
val _applied_timestamp: Long?
) {
companion object {
private val KEY_CLOCK_ID = "clockId"
private val KEY_TIMESTAMP = "_applied_timestamp"
fun serialize(setting: ClockSetting): String {
return JSONObject()
.put(KEY_CLOCK_ID, setting.clockId)
.put(KEY_TIMESTAMP, setting._applied_timestamp)
.toString()
}
fun deserialize(jsonStr: String): ClockSetting {
val json = JSONObject(jsonStr)
return ClockSetting(
json.getString(KEY_CLOCK_ID),
if (!json.isNull(KEY_TIMESTAMP)) json.getLong(KEY_TIMESTAMP) else null)
}
}
}
} }

View File

@@ -29,6 +29,7 @@ import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockEvents import com.android.systemui.plugins.ClockEvents
import com.android.systemui.plugins.ClockFaceController import com.android.systemui.plugins.ClockFaceController
import com.android.systemui.plugins.ClockFaceEvents import com.android.systemui.plugins.ClockFaceEvents
import com.android.systemui.plugins.ClockSettings
import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter import java.io.PrintWriter
import java.util.Locale import java.util.Locale
@@ -46,6 +47,7 @@ class DefaultClockController(
ctx: Context, ctx: Context,
private val layoutInflater: LayoutInflater, private val layoutInflater: LayoutInflater,
private val resources: Resources, private val resources: Resources,
private val settings: ClockSettings?,
) : ClockController { ) : ClockController {
override val smallClock: DefaultClockFaceController override val smallClock: DefaultClockFaceController
override val largeClock: LargeClockFaceController override val largeClock: LargeClockFaceController
@@ -66,12 +68,14 @@ class DefaultClockController(
smallClock = smallClock =
DefaultClockFaceController( DefaultClockFaceController(
layoutInflater.inflate(R.layout.clock_default_small, parent, false) layoutInflater.inflate(R.layout.clock_default_small, parent, false)
as AnimatableClockView as AnimatableClockView,
settings?.seedColor
) )
largeClock = largeClock =
LargeClockFaceController( LargeClockFaceController(
layoutInflater.inflate(R.layout.clock_default_large, parent, false) layoutInflater.inflate(R.layout.clock_default_large, parent, false)
as AnimatableClockView as AnimatableClockView,
settings?.seedColor
) )
clocks = listOf(smallClock.view, largeClock.view) clocks = listOf(smallClock.view, largeClock.view)
@@ -91,6 +95,7 @@ class DefaultClockController(
open inner class DefaultClockFaceController( open inner class DefaultClockFaceController(
override val view: AnimatableClockView, override val view: AnimatableClockView,
val seedColor: Int?,
) : ClockFaceController { ) : ClockFaceController {
// MAGENTA is a placeholder, and will be assigned correctly in initialize // MAGENTA is a placeholder, and will be assigned correctly in initialize
@@ -105,6 +110,9 @@ class DefaultClockController(
} }
init { init {
if (seedColor != null) {
currentColor = seedColor
}
view.setColors(currentColor, currentColor) view.setColors(currentColor, currentColor)
} }
@@ -132,7 +140,9 @@ class DefaultClockController(
fun updateColor() { fun updateColor() {
val color = val color =
if (isRegionDark) { if (seedColor != null) {
seedColor
} else if (isRegionDark) {
resources.getColor(android.R.color.system_accent1_100) resources.getColor(android.R.color.system_accent1_100)
} else { } else {
resources.getColor(android.R.color.system_accent2_600) resources.getColor(android.R.color.system_accent2_600)
@@ -152,7 +162,8 @@ class DefaultClockController(
inner class LargeClockFaceController( inner class LargeClockFaceController(
view: AnimatableClockView, view: AnimatableClockView,
) : DefaultClockFaceController(view) { seedColor: Int?,
) : DefaultClockFaceController(view, seedColor) {
override fun recomputePadding(targetRegion: Rect?) { override fun recomputePadding(targetRegion: Rect?) {
// We center the view within the targetRegion instead of within the parent // We center the view within the targetRegion instead of within the parent
// view by computing the difference and adding that to the padding. // view by computing the difference and adding that to the padding.

View File

@@ -22,6 +22,7 @@ import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata import com.android.systemui.plugins.ClockMetadata
import com.android.systemui.plugins.ClockProvider import com.android.systemui.plugins.ClockProvider
import com.android.systemui.plugins.ClockSettings
private val TAG = DefaultClockProvider::class.simpleName private val TAG = DefaultClockProvider::class.simpleName
const val DEFAULT_CLOCK_NAME = "Default Clock" const val DEFAULT_CLOCK_NAME = "Default Clock"
@@ -36,12 +37,12 @@ class DefaultClockProvider constructor(
override fun getClocks(): List<ClockMetadata> = override fun getClocks(): List<ClockMetadata> =
listOf(ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME)) listOf(ClockMetadata(DEFAULT_CLOCK_ID, DEFAULT_CLOCK_NAME))
override fun createClock(id: ClockId): ClockController { override fun createClock(settings: ClockSettings): ClockController {
if (id != DEFAULT_CLOCK_ID) { if (settings.clockId != DEFAULT_CLOCK_ID) {
throw IllegalArgumentException("$id is unsupported by $TAG") throw IllegalArgumentException("${settings.clockId} is unsupported by $TAG")
} }
return DefaultClockController(ctx, layoutInflater, resources) return DefaultClockController(ctx, layoutInflater, resources, settings)
} }
override fun getClockThumbnail(id: ClockId): Drawable? { override fun getClockThumbnail(id: ClockId): Drawable? {

View File

@@ -17,11 +17,13 @@ import android.content.res.Resources
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import com.android.internal.annotations.Keep
import com.android.systemui.plugins.annotations.ProvidesInterface import com.android.systemui.plugins.annotations.ProvidesInterface
import com.android.systemui.plugins.log.LogBuffer import com.android.systemui.plugins.log.LogBuffer
import java.io.PrintWriter import java.io.PrintWriter
import java.util.Locale import java.util.Locale
import java.util.TimeZone import java.util.TimeZone
import org.json.JSONObject
/** Identifies a clock design */ /** Identifies a clock design */
typealias ClockId = String typealias ClockId = String
@@ -41,7 +43,13 @@ interface ClockProvider {
fun getClocks(): List<ClockMetadata> fun getClocks(): List<ClockMetadata>
/** Initializes and returns the target clock design */ /** Initializes and returns the target clock design */
fun createClock(id: ClockId): ClockController @Deprecated("Use overload with ClockSettings")
fun createClock(id: ClockId): ClockController {
return createClock(ClockSettings(id, null, null))
}
/** Initializes and returns the target clock design */
fun createClock(settings: ClockSettings): ClockController
/** A static thumbnail for rendering in some examples */ /** A static thumbnail for rendering in some examples */
fun getClockThumbnail(id: ClockId): Drawable? fun getClockThumbnail(id: ClockId): Drawable?
@@ -62,7 +70,11 @@ interface ClockController {
val animations: ClockAnimations val animations: ClockAnimations
/** Initializes various rendering parameters. If never called, provides reasonable defaults. */ /** Initializes various rendering parameters. If never called, provides reasonable defaults. */
fun initialize(resources: Resources, dozeFraction: Float, foldFraction: Float) { fun initialize(
resources: Resources,
dozeFraction: Float,
foldFraction: Float,
) {
events.onColorPaletteChanged(resources) events.onColorPaletteChanged(resources)
animations.doze(dozeFraction) animations.doze(dozeFraction)
animations.fold(foldFraction) animations.fold(foldFraction)
@@ -167,3 +179,34 @@ data class ClockMetadata(
val clockId: ClockId, val clockId: ClockId,
val name: String, val name: String,
) )
/** Structure for keeping clock-specific settings */
@Keep
data class ClockSettings(
var clockId: ClockId? = null,
var seedColor: Int? = null,
var _applied_timestamp: Long? = null,
) {
companion object {
private val KEY_CLOCK_ID = "clockId"
private val KEY_SEED_COLOR = "seedColor"
private val KEY_TIMESTAMP = "_applied_timestamp"
fun serialize(setting: ClockSettings): String {
return JSONObject()
.put(KEY_CLOCK_ID, setting.clockId)
.put(KEY_SEED_COLOR, setting.seedColor)
.put(KEY_TIMESTAMP, setting._applied_timestamp)
.toString()
}
fun deserialize(jsonStr: String): ClockSettings {
val json = JSONObject(jsonStr)
return ClockSettings(
json.getString(KEY_CLOCK_ID),
if (!json.isNull(KEY_SEED_COLOR)) json.getInt(KEY_SEED_COLOR) else null,
if (!json.isNull(KEY_TIMESTAMP)) json.getLong(KEY_TIMESTAMP) else null
)
}
}
}

View File

@@ -27,6 +27,7 @@ import com.android.systemui.plugins.ClockController
import com.android.systemui.plugins.ClockId import com.android.systemui.plugins.ClockId
import com.android.systemui.plugins.ClockMetadata import com.android.systemui.plugins.ClockMetadata
import com.android.systemui.plugins.ClockProviderPlugin import com.android.systemui.plugins.ClockProviderPlugin
import com.android.systemui.plugins.ClockSettings
import com.android.systemui.plugins.PluginListener import com.android.systemui.plugins.PluginListener
import com.android.systemui.plugins.PluginManager import com.android.systemui.plugins.PluginManager
import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.argumentCaptor
@@ -59,7 +60,7 @@ class ClockRegistryTest : SysuiTestCase() {
private lateinit var pluginListener: PluginListener<ClockProviderPlugin> private lateinit var pluginListener: PluginListener<ClockProviderPlugin>
private lateinit var registry: ClockRegistry private lateinit var registry: ClockRegistry
private var settingValue: String = "" private var settingValue: ClockSettings? = null
companion object { companion object {
private fun failFactory(): ClockController { private fun failFactory(): ClockController {
@@ -79,7 +80,8 @@ class ClockRegistryTest : SysuiTestCase() {
private val thumbnailCallbacks = mutableMapOf<ClockId, () -> Drawable?>() private val thumbnailCallbacks = mutableMapOf<ClockId, () -> Drawable?>()
override fun getClocks() = metadata override fun getClocks() = metadata
override fun createClock(id: ClockId): ClockController = createCallbacks[id]!!() override fun createClock(settings: ClockSettings): ClockController =
createCallbacks[settings.clockId!!]!!()
override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!() override fun getClockThumbnail(id: ClockId): Drawable? = thumbnailCallbacks[id]!!()
fun addClock( fun addClock(
@@ -110,7 +112,7 @@ class ClockRegistryTest : SysuiTestCase() {
userHandle = UserHandle.USER_ALL, userHandle = UserHandle.USER_ALL,
defaultClockProvider = fakeDefaultProvider defaultClockProvider = fakeDefaultProvider
) { ) {
override var currentClockId: ClockId override var settings: ClockSettings?
get() = settingValue get() = settingValue
set(value) { settingValue = value } set(value) { settingValue = value }
} }
@@ -185,7 +187,7 @@ class ClockRegistryTest : SysuiTestCase() {
.addClock("clock_1", "clock 1") .addClock("clock_1", "clock 1")
.addClock("clock_2", "clock 2") .addClock("clock_2", "clock 2")
settingValue = "clock_3" settingValue = ClockSettings("clock_3", null, null)
val plugin2 = FakeClockPlugin() val plugin2 = FakeClockPlugin()
.addClock("clock_3", "clock 3", { mockClock }) .addClock("clock_3", "clock 3", { mockClock })
.addClock("clock_4", "clock 4") .addClock("clock_4", "clock 4")
@@ -203,7 +205,7 @@ class ClockRegistryTest : SysuiTestCase() {
.addClock("clock_1", "clock 1") .addClock("clock_1", "clock 1")
.addClock("clock_2", "clock 2") .addClock("clock_2", "clock 2")
settingValue = "clock_3" settingValue = ClockSettings("clock_3", null, null)
val plugin2 = FakeClockPlugin() val plugin2 = FakeClockPlugin()
.addClock("clock_3", "clock 3") .addClock("clock_3", "clock 3")
.addClock("clock_4", "clock 4") .addClock("clock_4", "clock 4")
@@ -222,7 +224,7 @@ class ClockRegistryTest : SysuiTestCase() {
.addClock("clock_1", "clock 1") .addClock("clock_1", "clock 1")
.addClock("clock_2", "clock 2") .addClock("clock_2", "clock 2")
settingValue = "clock_3" settingValue = ClockSettings("clock_3", null, null)
val plugin2 = FakeClockPlugin() val plugin2 = FakeClockPlugin()
.addClock("clock_3", "clock 3", { mockClock }) .addClock("clock_3", "clock 3", { mockClock })
.addClock("clock_4", "clock 4") .addClock("clock_4", "clock 4")
@@ -242,8 +244,8 @@ class ClockRegistryTest : SysuiTestCase() {
@Test @Test
fun jsonDeserialization_gotExpectedObject() { fun jsonDeserialization_gotExpectedObject() {
val expected = ClockRegistry.ClockSetting("ID", 500) val expected = ClockSettings("ID", null, 500)
val actual = ClockRegistry.ClockSetting.deserialize("""{ val actual = ClockSettings.deserialize("""{
"clockId":"ID", "clockId":"ID",
"_applied_timestamp":500 "_applied_timestamp":500
}""") }""")
@@ -252,15 +254,15 @@ class ClockRegistryTest : SysuiTestCase() {
@Test @Test
fun jsonDeserialization_noTimestamp_gotExpectedObject() { fun jsonDeserialization_noTimestamp_gotExpectedObject() {
val expected = ClockRegistry.ClockSetting("ID", null) val expected = ClockSettings("ID", null, null)
val actual = ClockRegistry.ClockSetting.deserialize("{\"clockId\":\"ID\"}") val actual = ClockSettings.deserialize("{\"clockId\":\"ID\"}")
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@Test @Test
fun jsonDeserialization_nullTimestamp_gotExpectedObject() { fun jsonDeserialization_nullTimestamp_gotExpectedObject() {
val expected = ClockRegistry.ClockSetting("ID", null) val expected = ClockSettings("ID", null, null)
val actual = ClockRegistry.ClockSetting.deserialize("""{ val actual = ClockSettings.deserialize("""{
"clockId":"ID", "clockId":"ID",
"_applied_timestamp":null "_applied_timestamp":null
}""") }""")
@@ -269,22 +271,22 @@ class ClockRegistryTest : SysuiTestCase() {
@Test(expected = JSONException::class) @Test(expected = JSONException::class)
fun jsonDeserialization_noId_threwException() { fun jsonDeserialization_noId_threwException() {
val expected = ClockRegistry.ClockSetting("ID", 500) val expected = ClockSettings("ID", null, 500)
val actual = ClockRegistry.ClockSetting.deserialize("{\"_applied_timestamp\":500}") val actual = ClockSettings.deserialize("{\"_applied_timestamp\":500}")
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@Test @Test
fun jsonSerialization_gotExpectedString() { fun jsonSerialization_gotExpectedString() {
val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}" val expected = "{\"clockId\":\"ID\",\"_applied_timestamp\":500}"
val actual = ClockRegistry.ClockSetting.serialize( ClockRegistry.ClockSetting("ID", 500)) val actual = ClockSettings.serialize(ClockSettings("ID", null, 500))
assertEquals(expected, actual) assertEquals(expected, actual)
} }
@Test @Test
fun jsonSerialization_noTimestamp_gotExpectedString() { fun jsonSerialization_noTimestamp_gotExpectedString() {
val expected = "{\"clockId\":\"ID\"}" val expected = "{\"clockId\":\"ID\"}"
val actual = ClockRegistry.ClockSetting.serialize( ClockRegistry.ClockSetting("ID", null)) val actual = ClockSettings.serialize(ClockSettings("ID", null, null))
assertEquals(expected, actual) assertEquals(expected, actual)
} }
} }