Make EditorSession timeout if there's an error and make EditorSession.createOnWatchEditingSession NonNull
For incorrect ComponentName don't send null session, but instead
wait for a timeout and throw exception. Consequently,
EditorSession.createOnWatchEditingSession and EditorRequest.createFromIntent
won't return null.
Bug: 182792664
Test: Added EditingSessionTest.createOnWatchEditingSessionThrowsTimeoutException
Relnote: "We have made EditorSession.createOnWatchEditingSession throw TimeoutCancellationException if there's an error instead of sending null session. Additionally, return value of EditorRequest.createFromIntent and EditorSession.createOnWatchEditingSession is now NonNull."
Change-Id: I41eb47cbe25cdc5e945752f20cba0a56f3bbce05
diff --git a/wear/wear-watchface-editor/api/current.txt b/wear/wear-watchface-editor/api/current.txt
index f1dddbb..193bdea 100644
--- a/wear/wear-watchface-editor/api/current.txt
+++ b/wear/wear-watchface-editor/api/current.txt
@@ -14,7 +14,7 @@
public final class EditorRequest {
ctor @RequiresApi(android.os.Build.VERSION_CODES.R) public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle, @RequiresApi(android.os.Build.VERSION_CODES.R) androidx.wear.watchface.client.WatchFaceId watchFaceId);
ctor public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle);
- method public static androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
method public String getEditorPackageName();
method public androidx.wear.watchface.style.UserStyleData? getInitialUserStyle();
method public android.content.ComponentName getWatchFaceComponentName();
@@ -27,13 +27,13 @@
}
public static final class EditorRequest.Companion {
- method public androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
}
public abstract class EditorSession implements java.lang.AutoCloseable {
ctor public EditorSession();
- method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent);
+ method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent) throws kotlinx.coroutines.TimeoutCancellationException;
method public abstract Integer? getBackgroundComplicationId();
method @UiThread public abstract Integer? getComplicationIdAt(@Px int x, @Px int y);
method @UiThread public abstract suspend Object? getComplicationsPreviewData(kotlin.coroutines.Continuation<? super java.util.Map<java.lang.Integer,? extends androidx.wear.complications.data.ComplicationData>> p);
@@ -57,11 +57,12 @@
property public abstract android.content.ComponentName watchFaceComponentName;
property @RequiresApi(android.os.Build.VERSION_CODES.R) public abstract androidx.wear.watchface.client.WatchFaceId watchFaceId;
field public static final androidx.wear.watchface.editor.EditorSession.Companion Companion;
+ field public static final long EDITING_SESSION_TIMEOUT_MILLIS = 4000L; // 0xfa0L
}
public static final class EditorSession.Companion {
- method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p);
+ method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p) throws kotlinx.coroutines.TimeoutCancellationException;
}
public final class EditorSessionKt {
diff --git a/wear/wear-watchface-editor/api/public_plus_experimental_current.txt b/wear/wear-watchface-editor/api/public_plus_experimental_current.txt
index f1dddbb..193bdea 100644
--- a/wear/wear-watchface-editor/api/public_plus_experimental_current.txt
+++ b/wear/wear-watchface-editor/api/public_plus_experimental_current.txt
@@ -14,7 +14,7 @@
public final class EditorRequest {
ctor @RequiresApi(android.os.Build.VERSION_CODES.R) public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle, @RequiresApi(android.os.Build.VERSION_CODES.R) androidx.wear.watchface.client.WatchFaceId watchFaceId);
ctor public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle);
- method public static androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
method public String getEditorPackageName();
method public androidx.wear.watchface.style.UserStyleData? getInitialUserStyle();
method public android.content.ComponentName getWatchFaceComponentName();
@@ -27,13 +27,13 @@
}
public static final class EditorRequest.Companion {
- method public androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
}
public abstract class EditorSession implements java.lang.AutoCloseable {
ctor public EditorSession();
- method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent);
+ method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent) throws kotlinx.coroutines.TimeoutCancellationException;
method public abstract Integer? getBackgroundComplicationId();
method @UiThread public abstract Integer? getComplicationIdAt(@Px int x, @Px int y);
method @UiThread public abstract suspend Object? getComplicationsPreviewData(kotlin.coroutines.Continuation<? super java.util.Map<java.lang.Integer,? extends androidx.wear.complications.data.ComplicationData>> p);
@@ -57,11 +57,12 @@
property public abstract android.content.ComponentName watchFaceComponentName;
property @RequiresApi(android.os.Build.VERSION_CODES.R) public abstract androidx.wear.watchface.client.WatchFaceId watchFaceId;
field public static final androidx.wear.watchface.editor.EditorSession.Companion Companion;
+ field public static final long EDITING_SESSION_TIMEOUT_MILLIS = 4000L; // 0xfa0L
}
public static final class EditorSession.Companion {
- method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p);
+ method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p) throws kotlinx.coroutines.TimeoutCancellationException;
}
public final class EditorSessionKt {
diff --git a/wear/wear-watchface-editor/api/restricted_current.txt b/wear/wear-watchface-editor/api/restricted_current.txt
index 5ab6ecc..fedbc34 100644
--- a/wear/wear-watchface-editor/api/restricted_current.txt
+++ b/wear/wear-watchface-editor/api/restricted_current.txt
@@ -34,7 +34,7 @@
public final class EditorRequest {
ctor @RequiresApi(android.os.Build.VERSION_CODES.R) public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle, @RequiresApi(android.os.Build.VERSION_CODES.R) androidx.wear.watchface.client.WatchFaceId watchFaceId);
ctor public EditorRequest(android.content.ComponentName watchFaceComponentName, String editorPackageName, androidx.wear.watchface.style.UserStyleData? initialUserStyle);
- method public static androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
method public String getEditorPackageName();
method public androidx.wear.watchface.style.UserStyleData? getInitialUserStyle();
method public android.content.ComponentName getWatchFaceComponentName();
@@ -47,13 +47,13 @@
}
public static final class EditorRequest.Companion {
- method public androidx.wear.watchface.editor.EditorRequest? createFromIntent(android.content.Intent intent);
+ method @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public androidx.wear.watchface.editor.EditorRequest createFromIntent(android.content.Intent intent) throws kotlinx.coroutines.TimeoutCancellationException;
}
public abstract class EditorSession implements java.lang.AutoCloseable {
ctor public EditorSession();
- method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent);
+ method @RequiresApi(27) @UiThread public static final androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public static final suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity p, android.content.Intent activity, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> editIntent) throws kotlinx.coroutines.TimeoutCancellationException;
method public abstract Integer? getBackgroundComplicationId();
method @UiThread public abstract Integer? getComplicationIdAt(@Px int x, @Px int y);
method @UiThread public abstract suspend Object? getComplicationsPreviewData(kotlin.coroutines.Continuation<? super java.util.Map<java.lang.Integer,? extends androidx.wear.complications.data.ComplicationData>> p);
@@ -77,11 +77,12 @@
property public abstract android.content.ComponentName watchFaceComponentName;
property @RequiresApi(android.os.Build.VERSION_CODES.R) public abstract androidx.wear.watchface.client.WatchFaceId watchFaceId;
field public static final androidx.wear.watchface.editor.EditorSession.Companion Companion;
+ field public static final long EDITING_SESSION_TIMEOUT_MILLIS = 4000L; // 0xfa0L
}
public static final class EditorSession.Companion {
- method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession? createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
- method @UiThread public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p);
+ method @RequiresApi(27) @UiThread public androidx.wear.watchface.editor.EditorSession createHeadlessEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, androidx.wear.watchface.client.HeadlessWatchFaceClient headlessWatchFaceClient);
+ method @UiThread @kotlin.jvm.Throws(exceptionClasses=TimeoutCancellationException::class) public suspend Object? createOnWatchEditingSession(androidx.activity.ComponentActivity activity, android.content.Intent editIntent, kotlin.coroutines.Continuation<? super androidx.wear.watchface.editor.EditorSession> p) throws kotlinx.coroutines.TimeoutCancellationException;
}
public final class EditorSessionKt {
diff --git a/wear/wear-watchface-editor/guava/src/main/java/androidx/wear/watchface/editor/ListenableEditorSession.kt b/wear/wear-watchface-editor/guava/src/main/java/androidx/wear/watchface/editor/ListenableEditorSession.kt
index f6c92d1..4b36de1 100644
--- a/wear/wear-watchface-editor/guava/src/main/java/androidx/wear/watchface/editor/ListenableEditorSession.kt
+++ b/wear/wear-watchface-editor/guava/src/main/java/androidx/wear/watchface/editor/ListenableEditorSession.kt
@@ -34,6 +34,7 @@
import com.google.common.util.concurrent.ListenableFuture
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import kotlin.coroutines.CoroutineContext
@@ -48,6 +49,9 @@
* Constructs a [ListenableFuture] for a [ListenableEditorSession] for an on watch face
* editor. This registers an activity result handler and so it must be called during an
* Activity or Fragment initialization path.
+ *
+ * If watch face editor takes more than 4s to create a watch face, returned future will be
+ * resolved with [TimeoutCancellationException] exception.
*/
@SuppressWarnings("ExecutorRegistration")
@JvmStatic
@@ -69,9 +73,7 @@
coroutineScope.launch {
try {
result.set(
- createOnWatchEditingSession(activity, editIntent)?.let {
- ListenableEditorSession(it)
- }
+ ListenableEditorSession(createOnWatchEditingSession(activity, editIntent))
)
} catch (e: Exception) {
result.setException(e)
@@ -96,7 +98,7 @@
activity,
editIntent,
headlessWatchFaceClient
- )?.let {
+ ).let {
ListenableEditorSession(it)
}
}
diff --git a/wear/wear-watchface-editor/samples/src/main/java/androidx/wear/watchface/editor/sample/WatchFaceConfigActivity.kt b/wear/wear-watchface-editor/samples/src/main/java/androidx/wear/watchface/editor/sample/WatchFaceConfigActivity.kt
index 9a27f0e..2fe9c01 100644
--- a/wear/wear-watchface-editor/samples/src/main/java/androidx/wear/watchface/editor/sample/WatchFaceConfigActivity.kt
+++ b/wear/wear-watchface-editor/samples/src/main/java/androidx/wear/watchface/editor/sample/WatchFaceConfigActivity.kt
@@ -93,7 +93,7 @@
EditorSession.createOnWatchEditingSession(
this@WatchFaceConfigActivity,
intent!!
- )!!,
+ ),
object : FragmentController {
@SuppressLint("SyntheticAccessor")
override fun showConfigFragment() {
diff --git a/wear/wear-watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditingSessionTest.kt b/wear/wear-watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditingSessionTest.kt
index 4884ce4..fa6c96e 100644
--- a/wear/wear-watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditingSessionTest.kt
+++ b/wear/wear-watchface-editor/src/androidTest/java/androidx/wear/watchface/editor/EditingSessionTest.kt
@@ -68,6 +68,7 @@
import androidx.wear.watchface.complications.rendering.CanvasComplicationDrawable
import androidx.wear.watchface.complications.rendering.ComplicationDrawable
import androidx.wear.watchface.data.ComplicationBoundsType
+import androidx.wear.watchface.editor.EditorSession.Companion.EDITING_SESSION_TIMEOUT_MILLIS
import androidx.wear.watchface.editor.data.EditorStateWireFormat
import androidx.wear.watchface.style.CurrentUserStyleRepository
import androidx.wear.watchface.style.UserStyle
@@ -79,6 +80,7 @@
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.android.asCoroutineDispatcher
import kotlinx.coroutines.async
import kotlinx.coroutines.job
@@ -98,6 +100,7 @@
import org.mockito.Mockito.mock
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
+import java.util.concurrent.TimeUnit.MILLISECONDS
public const val LEFT_COMPLICATION_ID: Int = 1000
public const val RIGHT_COMPLICATION_ID: Int = 1001
@@ -121,6 +124,7 @@
public open class OnWatchFaceEditingTestActivity : ComponentActivity() {
public lateinit var editorSession: EditorSession
public lateinit var onCreateException: Exception
+ public val creationLatch: CountDownLatch = CountDownLatch(1)
public val listenableEditorSession: ListenableEditorSession by lazy {
ListenableEditorSession(editorSession)
@@ -141,9 +145,11 @@
this@OnWatchFaceEditingTestActivity,
intent!!,
providerInfoRetrieverProvider!!
- )!!
+ )
} catch (e: Exception) {
>
+ } finally {
+ creationLatch.countDown()
}
}
}
@@ -383,7 +389,8 @@
watchFaceId: WatchFaceId = testInstanceId,
previewReferenceTimeMillis: Long = 12345,
providerInfoRetrieverProvider: ProviderInfoRetrieverProvider =
- TestProviderInfoRetrieverProvider()
+ TestProviderInfoRetrieverProvider(),
+ shouldTimeout: Boolean = false
): ActivityScenario<OnWatchFaceEditingTestActivity> {
val userStyleRepository = CurrentUserStyleRepository(UserStyleSchema(userStyleSettings))
val complicationsManager = ComplicationsManager(complications, userStyleRepository)
@@ -411,7 +418,9 @@
onDestroyLatch.countDown()
}
}
- WatchFace.registerEditorDelegate(testComponentName, editorDelegate)
+ if (!shouldTimeout) {
+ WatchFace.registerEditorDelegate(testComponentName, editorDelegate)
+ }
OnWatchFaceEditingTestActivity.providerInfoRetrieverProvider = providerInfoRetrieverProvider
@@ -428,6 +437,12 @@
)
}
+ private fun createOnWatchFaceEditingTestActivityThatThrowsTimeoutException():
+ ActivityScenario<OnWatchFaceEditingTestActivity> =
+ createOnWatchFaceEditingTestActivity(
+ emptyList(), emptyList(), /* other params are default */ shouldTimeout = true
+ )
+
@After
public fun tearDown() {
ComplicationProviderChooserContract.useTestComplicationHelperActivity = false
@@ -437,6 +452,15 @@
}
@Test
+ public fun createOnWatchEditingSessionThrowsTimeoutException() {
+ val scenario = createOnWatchFaceEditingTestActivityThatThrowsTimeoutException()
+ lateinit var activity: OnWatchFaceEditingTestActivity
+ scenario.onActivity { activity = it }
+ activity.creationLatch.await(EDITING_SESSION_TIMEOUT_MILLIS + 500, MILLISECONDS)
+ assert(activity.onCreateException is TimeoutCancellationException)
+ }
+
+ @Test
public fun watchFaceComponentName() {
val scenario = createOnWatchFaceEditingTestActivity(emptyList(), emptyList())
scenario.onActivity {
@@ -1228,7 +1252,7 @@
)
assertThat(intent.getPackage()).isEqualTo(testEditorPackageName)
- val editorRequest = EditorRequest.createFromIntent(intent)!!
+ val editorRequest = EditorRequest.createFromIntent(intent)
assertThat(editorRequest.editorPackageName).isEqualTo(testEditorPackageName)
assertThat(editorRequest.initialUserStyle).isNull()
assertThat(editorRequest.watchFaceComponentName).isEqualTo(testComponentName)
diff --git a/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt b/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
index 40648f6..ab064c3 100644
--- a/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
+++ b/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/EditorSession.kt
@@ -68,6 +68,7 @@
import kotlinx.coroutines.cancel
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
+import kotlin.jvm.Throws
private typealias WireComplicationProviderInfo =
android.support.wearable.complications.ComplicationProviderInfo
@@ -183,14 +184,17 @@
* @param editIntent The [Intent] sent by SysUI to launch the editing session.
* @return Deferred<EditorSession?> which is resolved with either the [EditorSession] or
* `null` if it can't be constructed.
+ * @throws [TimeoutCancellationException] if it takes more than
+ * [EDITING_SESSION_TIMEOUT_MILLIS] milliseconds to create a watch face editor.
*/
@SuppressWarnings("ExecutorRegistration")
@JvmStatic
@UiThread
+ @Throws(TimeoutCancellationException::class)
public suspend fun createOnWatchEditingSession(
activity: ComponentActivity,
editIntent: Intent
- ): EditorSession? = createOnWatchEditingSessionImpl(
+ ): EditorSession = createOnWatchEditingSessionImpl(
activity,
editIntent,
object : ProviderInfoRetrieverProvider {
@@ -199,16 +203,17 @@
)
// Used by tests.
+ @Throws(TimeoutCancellationException::class)
internal suspend fun createOnWatchEditingSessionImpl(
activity: ComponentActivity,
editIntent: Intent,
providerInfoRetrieverProvider: ProviderInfoRetrieverProvider
- ): EditorSession? = TraceEvent(
+ ): EditorSession = TraceEvent(
"EditorSession.createOnWatchEditingSessionAsyncImpl"
).use {
val coroutineScope =
CoroutineScope(Handler(Looper.getMainLooper()).asCoroutineDispatcher().immediate)
- return EditorRequest.createFromIntent(editIntent)?.let { editorRequest ->
+ return EditorRequest.createFromIntent(editIntent).let { editorRequest ->
// We need to respect the lifecycle and register the ActivityResultListener now.
val session = OnWatchFaceEditorSessionImpl(
activity,
@@ -223,14 +228,15 @@
// [WatchFace.getOrCreateEditorDelegate] is async.
// Resolve only after init has been completed.
withContext(coroutineScope.coroutineContext) {
- session.setEditorDelegate(
- WatchFace.getOrCreateEditorDelegate(
- editorRequest.watchFaceComponentName
- ).await()
- )
-
- // Resolve only after init has been completed.
- session
+ withTimeout(EDITING_SESSION_TIMEOUT_MILLIS) {
+ session.setEditorDelegate(
+ WatchFace.getOrCreateEditorDelegate(
+ editorRequest.watchFaceComponentName
+ ).await()
+ )
+ // Resolve only after init has been completed.
+ session
+ }
}
}
}
@@ -250,8 +256,8 @@
activity: ComponentActivity,
editIntent: Intent,
headlessWatchFaceClient: HeadlessWatchFaceClient
- ): EditorSession? = TraceEvent("EditorSession.createHeadlessEditingSession").use {
- EditorRequest.createFromIntent(editIntent)?.let {
+ ): EditorSession = TraceEvent("EditorSession.createHeadlessEditingSession").use {
+ EditorRequest.createFromIntent(editIntent).let {
HeadlessEditorSession(
activity,
headlessWatchFaceClient,
@@ -267,6 +273,9 @@
)
}
}
+
+ /** Timeout allowed for waiting for creating the watch face editing session. */
+ public const val EDITING_SESSION_TIMEOUT_MILLIS: Long = 4000L
}
}
diff --git a/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt b/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
index 9408e35..8a139a6 100644
--- a/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
+++ b/wear/wear-watchface-editor/src/main/java/androidx/wear/watchface/editor/WatchFaceEditorContract.kt
@@ -22,7 +22,6 @@
import android.content.Context
import android.content.Intent
import android.os.Build
-import android.support.wearable.watchface.Constants
import androidx.activity.result.contract.ActivityResultContract
import androidx.annotation.RequiresApi
import androidx.wear.watchface.client.EditorServiceClient
@@ -31,6 +30,8 @@
import androidx.wear.watchface.client.WatchFaceId
import androidx.wear.watchface.style.UserStyle
import androidx.wear.watchface.style.UserStyleData
+import kotlinx.coroutines.TimeoutCancellationException
+import kotlin.jvm.Throws
internal const val INSTANCE_ID_KEY: String = "INSTANCE_ID_KEY"
internal const val COMPONENT_NAME_KEY: String = "COMPONENT_NAME_KEY"
@@ -82,17 +83,18 @@
/**
* Returns an [EditorRequest] saved to a [Intent] by [WatchFaceEditorContract.createIntent]
* if there is one or `null` otherwise. Intended for use by the watch face editor activity.
+ * @throws [TimeoutCancellationException] in case of en error.
*/
@SuppressLint("NewApi")
@JvmStatic
- public fun createFromIntent(intent: Intent): EditorRequest? {
+ @Throws(TimeoutCancellationException::class)
+ public fun createFromIntent(intent: Intent): EditorRequest {
val componentName =
- intent.getParcelableExtra<ComponentName>(COMPONENT_NAME_KEY)
- ?: intent.getParcelableExtra(Constants.EXTRA_WATCH_FACE_COMPONENT)
+ intent.getParcelableExtra<ComponentName>(COMPONENT_NAME_KEY)!!
val editorPackageName = intent.getPackage() ?: ""
val instanceId = WatchFaceId(intent.getStringExtra(INSTANCE_ID_KEY) ?: "")
val userStyleKey = intent.getStringArrayExtra(USER_STYLE_KEY)
- return componentName?.let {
+ return componentName.let {
if (userStyleKey != null) {
EditorRequest(
componentName,
@@ -101,8 +103,7 @@
HashMap<String, ByteArray>().apply {
for (i in userStyleKey.indices) {
val userStyleValue =
- intent.getByteArrayExtra(USER_STYLE_VALUES + i)
- ?: return null
+ intent.getByteArrayExtra(USER_STYLE_VALUES + i)!!
put(userStyleKey[i], userStyleValue)
}
}