Fix interaction between clearComplicationData and upper layer
Recent changes to complication handling introduced a StateFlow and
better equality operator for ComplicationData. This means
ComplicationSlotsManager#clearComplicationData which operates at a
level below this, was now dangerous since it would be sticky
despite WCS sending an updated complication when switching between
favourites (because from the StateFlow's point of view nothing
changed).
Bug: 264414533
Test: Manual testing plus new unit test
Change-Id: Iadc2f5e68283aca45504ce3a49d76169251ae83b
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
index b422068..9553f47 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/ComplicationSlotsManager.kt
@@ -33,7 +33,6 @@
import androidx.wear.watchface.complications.data.ComplicationData
import androidx.wear.watchface.complications.data.ComplicationExperimental
import androidx.wear.watchface.complications.data.ComplicationType
-import androidx.wear.watchface.complications.data.NoDataComplicationData
import androidx.wear.watchface.utility.TraceEvent
import androidx.wear.watchface.control.data.IdTypeAndDefaultProviderPolicyWireFormat
import androidx.wear.watchface.data.ComplicationStateWireFormat
@@ -355,13 +354,6 @@
complication.setComplicationData(data, false, instant)
}
- @UiThread
- internal fun clearComplicationData() {
- for ((_, complication) in complicationSlots) {
- complication.setComplicationData(NoDataComplicationData(), false, Instant.EPOCH)
- }
- }
-
/**
* For each slot, if the ComplicationData is timeline complication data then the correct
* override is selected for [instant].
diff --git a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
index 0876d02..247b69e 100644
--- a/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
+++ b/wear/watchface/watchface/src/main/java/androidx/wear/watchface/WatchFaceService.kt
@@ -1579,7 +1579,14 @@
internal suspend fun updateInstance(newInstanceId: String) {
val watchFaceImpl = deferredWatchFaceImpl.await()
// If the favorite ID has changed then the complications are probably invalid.
- watchFaceImpl.complicationSlotsManager.clearComplicationData()
+ setComplicationDataList(
+ watchFaceImpl.complicationSlotsManager.complicationSlots.map {
+ IdAndComplicationDataWireFormat(
+ it.key,
+ NoDataComplicationData().asWireComplicationData()
+ )
+ }
+ )
// However we may have valid complications cached.
readComplicationDataCache(_context, newInstanceId)?.let {
diff --git a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
index 7bcd27e..e83833b 100644
--- a/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
+++ b/wear/watchface/watchface/src/test/java/androidx/wear/watchface/WatchFaceServiceTest.kt
@@ -5915,6 +5915,63 @@
InteractiveInstanceManager.releaseInstance(NEW_ID)
}
+ @Test
+ public fun updateComplications_after_updateInstance() {
+ val complicationList = listOf(
+ IdAndComplicationDataWireFormat(
+ LEFT_COMPLICATION_ID,
+ ComplicationData.Builder(ComplicationData.TYPE_LONG_TEXT)
+ .setLongText(ComplicationText.plainText("TYPE_LONG_TEXT")).build()
+ ),
+ IdAndComplicationDataWireFormat(
+ RIGHT_COMPLICATION_ID,
+ ComplicationData.Builder(ComplicationData.TYPE_SHORT_TEXT)
+ .setShortText(ComplicationText.plainText("TYPE_SHORT_TEXT")).build()
+ )
+ )
+
+ initWallpaperInteractiveWatchFaceInstance(
+ WatchFaceType.ANALOG,
+ listOf(leftComplication, rightComplication),
+ UserStyleSchema(emptyList()),
+ WallpaperInteractiveWatchFaceInstanceParams(
+ INTERACTIVE_INSTANCE_ID,
+ DeviceConfig(
+ false,
+ false,
+ 0,
+ 0
+ ),
+ WatchUiState(false, 0),
+ UserStyle(emptyMap()).toWireFormat(),
+ null,
+ null
+ )
+ )
+
+ interactiveWatchFaceInstance.updateComplicationData(complicationList)
+
+ val NEW_ID = SYSTEM_SUPPORTS_CONSISTENT_IDS_PREFIX + "New"
+ runBlocking {
+ interactiveWatchFaceInstance.updateWatchfaceInstance(
+ NEW_ID,
+ UserStyleWireFormat(emptyMap())
+ )
+ }
+
+ assertThat(leftComplication.complicationData.value).isInstanceOf(
+ NoDataComplicationData::class.java)
+ assertThat(rightComplication.complicationData.value).isInstanceOf(
+ NoDataComplicationData::class.java)
+
+ interactiveWatchFaceInstance.updateComplicationData(complicationList)
+
+ assertThat(leftComplication.complicationData.value).isInstanceOf(
+ LongTextComplicationData::class.java)
+ assertThat(rightComplication.complicationData.value).isInstanceOf(
+ ShortTextComplicationData::class.java)
+ }
+
@OptIn(WatchFaceExperimental::class)
@Test
@RequiresApi(27)