Merge "Remove IdAndComplicationData from the public API" into androidx-main
diff --git a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ErrorMessagesTest.kt b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ErrorMessagesTest.kt
index 2fbbab8..ba63e9f 100644
--- a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ErrorMessagesTest.kt
+++ b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ErrorMessagesTest.kt
@@ -30,7 +30,6 @@
import androidx.compose.ui.semantics.SemanticsActions
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.util.expectErrorMessage
-import androidx.compose.ui.test.util.expectErrorMessageMatches
import androidx.compose.ui.test.util.expectErrorMessageStartsWith
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
@@ -62,10 +61,10 @@
}
expectErrorMessage(
- "" +
- "Failed: assertExists.\n" +
- "Reason: Expected exactly '1' node but could not find any node that satisfies: " +
- "(TestTag = 'MyButton3')"
+ """
+ Failed: assertExists.
+ Reason: Expected exactly '1' node but could not find any node that satisfies: (TestTag = 'MyButton3')
+ """.trimIndent()
) {
rule.onNodeWithTag("MyButton3")
.assertExists()
@@ -79,10 +78,11 @@
}
expectErrorMessage(
- "" +
- "Failed to perform a gesture.\n" +
- "Reason: Expected exactly '1' node but could not find any node that satisfies: " +
- "(TestTag = 'MyButton3')"
+ """
+ Failed to perform a gesture.
+ Reason: Expected exactly '1' node but could not find any node that satisfies: (TestTag = 'MyButton3')
+ """.trimIndent()
+
) {
rule.onNodeWithTag("MyButton3")
.performClick()
@@ -96,10 +96,10 @@
}
expectErrorMessage(
- "" +
- "Failed to perform a gesture.\n" +
- "Reason: Expected exactly '1' node but could not find any node that satisfies: " +
- "((TestTag = 'MyButton3') && (OnClick is defined))"
+ """
+ Failed to perform a gesture.
+ Reason: Expected exactly '1' node but could not find any node that satisfies: ((TestTag = 'MyButton3') && (OnClick is defined))
+ """.trimIndent()
) {
rule.onNode(hasTestTag("MyButton3") and hasClickAction())
.performClick()
@@ -113,12 +113,12 @@
}
expectErrorMessageStartsWith(
- "" +
- "Failed to perform a gesture.\n" +
- "Reason: Expected exactly '1' node but found '2' nodes that satisfy: " +
- "(Text = 'Toggle' (ignoreCase: false))\n" +
- "Nodes found:\n" +
- "1) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'MyButton'"
+ """
+ Failed to perform a gesture.
+ Reason: Expected exactly '1' node but found '2' nodes that satisfy: (Text = 'Toggle' (ignoreCase: false))
+ Nodes found:
+ 1) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'MyButton'
+ """.trimIndent()
) {
rule.onNodeWithText("Toggle")
.performClick()
@@ -132,10 +132,10 @@
}
expectErrorMessageStartsWith(
- "" +
- "Failed to perform OnClick action.\n" +
- "Reason: Expected exactly '1' node but could not find any node that satisfies: " +
- "(TestTag = 'MyButton3')"
+ """
+ Failed to perform OnClick action.
+ Reason: Expected exactly '1' node but could not find any node that satisfies: (TestTag = 'MyButton3')
+ """.trimIndent()
) {
rule.onNodeWithTag("MyButton3")
.performSemanticsAction(SemanticsActions.OnClick)
@@ -149,12 +149,12 @@
}
expectErrorMessageStartsWith(
- "" +
- "Failed: assertDoesNotExist.\n" +
- "Reason: Did not expect any node but found '1' node that satisfies: " +
- "(TestTag = 'MyButton')\n" +
- "Node found:\n" +
- "Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'MyButton'"
+ """
+ Failed: assertDoesNotExist.
+ Reason: Did not expect any node but found '1' node that satisfies: (TestTag = 'MyButton')
+ Node found:
+ Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'MyButton'
+ """.trimIndent()
) {
rule.onNodeWithTag("MyButton")
.assertDoesNotExist()
@@ -168,12 +168,12 @@
}
expectErrorMessageStartsWith(
- "" +
- "Failed to assert count of nodes.\n" +
- "Reason: Expected '3' nodes but found '2' nodes that satisfy: " +
- "(Text = 'Toggle' (ignoreCase: false))\n" +
- "Nodes found:\n" +
- "1) Node #X at (l=X, t=X, r=X, b=X)px"
+ """
+ Failed to assert count of nodes.
+ Reason: Expected '3' nodes but found '2' nodes that satisfy: (Text = 'Toggle' (ignoreCase: false))
+ Nodes found:
+ 1) Node #X at (l=X, t=X, r=X, b=X)px
+ """.trimIndent()
) {
rule.onAllNodesWithText("Toggle")
.assertCountEquals(3)
@@ -187,10 +187,10 @@
}
expectErrorMessage(
- "" +
- "Failed to assert count of nodes.\n" +
- "Reason: Expected '3' nodes but could not find any node that satisfies: " +
- "(Text = 'Toggle2' (ignoreCase: false))"
+ """
+ Failed to assert count of nodes.
+ Reason: Expected '3' nodes but could not find any node that satisfies: (Text = 'Toggle2' (ignoreCase: false))
+ """.trimIndent()
) {
rule.onAllNodesWithText("Toggle2")
.assertCountEquals(3)
@@ -209,15 +209,16 @@
rule.onNodeWithTag("MyButton")
.performClick()
- expectErrorMessageMatches(
- "" +
- "Failed to perform a gesture.\n" +
- "The node is no longer in the tree, last known semantics:\n" +
- "Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'Hello'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling\n" +
- "Original selector: Text = 'Hello' \\(ignoreCase: false\\)"
+ expectErrorMessage(
+ """
+ Failed to perform a gesture.
+ The node is no longer in the tree, last known semantics:
+ Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ Original selector: Text = 'Hello' (ignoreCase: false)
+ """.trimIndent()
) {
node.performClick()
}
@@ -236,15 +237,16 @@
rule.onNodeWithTag("MyButton")
.performClick()
- expectErrorMessageMatches(
- "" +
- "Failed: assertExists.\n" +
- "The node is no longer in the tree, last known semantics:\n" +
- "Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'Hello'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling\n" +
- "Original selector: Text = 'Hello' \\(ignoreCase: false\\)"
+ expectErrorMessage(
+ """
+ Failed: assertExists.
+ The node is no longer in the tree, last known semantics:
+ Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ Original selector: Text = 'Hello' (ignoreCase: false)
+ """.trimIndent()
) {
node.assertExists()
}
@@ -263,15 +265,16 @@
rule.onNodeWithTag("MyButton")
.performClick()
- expectErrorMessageMatches(
- "" +
- "Failed to assert the following: \\(OnClick is defined\\)\n" +
- "The node is no longer in the tree, last known semantics:\n" +
- "Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'Hello'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling\n" +
- "Original selector: Text = 'Hello' \\(ignoreCase: false\\)"
+ expectErrorMessage(
+ """
+ Failed to assert the following: (OnClick is defined)
+ The node is no longer in the tree, last known semantics:
+ Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ Original selector: Text = 'Hello' (ignoreCase: false)
+ """.trimIndent()
) {
node.assertHasClickAction()
}
diff --git a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/PrintToStringTest.kt b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/PrintToStringTest.kt
index bdf172f..3d7c59b 100644
--- a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/PrintToStringTest.kt
+++ b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/PrintToStringTest.kt
@@ -67,12 +67,14 @@
val result = rule.onNodeWithText("Hello")
.printToString(maxDepth = 0)
- assertThat(obfuscateNodesInfo(result)).matches(
- "" +
- "Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'Hello'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling"
+ assertThat(obfuscateNodesInfo(result)).isEqualTo(
+ """
+ Printing with useUnmergedTree = 'false'
+ Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ """.trimIndent()
)
}
@@ -86,16 +88,18 @@
.onChildren()
.printToString()
- assertThat(obfuscateNodesInfo(result)).matches(
- "" +
- "1\\) Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'Hello'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling\n" +
- "2\\) Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- "Text = 'World'\n" +
- "GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- "Has 1 sibling"
+ assertThat(obfuscateNodesInfo(result)).isEqualTo(
+ """
+ Printing with useUnmergedTree = 'false'
+ 1) Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ 2) Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'World'
+ Actions = [GetTextLayoutResult]
+ Has 1 sibling
+ """.trimIndent()
)
}
@@ -115,23 +119,23 @@
val result = rule.onRoot()
.printToString()
- assertThat(obfuscateNodesInfo(result)).matches(
- "" +
- "Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- " ..*Node #X at \\(l=X, t=X, r=X, b=X\\)px, Tag: 'column'\n" +
- " Disabled = 'kotlin.Unit'\n" +
- " .-Node #X at \\(l=X, t=X, r=X, b=X\\)px, Tag: 'box'\n" +
- " . Disabled = 'kotlin.Unit'\n" +
- " . .-Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- " . Role = 'Button'\n" +
- " . OnClick = 'AccessibilityAction\\(label=null, action=.*\\)'\n" +
- " . Text = 'Button'\n" +
- " . GetTextLayoutResult = 'AccessibilityAction\\(label=null, " +
- "action=.*\\)'\n" +
- " . MergeDescendants = 'true'\n" +
- " .-Node #X at \\(l=X, t=X, r=X, b=X\\)px\n" +
- " Text = 'Hello'\n" +
- " GetTextLayoutResult = 'AccessibilityAction\\(label=null, action=.*\\).*'"
+ assertThat(obfuscateNodesInfo(result)).isEqualTo(
+ """
+ Printing with useUnmergedTree = 'false'
+ Node #X at (l=X, t=X, r=X, b=X)px
+ |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'column'
+ [Disabled]
+ |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'box'
+ | [Disabled]
+ | |-Node #X at (l=X, t=X, r=X, b=X)px
+ | Role = 'Button'
+ | Text = 'Button'
+ | Actions = [OnClick, GetTextLayoutResult]
+ | MergeDescendants = 'true'
+ |-Node #X at (l=X, t=X, r=X, b=X)px
+ Text = 'Hello'
+ Actions = [GetTextLayoutResult]
+ """.trimIndent()
)
}
@@ -155,13 +159,15 @@
.printToString(maxDepth = 1)
assertThat(obfuscateNodesInfo(result)).isEqualTo(
- "" +
- "1) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag1'\n" +
- " |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag11'\n" +
- " Has 1 child\n" +
- "2) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag2'\n" +
- " |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag22'\n" +
- " Has 1 child"
+ """
+ Printing with useUnmergedTree = 'false'
+ 1) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag1'
+ |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag11'
+ Has 1 child
+ 2) Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag2'
+ |-Node #X at (l=X, t=X, r=X, b=X)px, Tag: 'tag22'
+ Has 1 child
+ """.trimIndent()
)
}
diff --git a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/util/Output.kt b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/util/Output.kt
index 83d6af9..a67ef92 100644
--- a/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/util/Output.kt
+++ b/compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/util/Output.kt
@@ -40,18 +40,6 @@
throw AssertionError("No AssertionError thrown!")
}
-internal fun expectErrorMessageMatches(expectedErrorMessage: String, block: () -> Unit) {
- try {
- block()
- } catch (e: AssertionError) {
- val received = obfuscateNodesInfo(e.localizedMessage!!)
- Truth.assertThat(received).matches(expectedErrorMessage.trim())
- return
- }
-
- throw AssertionError("No AssertionError thrown!")
-}
-
internal fun expectErrorMessageStartsWith(expectedErrorMessage: String, block: () -> Unit) {
try {
block()
diff --git a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Output.kt b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Output.kt
index f2780d1..5ac3060 100644
--- a/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Output.kt
+++ b/compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/Output.kt
@@ -17,6 +17,7 @@
package androidx.compose.ui.test
import androidx.compose.ui.geometry.Rect
+import androidx.compose.ui.semantics.AccessibilityAction
import androidx.compose.ui.semantics.SemanticsConfiguration
import androidx.compose.ui.semantics.SemanticsNode
import androidx.compose.ui.semantics.SemanticsProperties
@@ -42,7 +43,8 @@
maxDepth: Int = Int.MAX_VALUE
): String {
val result = fetchSemanticsNode()
- return result.printToString(maxDepth)
+ return "Printing with useUnmergedTree = '$useUnmergedTree'\n" +
+ result.printToString(maxDepth)
}
/**
@@ -84,11 +86,12 @@
maxDepth: Int = 0
): String {
val nodes = fetchSemanticsNodes()
- return if (nodes.isEmpty()) {
- "There were 0 nodes found!"
- } else {
- nodes.printToString(maxDepth)
- }
+ return "Printing with useUnmergedTree = '$useUnmergedTree'\n" +
+ if (nodes.isEmpty()) {
+ "There were 0 nodes found!"
+ } else {
+ nodes.printToString(maxDepth)
+ }
}
/**
@@ -218,11 +221,25 @@
}
private fun StringBuilder.appendConfigInfo(config: SemanticsConfiguration, indent: String = "") {
+ val actions = mutableListOf<String>()
+ val units = mutableListOf<String>()
for ((key, value) in config) {
if (key == SemanticsProperties.TestTag) {
continue
}
+ if (value is AccessibilityAction<*>) {
+ // Avoids printing stuff like "action = 'AccessibilityAction\(label=null, action=.*\)'"
+ actions.add(key.name)
+ continue
+ }
+
+ if (value is Unit) {
+ // Avoids printing stuff like "Disabled = 'kotlin.Unit'"
+ units.add(key.name)
+ continue
+ }
+
appendLine()
append(indent)
append(key.name)
@@ -244,6 +261,22 @@
append("'")
}
+ if (units.isNotEmpty()) {
+ appendLine()
+ append(indent)
+ append("[")
+ append(units.joinToString(separator = ", "))
+ append("]")
+ }
+
+ if (actions.isNotEmpty()) {
+ appendLine()
+ append(indent)
+ append("Actions = [")
+ append(actions.joinToString(separator = ", "))
+ append("]")
+ }
+
if (config.isMergingSemanticsOfDescendants) {
appendLine()
append(indent)
diff --git a/wear/wear-watchface/guava/build.gradle b/wear/wear-watchface/guava/build.gradle
index 642c937..a70be6e 100644
--- a/wear/wear-watchface/guava/build.gradle
+++ b/wear/wear-watchface/guava/build.gradle
@@ -31,6 +31,12 @@
api(project(":wear:wear-watchface"))
api(GUAVA_LISTENABLE_FUTURE)
+ androidTestImplementation(ANDROIDX_TEST_EXT_JUNIT)
+ androidTestImplementation(ANDROIDX_TEST_CORE)
+ androidTestImplementation(ANDROIDX_TEST_RUNNER)
+ androidTestImplementation(MOCKITO_CORE, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(DEXMAKER_MOCKITO, libs.exclude_bytebuddy) // DexMaker has it"s own MockMaker
+ androidTestImplementation(TRUTH)
testImplementation(ANDROIDX_TEST_CORE)
testImplementation(ANDROIDX_TEST_RUNNER)
testImplementation(ANDROIDX_TEST_RULES)
diff --git a/wear/wear-watchface/guava/src/androidTest/java/AsyncListenableWatchFaceServiceTest.kt b/wear/wear-watchface/guava/src/androidTest/java/AsyncListenableWatchFaceServiceTest.kt
new file mode 100644
index 0000000..1736917
--- /dev/null
+++ b/wear/wear-watchface/guava/src/androidTest/java/AsyncListenableWatchFaceServiceTest.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2021 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.
+ */
+
+import android.graphics.Canvas
+import android.graphics.Rect
+import android.icu.util.Calendar
+import android.os.Handler
+import android.os.Looper
+import android.view.SurfaceHolder
+import androidx.wear.watchface.CanvasType
+import androidx.wear.watchface.ListenableWatchFaceService
+import androidx.wear.watchface.MutableWatchState
+import androidx.wear.watchface.Renderer
+import androidx.wear.watchface.WatchFace
+import androidx.wear.watchface.WatchFaceType
+import androidx.wear.watchface.WatchState
+import androidx.wear.watchface.style.UserStyleRepository
+import androidx.wear.watchface.style.UserStyleSchema
+import com.google.common.truth.Truth.assertThat
+import com.google.common.util.concurrent.ListenableFuture
+import com.google.common.util.concurrent.SettableFuture
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.mockito.Mockito
+
+private const val REFERENCE_PREVIEW_TIME = 123456L
+
+private class FakeRenderer(
+ surfaceHolder: SurfaceHolder,
+ watchState: WatchState,
+ userStyleRepository: UserStyleRepository
+) : Renderer.CanvasRenderer(
+ surfaceHolder,
+ userStyleRepository,
+ watchState,
+ CanvasType.SOFTWARE,
+ 16
+) {
+ override fun render(canvas: Canvas, bounds: Rect, calendar: Calendar) {
+ }
+}
+
+private class TestAsyncListenableWatchFaceService(private val handler: Handler) :
+ ListenableWatchFaceService() {
+ override fun createWatchFaceFuture(
+ surfaceHolder: SurfaceHolder,
+ watchState: WatchState
+ ): ListenableFuture<WatchFace> {
+ val future = SettableFuture.create<WatchFace>()
+ val userStyleRepository = UserStyleRepository(
+ UserStyleSchema(emptyList())
+ )
+ // Post a task to resolve the future.
+ handler.post {
+ future.set(
+ WatchFace(
+ WatchFaceType.DIGITAL,
+ userStyleRepository,
+ FakeRenderer(surfaceHolder, watchState, userStyleRepository)
+ ).apply { setOverridePreviewReferenceTimeMillis(REFERENCE_PREVIEW_TIME) }
+ )
+ }
+ return future
+ }
+
+ suspend fun createWatchFaceForTest(
+ surfaceHolder: SurfaceHolder,
+ watchState: WatchState
+ ): WatchFace = createWatchFace(surfaceHolder, watchState)
+}
+
+/**
+ * Illustrates that createWatchFaceFuture can be resolved in a different task posted to the main
+ * looper.
+ */
+public class AsyncListenableWatchFaceServiceTest {
+
+ @Test
+ public fun asyncTest() {
+ val handler = Handler(Looper.getMainLooper())
+ val service = TestAsyncListenableWatchFaceService(handler)
+ val mockSurfaceHolder = Mockito.mock(SurfaceHolder::class.java)
+ Mockito.`when`(mockSurfaceHolder.surfaceFrame).thenReturn(Rect(0, 0, 100, 100))
+
+ runBlocking {
+ val watchFace = service.createWatchFaceForTest(
+ mockSurfaceHolder,
+ MutableWatchState().asWatchState()
+ )
+
+ // Simple check that [watchFace] looks sensible.
+ assertThat(watchFace.overridePreviewReferenceTimeMillis).isEqualTo(
+ REFERENCE_PREVIEW_TIME
+ )
+ }
+ }
+}
\ No newline at end of file
diff --git a/wear/wear-watchface/guava/src/test/java/androidx/wear/watchface/ListenableWatchFaceServiceTest.kt b/wear/wear-watchface/guava/src/test/java/androidx/wear/watchface/ListenableWatchFaceServiceTest.kt
index 095e53f..272465f 100644
--- a/wear/wear-watchface/guava/src/test/java/androidx/wear/watchface/ListenableWatchFaceServiceTest.kt
+++ b/wear/wear-watchface/guava/src/test/java/androidx/wear/watchface/ListenableWatchFaceServiceTest.kt
@@ -98,4 +98,4 @@
)
.doNotInstrumentPackage("androidx.wear.watchface")
.build()
-}
\ No newline at end of file
+}