Merge "Fix menu closing on soft keyboard input" into androidx-main
diff --git a/.github/workflows/integration_tests.yml b/.github/workflows/integration_tests.yml
index db2e46a..cb49084 100644
--- a/.github/workflows/integration_tests.yml
+++ b/.github/workflows/integration_tests.yml
@@ -25,6 +25,12 @@
           gcp-token: ${{ secrets.GCP_SA_KEY }}
           github-token: ${{ secrets.GITHUB_TOKEN }}
           output-folder: ${{ steps.dirs.outputs.output-dir }}
+          gcp-bucket-name: "androidx-ftl-test-results"
+          gcp-bucket-path: "github-ci-action"
+          log-file: ${{ steps.dirs.outputs.output-dir }}/ftl-logs.txt
+          device-specs: Pixel2.arm:30
+          use-test-config-files: true
+          test-suite-tags: androidx_unit_tests
       - uses: actions/upload-artifact@v2
         if: always()
         with:
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
index a720034..58eb98a 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/Capability.kt
@@ -127,7 +127,7 @@
          * calling one will nullify the other.
          *
          * This method accepts a coroutine-based ExecutionCallback instance. There is also an
-         * overload which accepts the ExecutionCallbackAsync instead.
+         * overload which accepts the [ExecutionCallbackAsync] instead.
          */
         @SuppressLint("MissingGetterMatchingBuilder")
         fun setExecutionCallback(executionCallback: ExecutionCallback<ArgumentsT, OutputT>) =
@@ -136,13 +136,13 @@
             }
 
         /**
-         * Sets the ExecutionCallbackAsync for this capability.
+         * Sets the [ExecutionCallbackAsync] for this capability.
          *
-         * setExecutionSessionFactory and setExecutionCallback are mutually exclusive, so calling
-         * one will nullify the other.
+         * [setExecutionSessionFactory] and [setExecutionCallback] are mutually exclusive, so
+         * calling one will nullify the other.
          *
-         * This method accepts the ExecutionCallbackAsync interface which returns a
-         * [ListenableFuture].
+         * This method accepts the [ExecutionCallbackAsync] interface, which is the Future version
+         * of [ExecutionCallback]
          */
         @SuppressLint("MissingGetterMatchingBuilder")
         fun setExecutionCallback(
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
index 564a173..b3cdb06 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/HostProperties.kt
@@ -52,7 +52,7 @@
          * Builds and returns the HostProperties instance.
          */
         fun build() = HostProperties(
-            requireNotNull(maxHostSizeDp, { "maxHostSizeDp must be set." }),
+            requireNotNull(maxHostSizeDp) { "maxHostSizeDp must be set." },
         )
     }
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SearchAction.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SearchAction.kt
index 10beb9a..03648fd 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SearchAction.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/SearchAction.kt
@@ -35,6 +35,12 @@
         return true
     }
 
+    override fun hashCode(): Int {
+        var result = query?.hashCode() ?: 0
+        result += 31 * (filter?.hashCode() ?: 0)
+        return result
+    }
+
     /** Builder class for Entity. */
     class Builder<FilterT> {
         private var query: String? = null
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
index e1734cb..9fac8e1 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupCandidate.kt
@@ -22,7 +22,7 @@
 ) {
 
     override fun toString(): String {
-        return "EntityLookupCandidate(cadidate=$candidate)"
+        return "EntityLookupCandidate(candidate=$candidate)"
     }
 
     override fun equals(other: Any?): Boolean {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
index 029e261..1f3f166 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/entity/EntityLookupResponse.kt
@@ -56,7 +56,7 @@
         private var candidateList: List<EntityLookupCandidate<T>> = listOf()
 
         @property:EntityLookupStatus
-        private var status: Int = EntityLookupResponse.SUCCESS
+        private var status: Int = SUCCESS
         private var nextPageToken: ByteString? = null
         fun setCandidateList(candidateList: List<EntityLookupCandidate<T>>): Builder<T> = apply {
             this.candidateList = candidateList
@@ -71,7 +71,7 @@
             this.nextPageToken = nextPageToken
         }
 
-        fun build() = EntityLookupResponse<T>(candidateList, status, nextPageToken)
+        fun build() = EntityLookupResponse(candidateList, status, nextPageToken)
     }
 
     companion object {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.java
index 51a4614..1486f0b 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/concurrent/Futures.java
@@ -122,7 +122,7 @@
             }
 
             @Override
-            public void onFailure(Throwable failure) {
+            public void onFailure(@NonNull Throwable failure) {
                 completer.setException(failure);
             }
         };
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverter.kt
index 6c7a290..05072dd 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverter.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/EntityConverter.kt
@@ -43,13 +43,13 @@
             }
         }
 
-        internal fun valueToEntity(value: Value): Entity {
+        private fun valueToEntity(value: Value): Entity {
             val builder = Entity.newBuilder()
             when {
-                value.hasStringValue() -> builder.setStringValue(value.getStringValue())
-                value.hasBoolValue() -> builder.setBoolValue(value.getBoolValue())
-                value.hasNumberValue() -> builder.setNumberValue(value.getNumberValue())
-                value.hasStructValue() -> builder.setStructValue(value.getStructValue())
+                value.hasStringValue() -> builder.stringValue = value.stringValue
+                value.hasBoolValue() -> builder.boolValue = value.boolValue
+                value.hasNumberValue() -> builder.numberValue = value.numberValue
+                value.hasStructValue() -> builder.structValue = value.structValue
                 else -> throw IllegalStateException("cannot convert $value into Entity.")
             }
             return builder.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverter.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverter.kt
index df74750..a2ec085 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverter.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/ParamValueConverter.kt
@@ -54,10 +54,10 @@
         internal fun paramValueToValue(paramValue: ParamValue): Value {
             val builder = Value.newBuilder()
             when {
-                paramValue.hasStringValue() -> builder.setStringValue(paramValue.getStringValue())
-                paramValue.hasBoolValue() -> builder.setBoolValue(paramValue.getBoolValue())
-                paramValue.hasNumberValue() -> builder.setNumberValue(paramValue.getNumberValue())
-                paramValue.hasStructValue() -> builder.setStructValue(paramValue.getStructValue())
+                paramValue.hasStringValue() -> builder.stringValue = paramValue.stringValue
+                paramValue.hasBoolValue() -> builder.boolValue = paramValue.boolValue
+                paramValue.hasNumberValue() -> builder.numberValue = paramValue.numberValue
+                paramValue.hasStructValue() -> builder.structValue = paramValue.structValue
                 else -> throw StructConversionException("cannot convert $paramValue into Value.")
             }
             return builder.build()
@@ -66,10 +66,10 @@
         internal fun valueToParamValue(value: Value): ParamValue {
             val builder = ParamValue.newBuilder()
             when {
-                value.hasStringValue() -> builder.setStringValue(value.getStringValue())
-                value.hasBoolValue() -> builder.setBoolValue(value.getBoolValue())
-                value.hasNumberValue() -> builder.setNumberValue(value.getNumberValue())
-                value.hasStructValue() -> builder.setStructValue(value.getStructValue())
+                value.hasStringValue() -> builder.stringValue = value.stringValue
+                value.hasBoolValue() -> builder.boolValue = value.boolValue
+                value.hasNumberValue() -> builder.numberValue = value.numberValue
+                value.hasStructValue() -> builder.structValue = value.structValue
                 else -> throw IllegalStateException("cannot convert $value to ParamValue.")
             }
             return builder.build()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
index a963bf6..8d26ad7 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeConverters.java
@@ -373,15 +373,15 @@
         return TypeSpecBuilder.newBuilder(
                         "SearchAction",
                         SearchAction.Builder<T>::new,
-                        SearchAction.Builder<T>::build)
+                        SearchAction.Builder::build)
                 .bindStringField(
                         "query",
                         SearchAction::getQuery,
-                        SearchAction.Builder<T>::setQuery)
+                        SearchAction.Builder::setQuery)
                 .bindSpecField(
                         "filter",
                         SearchAction::getFilter,
-                        SearchAction.Builder<T>::setFilter,
+                        SearchAction.Builder::setFilter,
                         nestedTypeSpec)
                 .build();
     }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpec.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpec.kt
index fbb5d4a..4656db6 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpec.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpec.kt
@@ -47,7 +47,7 @@
             ): Value = Value.newBuilder().setStringValue(obj).build()
 
             override fun fromValue(value: Value): String = when {
-                value.hasStringValue() -> value.getStringValue()
+                value.hasStringValue() -> value.stringValue
                 else -> throw StructConversionException("STRING_TYPE_SPEC cannot convert $value")
             }
         }
@@ -61,7 +61,7 @@
             ): Value = Value.newBuilder().setBoolValue(obj).build()
 
             override fun fromValue(value: Value): Boolean = when {
-                value.hasBoolValue() -> value.getBoolValue()
+                value.hasBoolValue() -> value.boolValue
                 else -> throw StructConversionException("BOOL_TYPE_SPEC cannot convert $value")
             }
         }
@@ -75,7 +75,7 @@
             ): Value = Value.newBuilder().setNumberValue(obj).build()
 
             override fun fromValue(value: Value): Double = when {
-                value.hasNumberValue() -> value.getNumberValue()
+                value.hasNumberValue() -> value.numberValue
                 else -> throw StructConversionException("NUMBER_TYPE_SPEC cannot convert $value")
             }
         }
@@ -89,7 +89,7 @@
             ): Value = Value.newBuilder().setNumberValue(obj.toDouble()).build()
 
             override fun fromValue(value: Value): Int = when {
-                value.hasNumberValue() -> value.getNumberValue().toInt()
+                value.hasNumberValue() -> value.numberValue.toInt()
                 else -> throw StructConversionException("INTEGER_TYPE_SPEC cannot convert $value")
             }
         }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecBuilder.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecBuilder.java
index 21c30a6..279e65c 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecBuilder.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/TypeSpecBuilder.java
@@ -305,9 +305,7 @@
                     }
                     return spec.toValue(value);
                 },
-                (builder, value) -> {
-                    valueSetter.accept(builder, spec.fromValue(value));
-                });
+                (builder, value) -> valueSetter.accept(builder, spec.fromValue(value)));
     }
 
     /** binds a repeated spec field to read from / write to Struct. */
@@ -321,7 +319,7 @@
                 valueGetter,
                 valueSetter,
                 spec::toValue,
-                (value) -> spec.fromValue(value));
+                spec::fromValue);
     }
 
     TypeSpec<T> build() {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpec.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpec.kt
index 8f161a6..025c5fa 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpec.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/converters/UnionTypeSpec.kt
@@ -25,9 +25,9 @@
     private val bindings: List<MemberBinding<T, *>>,
 ) : TypeSpec<T> {
     internal class MemberBinding<T, M>(
-        val memberGetter: (T) -> M?,
-        val ctor: (M) -> T,
-        val typeSpec: TypeSpec<M>,
+        private val memberGetter: (T) -> M?,
+        private val ctor: (M) -> T,
+        private val typeSpec: TypeSpec<M>,
     ) {
         @Throws(StructConversionException::class)
         fun tryDeserialize(value: Value): T {
@@ -48,7 +48,7 @@
     }
 
     private fun getApplicableBinding(obj: T): MemberBinding<T, *> {
-        var applicableBindings = bindings.filter { it.isMemberSet(obj) }
+        val applicableBindings = bindings.filter { it.isMemberSet(obj) }
         return when (applicableBindings.size) {
             0 -> throw IllegalStateException("$obj is invalid, all union members are null.")
             1 -> applicableBindings[0]
@@ -95,6 +95,6 @@
             )
         }
 
-        fun build() = UnionTypeSpec<T>(bindings.toList())
+        fun build() = UnionTypeSpec(bindings.toList())
     }
 }
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
index 9601c24..d4d418a 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/TaskHandler.kt
@@ -35,7 +35,7 @@
     internal val confirmationDataBindings: Map<String, (ConfirmationT) -> List<ParamValue>>,
     internal val onReadyToConfirmListener: OnReadyToConfirmListener<ArgumentsT, ConfirmationT>?,
 ) {
-    class Builder<ArgumentsT, ConfirmationT>() {
+    class Builder<ArgumentsT, ConfirmationT> {
         private val mutableTaskParamMap = mutableMapOf<String, TaskParamBinding<*>>()
         private val confirmationDataBindings =
             mutableMapOf<String, (ConfirmationT) -> List<ParamValue>>()
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/DisambigStateException.java b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/DisambigStateException.java
index af225a1..616c7b3 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/DisambigStateException.java
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/task/exceptions/DisambigStateException.java
@@ -21,7 +21,7 @@
 
 /**
  * Represents an internal issue with the state sync between the SDK and Assistant. One example is
- * when the SDK places an argument in dismabig state, but then Assistant sends the same argument
+ * when the SDK places an argument in disambig state, but then Assistant sends the same argument
  * data again without any grounding.
  */
 public final class DisambigStateException extends InvalidRequestException {
diff --git a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CallbackUtils.kt b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CallbackUtils.kt
index 4410f42..536472e 100644
--- a/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CallbackUtils.kt
+++ b/appactions/interaction/interaction-capabilities-core/src/main/java/androidx/appactions/interaction/capabilities/core/impl/utils/CallbackUtils.kt
@@ -88,7 +88,7 @@
 }
 
 /**
- * Handles an exception encountered during request proessing (one-shot or multi-turn).
+ * Handles an exception encountered during request processing (one-shot or multi-turn).
  * Includes reporting an ErrorStatusInternal to some callback based on the exception.
  */
 internal fun handleExceptionFromRequestProcessing(
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.kt
index 69a32b0..d1ac8d1 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/AppInteractionServiceGrpcImpl.kt
@@ -138,13 +138,13 @@
             if (currentSessionId != null) {
                 return
             }
-            val sessionId = request.getSessionIdentifier()!!
+            val sessionId = request.sessionIdentifier!!
             currentSessionId = sessionId
-            if (registeredCapabilities.size == 0) {
+            if (registeredCapabilities.isEmpty()) {
                 registeredCapabilities = appInteractionService.registeredCapabilities
             }
             val targetCapability = registeredCapabilities
-                .filter { request.getIdentifier() == it.id }
+                .filter { request.identifier == it.id }
                 .firstOrNull()
             if (targetCapability == null) {
                 return respondWithError(
@@ -159,8 +159,8 @@
             val hostProperties = HostProperties.Builder()
                 .setMaxHostSizeDp(
                     SizeF(
-                        request.getHostProperties().getHostViewHeightDp(),
-                        request.getHostProperties().getHostViewWidthDp(),
+                        request.hostProperties.hostViewHeightDp,
+                        request.hostProperties.hostViewWidthDp,
                     ),
                 ).build()
             val session = targetCapability.createSession(
@@ -194,7 +194,7 @@
         request: Request,
         responseObserver: StreamObserver<Response>,
     ) {
-        if (request.getFulfillmentRequest().getFulfillmentsList().isEmpty()) {
+        if (request.fulfillmentRequest.fulfillmentsList.isEmpty()) {
             return respondWithError(
                 StatusRuntimeException(
                     Status.FAILED_PRECONDITION.withDescription(
@@ -204,10 +204,9 @@
                 responseObserver,
             )
         }
-        val selectedFulfillment = request.getFulfillmentRequest().getFulfillments(0)
-        val capability = registeredCapabilities
-            .filter { selectedFulfillment.getIdentifier() == it.id }
-            .firstOrNull()
+        val selectedFulfillment = request.fulfillmentRequest.getFulfillments(0)
+        val capability =
+            registeredCapabilities.firstOrNull { selectedFulfillment.identifier == it.id }
         if (capability == null) {
             return respondWithError(
                 StatusRuntimeException(
@@ -218,7 +217,7 @@
                 responseObserver,
             )
         }
-        val sessionId = request.getSessionIdentifier()!!
+        val sessionId = request.sessionIdentifier!!
         val currentSession = SessionManager.getSession(sessionId)
         if (currentSession == null) {
             return respondWithError(
@@ -246,9 +245,10 @@
                     val uiCache = UiSessions.getUiCacheOrNull(sessionId)
                     if (uiCache != null && uiCache.hasUnreadUiResponse) {
                         val cachedRemoteViewsInternal = uiCache.cachedRemoteViewsInternal
-                        responseBuilder.setUiUpdate(UiUpdate.getDefaultInstance())
+                        responseBuilder.uiUpdate = UiUpdate.getDefaultInstance()
                         if (cachedRemoteViewsInternal != null &&
-                            !cachedRemoteViewsInternal.collectionViewFactories.keys.isEmpty()) {
+                            cachedRemoteViewsInternal.collectionViewFactories.keys.isNotEmpty()
+                        ) {
                             responseBuilder.setCollectionUpdate(
                                 AppInteractionServiceProto.CollectionUpdate.newBuilder()
                                     .addAllViewIds(
@@ -263,9 +263,9 @@
 
                 override fun onFailure(t: Throwable) {
                     respondWithError(
-                        when {
-                            t is CapabilityExecutionException -> convertToGrpcException(t)
-                            t is StatusRuntimeException || t is StatusException -> t
+                        when (t) {
+                            is CapabilityExecutionException -> convertToGrpcException(t)
+                            is StatusRuntimeException, is StatusException -> t
                             else -> StatusRuntimeException(
                                 Status.INTERNAL.withDescription(
                                     t.message,
@@ -286,7 +286,7 @@
         req: AppInteractionServiceProto.UiRequest,
         responseObserver: StreamObserver<AppInteractionServiceProto.UiResponse>,
     ) {
-        val sessionId = req.getSessionIdentifier()!!
+        val sessionId = req.sessionIdentifier!!
         if (SessionManager.getSession(sessionId) == null) {
             return respondWithError(
                 StatusRuntimeException(
@@ -347,9 +347,7 @@
                 responseObserver,
             )
         }
-        val factory = uiCache.cachedRemoteViewsInternal?.collectionViewFactories?.get(
-            req.getViewId()
-        )
+        val factory = uiCache.cachedRemoteViewsInternal?.collectionViewFactories?.get(req.viewId)
         if (factory == null) {
             return respondWithError(
                 StatusRuntimeException(
@@ -358,7 +356,7 @@
                 responseObserver,
             )
         }
-        when (req.getRequestDataCase()) {
+        when (req.requestDataCase) {
             RequestDataCase.ON_DESTROY -> {
                 requestCollectionOnDestroy(factory, responseObserver)
             }
@@ -369,7 +367,7 @@
                 requestCollectionGetViewAt(
                     factory,
                     responseObserver,
-                    req.getGetViewAt().getPosition(),
+                    req.getViewAt.position,
                 )
             }
             RequestDataCase.GET_LOADING_VIEW -> {
@@ -382,7 +380,7 @@
                 requestCollectionGetItemId(
                     factory,
                     responseObserver,
-                    req.getGetItemId().getPosition(),
+                    req.getItemId.position,
                 )
             }
             RequestDataCase.HAS_STABLE_IDS -> {
@@ -400,9 +398,9 @@
         request: GroundingRequest,
         responseObserver: StreamObserver<GroundingResponse>,
     ) {
-        val entityProvider = appInteractionService.registeredEntityProviders.filter {
-            it.id == request.getRequest().getEntityProviderId()
-        }.firstOrNull()
+        val entityProvider = appInteractionService.registeredEntityProviders.firstOrNull {
+            it.id == request.request.entityProviderId
+        }
         if (entityProvider == null) {
             return respondAndComplete(
                 GroundingResponse.newBuilder()
@@ -422,8 +420,8 @@
                 )
             } catch (t: Throwable) {
                 respondWithError(
-                    when {
-                        t is StatusRuntimeException || t is StatusException -> t
+                    when (t) {
+                        is StatusRuntimeException, is StatusException -> t
                         else -> StatusRuntimeException(
                             Status.INTERNAL.withDescription(
                                 t.message,
@@ -452,7 +450,7 @@
             CollectionResponse.newBuilder()
                 .setGetCount(
                     CollectionResponse.GetCount.newBuilder()
-                        .setCount(factory.getCount()),
+                        .setCount(factory.count),
                 )
                 .build(),
             observer,
@@ -472,7 +470,7 @@
         factory: RemoteViewsFactory,
         observer: StreamObserver<CollectionResponse>,
     ) {
-        factory.getLoadingView()?.let(RemoteViewsOverMetadataInterceptor::setRemoteViews)
+        factory.loadingView?.let(RemoteViewsOverMetadataInterceptor::setRemoteViews)
         respondAndComplete(CollectionResponse.getDefaultInstance(), observer)
     }
 
@@ -484,7 +482,7 @@
             CollectionResponse.newBuilder()
                 .setGetViewTypeCount(
                     CollectionResponse.GetViewTypeCount.newBuilder()
-                        .setViewTypeCount(factory.getViewTypeCount()),
+                        .setViewTypeCount(factory.viewTypeCount),
                 )
                 .build(),
             observer,
@@ -543,7 +541,7 @@
     }
 
     internal fun convertToGrpcException(e: CapabilityExecutionException): StatusRuntimeException {
-        return when (e.getErrorStatus()) {
+        return when (e.errorStatus) {
             ErrorStatusInternal.TIMEOUT -> StatusRuntimeException(
                 Status.DEADLINE_EXCEEDED.withDescription(e.message).withCause(e),
             )
@@ -558,9 +556,9 @@
         capability: Capability,
     ): Response {
         val appAction = capability.appAction
-        val isDialogSession = appAction.getTaskInfo().getSupportsPartialFulfillment()
+        val isDialogSession = appAction.taskInfo.supportsPartialFulfillment
         val version = convertToAppActionsContextVersion(
-            LibInfo(appInteractionService.getApplicationContext()).getVersion(),
+            LibInfo(appInteractionService.applicationContext).getVersion(),
         )
         val responseBuilder: Response.Builder =
             // TODO(b/269638788): Add DialogState to the Response proto.
@@ -573,11 +571,9 @@
                         .build(),
                 )
         if (!isDialogSession) {
-            responseBuilder.setEndingStatus(
-                AppInteractionServiceProto.Status.newBuilder()
-                    .setStatusCode(Code.COMPLETE)
-                    .build(),
-            )
+            responseBuilder.endingStatus = AppInteractionServiceProto.Status.newBuilder()
+                .setStatusCode(Code.COMPLETE)
+                .build()
         }
         return responseBuilder.build()
     }
diff --git a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
index 915be548..5fd605d 100644
--- a/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
+++ b/appactions/interaction/interaction-service/src/main/java/androidx/appactions/interaction/service/UiResponse.kt
@@ -1,3 +1,4 @@
+
 /*
  * Copyright 2023 The Android Open Source Project
  *
@@ -13,16 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 package androidx.appactions.interaction.service
-
 import android.annotation.SuppressLint
 import android.util.SizeF
 import android.widget.RemoteViews
 import android.widget.RemoteViewsService.RemoteViewsFactory
 import androidx.annotation.IdRes
 import androidx.annotation.RestrictTo
-
 /**
  * A class representing the UI response being returned to the host. A `UiResponse` cannot be built
  * directly, it must be built from a [UiResponse] Builder.
@@ -31,21 +29,17 @@
     /** @suppress */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     val remoteViewsInternal: RemoteViewsInternal?
-
     /** @suppress */
     @RestrictTo(RestrictTo.Scope.LIBRARY)
     val tileLayoutInternal: TileLayoutInternal?
-
     internal constructor(remoteViewsInternal: RemoteViewsInternal) {
         this.remoteViewsInternal = remoteViewsInternal
         this.tileLayoutInternal = null
     }
-
     internal constructor(tileLayout: TileLayoutInternal) {
         this.remoteViewsInternal = null
         this.tileLayoutInternal = tileLayout
     }
-
     /** Builder for TileLayouts, used in Wear OS. */
     @Suppress("deprecation") // for backward compatibility
     class TileLayoutBuilder {
@@ -53,11 +47,13 @@
         private var resources: androidx.wear.tiles.ResourceBuilders.Resources? = null
 
         /**
-         * Sets the [LayoutElementBuilders.Layout] and the associated [ResourceBuilders.Resources]
-         * to be displayed. [RemoteViews] should not be used together with
-         * [LayoutElementBuilders.Layout] in the same session.
+         * Sets the [androidx.wear.tiles.LayoutElementBuilders.Layout] and the associated
+         * [androidx.wear.tiles.ResourceBuilders.Resources] to be displayed. [RemoteViews] should
+         * not be used together with [androidx.wear.tiles.LayoutElementBuilders.Layout] in the same
+         * session.
          *
-         * @param layout the wear-tile [LayoutElementBuilders.Layout] to be displayed.
+         * @param layout the wear-tile [androidx.wear.tiles.LayoutElementBuilders.Layout] to be
+         * displayed.
          * @param resources the resources associated with the layout.
          */
         @SuppressLint("MissingGetterMatchingBuilder")
@@ -69,17 +65,14 @@
             this.resources = resources
             return this
         }
-
         /** Builds the UiResponse. */
         fun build() = UiResponse(TileLayoutInternal(layout!!, resources!!))
     }
-
     /** Builder for RemoteViews UI response. */
     class RemoteViewsUiBuilder {
         private var remoteViews: RemoteViews? = null
         private var size: SizeF? = null
         private val collectionViewFactories: HashMap<Int, RemoteViewsFactory> = HashMap()
-
         /**
          * Sets the `RemoteViews` to be displayed in the host.
          *
@@ -92,7 +85,6 @@
             this.size = size
             return this
         }
-
         /**
          * Implemented to generate the appropriate factories for collection views (e.g. ListView).
          * Called when the host detects a collection view in the response UI. The
@@ -106,14 +98,13 @@
             @IdRes viewId: Int,
             factory: RemoteViewsFactory
         ): RemoteViewsUiBuilder {
-            collectionViewFactories.put(viewId, factory)
+            collectionViewFactories[viewId] = factory
             return this
         }
-
         /** Builds the UiResponse. */
         fun build() =
             UiResponse(
                 RemoteViewsInternal(remoteViews!!, size!!, collectionViewFactories)
             )
     }
-}
+}
\ No newline at end of file
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
index b305e73..25b43d8 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/experimental/GattClientImpl.kt
@@ -43,7 +43,8 @@
 import kotlinx.coroutines.launch
 
 internal class GattClientImpl {
-    companion object {
+
+    private companion object {
         private const val TAG = "GattClientImpl"
         private const val GATT_MAX_MTU = 517
         private val CCCD_UID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
@@ -91,6 +92,11 @@
 
         val callback = object : BluetoothGattCallback() {
             override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
+                Log.d(
+                    TAG,
+                    "onConnectionStateChange() called with: gatt = $gatt, status = $status, " +
+                        "newState = $newState"
+                )
                 if (newState == BluetoothGatt.STATE_CONNECTED) {
                     gatt?.requestMtu(GATT_MAX_MTU)
                 } else {
@@ -101,6 +107,7 @@
             }
 
             override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
+                Log.d(TAG, "onMtuChanged() called with: gatt = $gatt, mtu = $mtu, status = $status")
                 if (status == GATT_SUCCESS) {
                     gatt?.discoverServices()
                 } else {
@@ -303,4 +310,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
index e22e999..193adf1 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/advertiser/AdvertiserFragment.kt
@@ -16,7 +16,12 @@
 
 package androidx.bluetooth.integration.testapp.ui.advertiser
 
+// TODO(ofy) Migrate to androidx.bluetooth.BluetoothLe once Gatt Server API is in place
+import android.Manifest
 import android.annotation.SuppressLint
+import android.bluetooth.BluetoothManager
+import android.content.Context
+import android.content.pm.PackageManager
 import android.os.Bundle
 import android.util.Log
 import android.view.LayoutInflater
@@ -29,12 +34,15 @@
 import androidx.bluetooth.BluetoothLe
 import androidx.bluetooth.integration.testapp.R
 import androidx.bluetooth.integration.testapp.databinding.FragmentAdvertiserBinding
+import androidx.bluetooth.integration.testapp.experimental.BluetoothLe as BluetoothLeExperimental
 import androidx.bluetooth.integration.testapp.ui.common.getColor
 import androidx.bluetooth.integration.testapp.ui.common.setViewEditText
 import androidx.bluetooth.integration.testapp.ui.common.toast
+import androidx.core.content.ContextCompat
 import androidx.core.view.isVisible
 import androidx.fragment.app.Fragment
 import androidx.lifecycle.ViewModelProvider
+import com.google.android.material.tabs.TabLayout
 import java.util.UUID
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -45,17 +53,25 @@
 
     private companion object {
         private const val TAG = "AdvertiserFragment"
+
+        private const val TAB_ADVERTISER_POSITION = 0
     }
 
     private lateinit var advertiserViewModel: AdvertiserViewModel
 
     private lateinit var bluetoothLe: BluetoothLe
 
+    // TODO(ofy) Migrate to androidx.bluetooth.BluetoothLe once scan API is in place
+    private lateinit var bluetoothLeExperimental: BluetoothLeExperimental
+
     private var advertiseDataAdapter: AdvertiseDataAdapter? = null
 
     private val advertiseScope = CoroutineScope(Dispatchers.Main + Job())
     private var advertiseJob: Job? = null
 
+    private val gattServerScope = CoroutineScope(Dispatchers.Main + Job())
+    private var gattServerJob: Job? = null
+
     private var isAdvertising: Boolean = false
         set(value) {
             field = value
@@ -68,7 +84,6 @@
                 advertiseJob?.cancel()
                 advertiseJob = null
             }
-            _binding?.textInputEditTextDisplayName?.isEnabled = !value
             _binding?.checkBoxIncludeDeviceName?.isEnabled = !value
             _binding?.checkBoxConnectable?.isEnabled = !value
             _binding?.checkBoxDiscoverable?.isEnabled = !value
@@ -76,6 +91,39 @@
             _binding?.viewRecyclerViewOverlay?.isVisible = value
         }
 
+    private var isGattServerOpen: Boolean = false
+        set(value) {
+            field = value
+            if (value) {
+                _binding?.buttonGattServer?.text = getString(R.string.stop_gatt_server)
+                _binding?.buttonGattServer?.backgroundTintList = getColor(R.color.red_500)
+            } else {
+                _binding?.buttonGattServer?.text = getString(R.string.open_gatt_server)
+                _binding?.buttonGattServer?.backgroundTintList = getColor(R.color.indigo_500)
+                gattServerJob?.cancel()
+                gattServerJob = null
+            }
+        }
+
+    private var showingAdvertiser: Boolean = false
+        set(value) {
+            field = value
+            _binding?.layoutAdvertiser?.isVisible = value
+            _binding?.layoutGattServer?.isVisible = !value
+        }
+
+    private val onTabSelectedListener = object : TabLayout.OnTabSelectedListener {
+        override fun onTabSelected(tab: TabLayout.Tab) {
+            showingAdvertiser = tab.position == TAB_ADVERTISER_POSITION
+        }
+
+        override fun onTabUnselected(tab: TabLayout.Tab) {
+        }
+
+        override fun onTabReselected(tab: TabLayout.Tab) {
+        }
+    }
+
     private var _binding: FragmentAdvertiserBinding? = null
 
     // This property is only valid between onCreateView and onDestroyView.
@@ -90,9 +138,11 @@
 
         bluetoothLe = BluetoothLe(requireContext())
 
+        bluetoothLeExperimental = BluetoothLeExperimental(requireContext())
+
         _binding = FragmentAdvertiserBinding.inflate(inflater, container, false)
 
-        initData()
+        binding.tabLayout.addOnTabSelectedListener(onTabSelectedListener)
 
         binding.checkBoxIncludeDeviceName.setOnCheckedChangeListener { _, isChecked ->
             advertiserViewModel.includeDeviceName = isChecked
@@ -134,6 +184,16 @@
             }
         }
 
+        binding.buttonGattServer.setOnClickListener {
+            if (gattServerJob?.isActive == true) {
+                isGattServerOpen = false
+            } else {
+                openGattServer()
+            }
+        }
+
+        initData()
+
         return binding.root
     }
 
@@ -144,6 +204,17 @@
     }
 
     private fun initData() {
+        if (ContextCompat.checkSelfPermission(
+                requireContext(),
+                Manifest.permission.BLUETOOTH_CONNECT
+            )
+            == PackageManager.PERMISSION_GRANTED
+        ) {
+            binding.textInputEditTextDisplayName.setText(
+                (requireContext().getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager)
+                    .adapter.name
+            )
+        }
         binding.checkBoxIncludeDeviceName.isChecked = advertiserViewModel.includeDeviceName
         binding.checkBoxConnectable.isChecked = advertiserViewModel.connectable
         binding.checkBoxDiscoverable.isChecked = advertiserViewModel.discoverable
@@ -270,4 +341,16 @@
                 }
         }
     }
+
+    private fun openGattServer() {
+        Log.d(TAG, "openGattServer() called")
+
+        gattServerJob = gattServerScope.launch {
+            isGattServerOpen = true
+
+            bluetoothLeExperimental.gattServer().collect { gattServerCallback ->
+                Log.d(TAG, "openGattServer() called with: gattServerCallback = $gattServerCallback")
+            }
+        }
+    }
 }
diff --git a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
index 5bfc8f0..ad5e5da 100644
--- a/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
+++ b/bluetooth/integration-tests/testapp/src/main/java/androidx/bluetooth/integration/testapp/ui/scanner/ScannerFragment.kt
@@ -16,8 +16,7 @@
 
 package androidx.bluetooth.integration.testapp.ui.scanner
 
-// TODO(ofy) Migrate from androidx.bluetooth.integration.testapp.experimental.BluetoothLe
-// to androidx.bluetooth.BluetoothLe once scan API is in place
+// TODO(ofy) Migrate to androidx.bluetooth.BluetoothLe once scan API is in place
 import android.annotation.SuppressLint
 import android.bluetooth.le.ScanResult
 import android.bluetooth.le.ScanSettings
@@ -84,8 +83,8 @@
     private var showingScanResults: Boolean = false
         set(value) {
             field = value
-            _binding?.relativeLayoutScanResults?.isVisible = value
-            _binding?.linearLayoutDevice?.isVisible = !value
+            _binding?.layoutScanResults?.isVisible = value
+            _binding?.layoutDevice?.isVisible = !value
         }
 
     private val onTabSelectedListener = object : TabLayout.OnTabSelectedListener {
@@ -141,6 +140,10 @@
             }
         }
 
+        binding.buttonReconnect.setOnClickListener {
+            connectTo(scannerViewModel.deviceConnection(binding.tabLayout.selectedTabPosition))
+        }
+
         initData()
 
         return binding.root
@@ -251,6 +254,7 @@
     @SuppressLint("NotifyDataSetChanged")
     private fun updateDeviceUI(deviceConnection: DeviceConnection) {
         binding.progressIndicatorDeviceConnection.isVisible = false
+        binding.buttonReconnect.isVisible = false
 
         when (deviceConnection.status) {
             Status.NOT_CONNECTED -> {
@@ -269,6 +273,7 @@
             Status.CONNECTION_FAILED -> {
                 binding.textViewDeviceConnectionStatus.text = getString(R.string.connection_failed)
                 binding.textViewDeviceConnectionStatus.setTextColor(getColor(R.color.red_500))
+                binding.buttonReconnect.isVisible = true
             }
         }
         deviceServicesAdapter?.services = deviceConnection.services
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
index 014dc75..024d732 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_advertiser.xml
@@ -21,108 +21,158 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <TextView
-        android:id="@+id/text_view_configure_advertising_packet"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:padding="16dp"
-        android:text="@string/configure_advertising_packet"
-        android:textColor="@color/black"
-        android:textSize="21sp"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent" />
-
-    <com.google.android.material.textfield.TextInputLayout
-        android:id="@+id/text_input_layout_display_name"
+    <com.google.android.material.tabs.TabLayout
+        android:id="@+id/tab_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:hint="@string/display_name"
-        app:layout_constraintTop_toBottomOf="@+id/text_view_configure_advertising_packet">
+        app:layout_constraintTop_toTopOf="parent"
+        app:tabMode="fixed">
 
-        <com.google.android.material.textfield.TextInputEditText
-            android:id="@+id/text_input_edit_text_display_name"
+        <com.google.android.material.tabs.TabItem
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/title_advertiser" />
+
+        <com.google.android.material.tabs.TabItem
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/gatt_server" />
+
+    </com.google.android.material.tabs.TabLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/layout_advertiser"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
+        tools:visibility="gone">
+
+        <TextView
+            android:id="@+id/text_view_configure_advertising_packet"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:padding="16dp"
+            android:text="@string/configure_advertising_packet"
+            android:textColor="@color/black"
+            android:textSize="21sp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <com.google.android.material.textfield.TextInputLayout
+            android:id="@+id/text_input_layout_display_name"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:inputType="text"
-            android:maxLines="1" />
+            android:hint="@string/display_name"
+            app:layout_constraintTop_toBottomOf="@+id/text_view_configure_advertising_packet">
 
-    </com.google.android.material.textfield.TextInputLayout>
+            <com.google.android.material.textfield.TextInputEditText
+                android:id="@+id/text_input_edit_text_display_name"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:enabled="false"
+                android:inputType="text"
+                android:maxLines="1" />
 
-    <CheckBox
-        android:id="@+id/check_box_include_device_name"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:layout_marginTop="8dp"
-        android:text="@string/include_device_name"
-        app:layout_constraintTop_toBottomOf="@+id/text_input_layout_display_name" />
+        </com.google.android.material.textfield.TextInputLayout>
 
-    <CheckBox
-        android:id="@+id/check_box_connectable"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:text="@string/connectable"
-        app:layout_constraintTop_toBottomOf="@+id/check_box_include_device_name" />
+        <CheckBox
+            android:id="@+id/check_box_include_device_name"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:layout_marginTop="8dp"
+            android:text="@string/include_device_name"
+            app:layout_constraintTop_toBottomOf="@+id/text_input_layout_display_name" />
 
-    <CheckBox
-        android:id="@+id/check_box_discoverable"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="16dp"
-        android:text="@string/discoverable"
-        app:layout_constraintTop_toBottomOf="@+id/check_box_connectable" />
+        <CheckBox
+            android:id="@+id/check_box_connectable"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:text="@string/connectable"
+            app:layout_constraintTop_toBottomOf="@+id/check_box_include_device_name" />
 
-    <TextView
-        android:id="@+id/text_view_advertising_data"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:layout_marginEnd="8dp"
-        android:padding="8dp"
-        android:text="@string/advertising_data"
-        android:textColor="@color/black"
-        android:textSize="21sp"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/check_box_discoverable" />
+        <CheckBox
+            android:id="@+id/check_box_discoverable"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="16dp"
+            android:text="@string/discoverable"
+            app:layout_constraintTop_toBottomOf="@+id/check_box_connectable" />
 
-    <Button
-        android:id="@+id/button_add_data"
-        style="@style/Widget.MaterialComponents.Button.Icon"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginStart="8dp"
-        android:text="@string/add_data"
-        app:icon="@drawable/baseline_add_24"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/text_view_advertising_data" />
+        <TextView
+            android:id="@+id/text_view_advertising_data"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:layout_marginEnd="8dp"
+            android:padding="8dp"
+            android:text="@string/advertising_data"
+            android:textColor="@color/black"
+            android:textSize="21sp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/check_box_discoverable" />
 
-    <androidx.recyclerview.widget.RecyclerView
-        android:id="@+id/recycler_view_advertise_data"
+        <Button
+            android:id="@+id/button_add_data"
+            style="@style/Widget.MaterialComponents.Button.Icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="8dp"
+            android:text="@string/add_data"
+            app:icon="@drawable/baseline_add_24"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/text_view_advertising_data" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/recycler_view_advertise_data"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            app:layoutManager="LinearLayoutManager"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/button_add_data"
+            tools:itemCount="3"
+            tools:listitem="@layout/item_advertiser_data" />
+
+        <View
+            android:id="@+id/view_recycler_view_overlay"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:clickable="true"
+            android:visibility="gone"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/button_add_data" />
+
+        <Button
+            android:id="@+id/button_advertise"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="16dp"
+            android:text="@string/start_advertising"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:id="@+id/layout_gatt_server"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        app:layoutManager="LinearLayoutManager"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/button_add_data"
-        tools:itemCount="3"
-        tools:listitem="@layout/item_advertiser_data" />
-
-    <View
-        android:id="@+id/view_recycler_view_overlay"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:clickable="true"
         android:visibility="gone"
         app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintTop_toBottomOf="@+id/button_add_data" />
+        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
+        tools:visibility="visible">
 
-    <Button
-        android:id="@+id/button_advertise"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_margin="16dp"
-        android:text="@string/start_advertising"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent" />
+        <Button
+            android:id="@+id/button_gatt_server"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_margin="16dp"
+            android:text="@string/open_gatt_server"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
index 9cf7c3484..dc4f3a1 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/layout/fragment_scanner.xml
@@ -37,7 +37,7 @@
     </com.google.android.material.tabs.TabLayout>
 
     <RelativeLayout
-        android:id="@+id/relative_layout_scan_results"
+        android:id="@+id/layout_scan_results"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -64,7 +64,7 @@
     </RelativeLayout>
 
     <LinearLayout
-        android:id="@+id/linear_layout_device"
+        android:id="@+id/layout_device"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         android:orientation="vertical"
@@ -97,6 +97,18 @@
                 android:visibility="gone"
                 app:indicatorSize="24dp" />
 
+            <View
+                android:layout_width="0dp"
+                android:layout_height="0dp"
+                android:layout_weight="1" />
+
+            <Button
+                android:id="@+id/button_reconnect"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/reconnect"
+                android:visibility="gone" />
+
         </LinearLayout>
 
         <View
diff --git a/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml b/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
index b6a131a..cab9c9f 100644
--- a/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
+++ b/bluetooth/integration-tests/testapp/src/main/res/values/donottranslate-strings.xml
@@ -26,6 +26,7 @@
     <string name="stop_scanning">Stop scanning</string>
     <string name="scan_result_icon">Scan Result Icon</string>
     <string name="connect">Connect</string>
+    <string name="reconnect">Reconnect</string>
     <string name="scan_results">Scan Results</string>
     <string name="not_connected">Not Connected</string>
     <string name="connecting">Connecting…</string>
@@ -54,6 +55,11 @@
     <string name="cancel">Cancel</string>
     <string name="clear_data">Clear Data</string>
 
+    <!-- GATT Server -->
+    <string name="gatt_server">Gatt Server</string>
+    <string name="open_gatt_server">Open Gatt Server</string>
+    <string name="stop_gatt_server">Stop Gatt Server</string>
+
     <string name="scan_using_androidx_bluetooth">Scan using AndroidX Bluetooth APIs</string>
     <string name="scan_start_message">Scan started. Results are in Logcat</string>
 
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
index 7a4f3c0..1a36ae6 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/AndroidXRootImplPlugin.kt
@@ -69,6 +69,8 @@
         configureKtlintCheckFile()
         tasks.register(CheckExternalDependencyLicensesTask.TASK_NAME)
 
+        maybeRegisterFilterableTask()
+
         // If we're running inside Studio, validate the Android Gradle Plugin version.
         val expectedAgpVersion = System.getenv("EXPECTED_AGP_VERSION")
         if (properties.containsKey("android.injected.invoked.from.ide")) {
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/FilteredAnchorTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/FilteredAnchorTask.kt
new file mode 100644
index 0000000..c40a47d
--- /dev/null
+++ b/buildSrc/private/src/main/kotlin/androidx/build/FilteredAnchorTask.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.build
+
+import androidx.build.FilteredAnchorTask.Companion.GLOBAL_TASK_NAME
+import androidx.build.FilteredAnchorTask.Companion.PROP_PATH_PREFIX
+import androidx.build.FilteredAnchorTask.Companion.PROP_TASK_NAME
+import org.gradle.api.DefaultTask
+import org.gradle.api.GradleException
+import org.gradle.api.Project
+import org.gradle.api.tasks.Input
+import org.gradle.api.tasks.TaskAction
+import org.gradle.api.tasks.TaskProvider
+import org.gradle.work.DisableCachingByDefault
+
+@DisableCachingByDefault(because = "This is an anchor task that does no work.")
+abstract class FilteredAnchorTask : DefaultTask() {
+    init {
+        group = "Help"
+        description = "Runs tasks with a name specified by -P$PROP_TASK_NAME= for projects with " +
+            "a path prefix specified by -P$PROP_PATH_PREFIX="
+    }
+
+    @get:Input
+    abstract var pathPrefix: String
+
+    @get:Input
+    abstract var taskName: String
+
+    @TaskAction
+    fun exec() {
+        if (dependsOn.isEmpty()) {
+            throw GradleException("Failed to find any filterable tasks with name \"$taskName\" " +
+                "and path prefixed with \"$pathPrefix\"")
+        }
+    }
+
+    companion object {
+        const val GLOBAL_TASK_NAME = "filterTasks"
+        const val PROP_PATH_PREFIX = "androidx.pathPrefix"
+        const val PROP_TASK_NAME = "androidx.taskName"
+    }
+}
+
+/**
+ * Offers the specified [taskProviders] to the global [FilteredAnchorTask], adding them if they match
+ * the requested path prefix and task name.
+ */
+internal fun Project.addFilterableTasks(vararg taskProviders: TaskProvider<*>?) {
+    if (hasProperty(PROP_PATH_PREFIX) && hasProperty(PROP_TASK_NAME)) {
+        val pathPrefix = properties[PROP_PATH_PREFIX] as String
+        if (relativePathForFiltering().startsWith(pathPrefix)) {
+            val taskName = properties[PROP_TASK_NAME] as String
+            taskProviders.find { taskProvider ->
+                taskName == taskProvider?.name
+            }?.let { taskProvider ->
+                rootProject.tasks.named(GLOBAL_TASK_NAME).configure { task ->
+                    task.dependsOn(taskProvider)
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Registers the global [FilteredAnchorTask] if the required command-line properties are set.
+ *
+ * For example, to run `checkApi` for all projects under `core/core/`:
+ * ./gradlew filterTasks -Pandroidx.taskName=checkApi -Pandroidx.pathPrefix=core/core/
+ */
+internal fun Project.maybeRegisterFilterableTask() {
+    if (hasProperty(PROP_TASK_NAME) && hasProperty(PROP_PATH_PREFIX)) {
+        tasks.register(GLOBAL_TASK_NAME, FilteredAnchorTask::class.java) { task ->
+            task.pathPrefix = properties[PROP_PATH_PREFIX] as String
+            task.taskName = properties[PROP_TASK_NAME] as String
+        }
+    }
+}
+
+/**
+ * Returns an AndroidX-relative path for the [Project], inserting the root project directory when
+ * run in a Playground context such that paths are consistent with the AndroidX context.
+ */
+internal fun Project.relativePathForFiltering(): String =
+    if (ProjectLayoutType.isPlayground(project)) {
+        "${rootProject.projectDir.name}/"
+    } else {
+        ""
+    } + "${projectDir.relativeTo(rootDir)}/"
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
index d7c4c07..54597b4 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/buildInfo/CreateLibraryBuildInfoFileTask.kt
@@ -258,12 +258,7 @@
          * of the build that is released.  Thus, we use frameworks/support to get the sha
          */
         fun Project.getFrameworksSupportCommitShaAtHead(): String {
-            val gitClient = GitClient.create(
-                project.getSupportRootFolder(),
-                logger,
-                GitClient.getChangeInfoPath(project).get(),
-                GitClient.getManifestPath(project).get()
-            )
+            val gitClient = GitClient.forProject(project)
             return gitClient.getHeadSha(getSupportRootFolder())
         }
     }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt b/buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
index feb0a6f..756da81 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/dependencyTracker/AffectedModuleDetector.kt
@@ -278,7 +278,7 @@
                 logger.info("using base commit override $baseCommitOverride")
             }
             val gitClient = GitClient.create(
-                rootProjectDir = parameters.rootDir,
+                projectDir = parameters.rootDir,
                 logger = logger.toLogger(),
                 changeInfoPath = parameters.changeInfoPath.get(),
                 manifestPath = parameters.manifestPath.get()
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/dokka/kmpDocs/DokkaCombinedDocsTask.kt b/buildSrc/private/src/main/kotlin/androidx/build/dokka/kmpDocs/DokkaCombinedDocsTask.kt
index 471f537..bfec803 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/dokka/kmpDocs/DokkaCombinedDocsTask.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/dokka/kmpDocs/DokkaCombinedDocsTask.kt
@@ -204,12 +204,7 @@
                 it.additionalDocumentation.set(
                     project.files("homepage.md")
                 )
-                val gitClient = GitClient.create(
-                    project.getSupportRootFolder(),
-                    project.logger,
-                    GitClient.getChangeInfoPath(project).get(),
-                    GitClient.getManifestPath(project).get()
-                )
+                val gitClient = GitClient.forProject(project)
                 it.replacementUrl.set(
                     DokkaUtils.createCsAndroidUrl(
                         gitClient.getHeadSha(project.getSupportRootFolder())
@@ -253,4 +248,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitClient.kt b/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitClient.kt
index 9b1ecee..25c6a81 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitClient.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitClient.kt
@@ -19,6 +19,7 @@
 import androidx.build.releasenotes.getBuganizerLink
 import androidx.build.releasenotes.getChangeIdAOSPLink
 import java.io.File
+import java.util.concurrent.ConcurrentHashMap
 import org.gradle.api.GradleException
 import org.gradle.api.Project
 import org.gradle.api.logging.Logger
@@ -83,8 +84,16 @@
         fun getManifestPath(project: Project): Provider<String> {
             return project.providers.environmentVariable("MANIFEST").orElse("")
         }
+        fun forProject(project: Project): GitClient {
+            return create(
+                project.projectDir,
+                project.logger,
+                GitClient.getChangeInfoPath(project).get(),
+                GitClient.getManifestPath(project).get()
+            )
+        }
         fun create(
-            rootProjectDir: File,
+            projectDir: File,
             logger: Logger,
             changeInfoPath: String,
             manifestPath: String
@@ -107,8 +116,41 @@
                     "manifest $manifestPath")
                 return ChangeInfoGitClient(changeInfoText, manifestText)
             }
+            val gitRoot = findGitDirInParentFilepath(projectDir)
+            check(gitRoot != null) {
+                "Could not find .git dir for $projectDir"
+            }
             logger.info("UsingGitRunnerGitClient")
-            return GitRunnerGitClient(rootProjectDir, logger)
+            return GitRunnerGitClient(gitRoot, logger)
+        }
+    }
+}
+
+data class MultiGitClient(
+    val logger: Logger,
+    val changeInfoPath: String,
+    val manifestPath: String
+) {
+    // Map from the root of the git repository to a GitClient for that repository
+    // In AndroidX this directory could be frameworks/support, external/noto-fonts, or others
+    @Transient // We don't want Gradle to persist GitClient in the configuration cache
+    val cache: MutableMap<File, GitClient> = ConcurrentHashMap()
+
+    fun getGitClient(projectDir: File): GitClient {
+        return cache.getOrPut(
+            key = projectDir
+        ) {
+            GitClient.create(projectDir, logger, changeInfoPath, manifestPath)
+        }
+    }
+
+    companion object {
+        fun create(project: Project): MultiGitClient {
+            return MultiGitClient(
+                project.logger,
+                GitClient.getChangeInfoPath(project).get(),
+                GitClient.getManifestPath(project).get()
+            )
         }
     }
 }
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitRunnerGitClient.kt b/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitRunnerGitClient.kt
index 2057187..342d2e5 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitRunnerGitClient.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/gitclient/GitRunnerGitClient.kt
@@ -66,17 +66,6 @@
             ?.firstOrNull()
     }
 
-    private fun findGitDirInParentFilepath(filepath: File): File? {
-        var curDirectory: File = filepath
-        while (curDirectory.path != "/") {
-            if (File("$curDirectory/.git").exists()) {
-                return curDirectory
-            }
-            curDirectory = curDirectory.parentFile
-        }
-        return null
-    }
-
     private fun parseCommitLogString(
         commitLogString: String,
         commitStartDelimiter: String,
@@ -214,3 +203,17 @@
         const val GIT_LOG_CMD_PREFIX = "git log --name-only"
     }
 }
+
+/**
+ * Finds the git directory containing the given File by checking parent directories
+ */
+internal fun findGitDirInParentFilepath(filepath: File): File? {
+    var curDirectory: File = filepath
+    while (curDirectory.path != "/") {
+        if (File("$curDirectory/.git").exists()) {
+            return curDirectory
+        }
+        curDirectory = curDirectory.parentFile
+    }
+    return null
+}
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt b/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
index c8458bc..63e1edb 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/metalava/MetalavaTasks.kt
@@ -17,7 +17,7 @@
 package androidx.build.metalava
 
 import androidx.build.AndroidXExtension
-import androidx.build.ProjectLayoutType.Companion.isPlayground
+import androidx.build.addFilterableTasks
 import androidx.build.addToBuildOnServer
 import androidx.build.addToCheckTask
 import androidx.build.checkapi.ApiBaselinesLocation
@@ -26,6 +26,7 @@
 import androidx.build.getSuppressCompatibilityOptInPathPrefixes
 import androidx.build.getSuppressCompatibilityOptOutPathPrefixes
 import androidx.build.java.JavaCompileInputs
+import androidx.build.relativePathForFiltering
 import androidx.build.uptodatedness.cacheEvenIfNoOutputs
 import com.android.build.gradle.tasks.ProcessLibraryManifest
 import org.gradle.api.Project
@@ -113,7 +114,7 @@
             }
         }
 
-        project.tasks.register(
+        val updateApiLintBaseline = project.tasks.register(
             "updateApiLintBaseline",
             UpdateApiLintBaselineTask::class.java
         ) { task ->
@@ -189,7 +190,7 @@
         // Make sure it always runs *after* the updateApi task.
         ignoreApiChanges?.configure { it.mustRunAfter(updateApi) }
 
-        project.tasks.register("regenerateApis") { task ->
+        val regenerateApis = project.tasks.register("regenerateApis") { task ->
             task.group = "API"
             task.description = "Regenerates current and historic API .txt files using the " +
                 "corresponding prebuilt and the latest Metalava, then updates API ignore files"
@@ -200,6 +201,14 @@
 
         project.addToCheckTask(checkApi)
         project.addToBuildOnServer(checkApi)
+        project.addFilterableTasks(
+            ignoreApiChanges,
+            updateApiLintBaseline,
+            checkApi,
+            regenerateOldApis,
+            updateApi,
+            regenerateApis,
+        )
     }
 
     private fun applyInputs(inputs: JavaCompileInputs, task: MetalavaTask) {
@@ -214,11 +223,7 @@
  * Returns whether the project has been opted-in to the Suppress Compatibility migration.
  */
 internal fun Project.isOptedInToSuppressCompatibilityMigration(): Boolean {
-    val dir = if (isPlayground(project)) {
-        "${rootProject.projectDir.name}/"
-    } else {
-        ""
-    } + "${projectDir.relativeTo(rootDir)}/"
+    val dir = relativePathForFiltering()
     return getSuppressCompatibilityOptOutPathPrefixes().none { pathPrefix ->
         dir.startsWith(pathPrefix)
     } && getSuppressCompatibilityOptInPathPrefixes().any { pathPrefix ->
diff --git a/buildSrc/private/src/main/kotlin/androidx/build/sbom/Sbom.kt b/buildSrc/private/src/main/kotlin/androidx/build/sbom/Sbom.kt
index 6849ca4..8889212 100644
--- a/buildSrc/private/src/main/kotlin/androidx/build/sbom/Sbom.kt
+++ b/buildSrc/private/src/main/kotlin/androidx/build/sbom/Sbom.kt
@@ -37,7 +37,11 @@
     return when (configurationName) {
         BundleInsideHelper.CONFIGURATION_NAME -> true
         "shadowed" -> true
-        "compileClasspath" -> appliesShadowPlugin()
+        // compileClasspath is included by the Shadow plugin by default but projects that
+        // declare a "shadowed" configuration exclude the "compileClasspath" configuration from
+        // the shadowJar task
+        "compileClasspath" ->
+            appliesShadowPlugin() && project.configurations.findByName("shadowed") == null
         EXPORT_INSPECTOR_DEPENDENCIES -> true
         IMPORT_INSPECTOR_DEPENDENCIES -> true
         else -> false
diff --git a/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt b/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
index b6c5c29..51a2301 100644
--- a/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
+++ b/buildSrc/public/src/main/kotlin/androidx/build/LibraryType.kt
@@ -36,17 +36,33 @@
  *
  * The possible values of LibraryType are as follows:
  * PUBLISHED_LIBRARY: a conventional library, published, sourced, documented, and versioned.
- * SAMPLES: a library of samples, published as additional properties to a conventional library,
- *      including published source. Documented in a special way, not API tracked.
+ * PUBLISHED_TEST_LIBRARY: PUBLISHED_LIBRARY, but allows calling @VisibleForTesting API. Used for
+ * libraries that allow developers to test code that uses your library. Often provides test fakes.
+ * PUBLISHED_NATIVE_LIBRARY: PUBLISHED_LIBRARY, but uses native API tracking instead of Java
+ * INTERNAL_TEST_LIBRARY: unpublished, untracked, undocumented. Used in internal tests. Usually
+ * contains integration tests, but is _not_ an app. Runs device tests.
+ * INTERNAL_HOST_TEST_LIBRARY: as INTERNAL_TEST_LIBRARY, but runs host tests instead. Avoid mixing
+ * host tests and device tests in the same library, for performance / test-result-caching reasons.
+ * SAMPLES: a library containing sample code referenced in your library's documentation with
+ * @sampled, published as a documentation-related supplement to a conventional library.
  * LINT: a library of lint rules for using a conventional library. Published through lintPublish as
- *      part of an AAR, not published standalone.
- * COMPILER_PLUGIN: a tool that modifies the kotlin or java compiler. Used only while compiling.
+ * part of an AAR, not published standalone.
+ * COMPILER_DAEMON: a tool that modifies the kotlin or java compiler. Used only while compiling. Has
+ * no API and does not publish source jars, but does release to maven.
+ * COMPILER_DAEMON_TEST: a compiler plugin that is not published at all, for internal-only use.
+ * COMPILER_PLUGIN: as COMPILER_DAEMON, but is compatible with JDK 11.
  * GRADLE_PLUGIN: a library that is a gradle plugin.
  * ANNOTATION_PROCESSOR: a library consisting of an annotation processor. Used only while compiling.
+ * ANNOTATION_PROCESSOR_UTILS: contains reference code for understanding an annotation processor.
+ * Publishes source jars, but does not track API.
  * OTHER_CODE_PROCESSOR: a library that algorithmically generates and/or alters code
  *                      but not through hooking into custom annotations or the kotlin compiler.
  *                      For example, navigation:safe-args-generator or Jetifier.
+ * IDE_PLUGIN: a library that should only ever be downloaded by studio. Unfortunately, we don't
+ * yet have a good way to track API for these. b/281843422
  * UNSET: a library that has not yet been migrated to using LibraryType. Should never be used.
+ * APP: an app, such as an example app or integration testsapp. Should never be used; apps should
+ * not apply the AndroidX plugin or have an androidx block in their build.gradle files.
  *
  * TODO: potential future LibraryTypes:
  * KOTLIN_ONLY_LIBRARY: like PUBLISHED_LIBRARY, but not intended for use from java. ktx and compose.
@@ -82,7 +98,10 @@
         val OTHER_CODE_PROCESSOR = OtherCodeProcessor()
         val IDE_PLUGIN = IdePlugin()
         val UNSET = Unset()
+        @Deprecated("Do not use an androidx block for apps/testapps, only for libraries")
+        val APP = UNSET
 
+        @Suppress("DEPRECATION")
         private val allTypes = mapOf(
             "PUBLISHED_LIBRARY" to PUBLISHED_LIBRARY,
             "PUBLISHED_TEST_LIBRARY" to PUBLISHED_TEST_LIBRARY,
@@ -99,7 +118,8 @@
             "ANNOTATION_PROCESSOR_UTILS" to ANNOTATION_PROCESSOR_UTILS,
             "OTHER_CODE_PROCESSOR" to OTHER_CODE_PROCESSOR,
             "IDE_PLUGIN" to IDE_PLUGIN,
-            "UNSET" to UNSET
+            "UNSET" to UNSET,
+            "APP" to APP
         )
         fun valueOf(name: String): LibraryType {
             val result = allTypes[name]
diff --git a/busytown/androidx_host_tests.sh b/busytown/androidx_host_tests.sh
index 67d8d37..3555073 100755
--- a/busytown/androidx_host_tests.sh
+++ b/busytown/androidx_host_tests.sh
@@ -5,7 +5,7 @@
 
 cd "$(dirname $0)"
 
-impl/build.sh test zipOwnersFiles \
+impl/build.sh test zipOwnersFiles createModuleInfo \
     -Pandroidx.ignoreTestFailures \
     -Pandroidx.displayTestOutput=false \
     "$@"
diff --git a/busytown/androidx_host_tests_max_dep_versions.sh b/busytown/androidx_host_tests_max_dep_versions.sh
index 4442f42..5dbf2ee 100755
--- a/busytown/androidx_host_tests_max_dep_versions.sh
+++ b/busytown/androidx_host_tests_max_dep_versions.sh
@@ -5,7 +5,7 @@
 
 cd "$(dirname $0)"
 
-impl/build.sh test zipOwnersFiles \
+impl/build.sh test zipOwnersFiles createModuleInfo \
     -Pandroidx.useMaxDepVersions \
     -Pandroidx.displayTestOutput=false \
     -Pandroidx.ignoreTestFailures "$@"
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
index 0a60ca7..7a88d02 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/Camera2InteropIntegrationTest.kt
@@ -156,9 +156,10 @@
                 when (state) {
                     // Filter out this state from the downstream flow
                     is SessionState.Unknown -> true
-                    is SessionState.Configured -> {
+                    is SessionState.Configured -> true
+                    is SessionState.Ready -> {
                         withContext(Dispatchers.Main) { processCameraProvider!!.unbindAll() }
-                        true // Filter out this state from the downstream flow
+                        false
                     }
 
                     else -> false // Forward to the downstream flow
@@ -368,19 +369,19 @@
         MutableStateFlow<SessionState>(SessionState.Unknown).apply {
             val stateCallback = object : CameraCaptureSession.StateCallback() {
                 override fun onReady(session: CameraCaptureSession) {
-                    tryEmit(SessionState.Ready)
+                        tryEmit(SessionState.Ready)
                 }
 
                 override fun onConfigured(session: CameraCaptureSession) {
-                    tryEmit(SessionState.Configured)
+                        tryEmit(SessionState.Configured)
                 }
 
                 override fun onConfigureFailed(session: CameraCaptureSession) {
-                    tryEmit(SessionState.ConfigureFailed)
+                        tryEmit(SessionState.ConfigureFailed)
                 }
 
                 override fun onClosed(session: CameraCaptureSession) {
-                    tryEmit(SessionState.Closed)
+                        tryEmit(SessionState.Closed)
                 }
             }
             CameraPipeUtil.setSessionStateCallback(
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
index 91d0350..c247a1d 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/LazyListMeasure.kt
@@ -342,22 +342,17 @@
 
     var end = visibleItems.last().index
 
-    fun addItem(index: Int) {
-        if (list == null) list = mutableListOf()
-        requireNotNull(list).add(
-            measuredItemProvider.getAndMeasure(index)
-        )
-    }
-
     end = minOf(end + beyondBoundsItemCount, itemsCount - 1)
 
     for (i in visibleItems.last().index + 1..end) {
-        addItem(i)
+        if (list == null) list = mutableListOf()
+        list.add(measuredItemProvider.getAndMeasure(i))
     }
 
     pinnedItems.fastForEach { index ->
         if (index > end) {
-            addItem(index)
+            if (list == null) list = mutableListOf()
+            list?.add(measuredItemProvider.getAndMeasure(index))
         }
     }
 
@@ -374,22 +369,17 @@
 
     var start = currentFirstItemIndex
 
-    fun addItem(index: Int) {
-        if (list == null) list = mutableListOf()
-        requireNotNull(list).add(
-            measuredItemProvider.getAndMeasure(index)
-        )
-    }
-
     start = maxOf(0, start - beyondBoundsItemCount)
 
     for (i in currentFirstItemIndex - 1 downTo start) {
-        addItem(i)
+        if (list == null) list = mutableListOf()
+        list.add(measuredItemProvider.getAndMeasure(i))
     }
 
     pinnedItems.fastForEach { index ->
         if (index < start) {
-            addItem(index)
+            if (list == null) list = mutableListOf()
+            list?.add(measuredItemProvider.getAndMeasure(index))
         }
     }
 
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
index 2996035..7f5d9cb 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/lazy/layout/LazyLayoutBeyondBoundsState.kt
@@ -58,4 +58,4 @@
         }
         return pinnedItems
     }
-}
\ No newline at end of file
+}
diff --git a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
index 2cc255c..4c6eb09 100644
--- a/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
+++ b/compose/foundation/foundation/src/commonMain/kotlin/androidx/compose/foundation/pager/PagerMeasure.kt
@@ -429,18 +429,15 @@
 
     val end = minOf(currentLastPage + beyondBoundsPageCount, pagesCount - 1)
 
-    fun addPage(index: Int) {
-        if (list == null) list = mutableListOf()
-        requireNotNull(list).add(getAndMeasure(index))
-    }
-
     for (i in currentLastPage + 1..end) {
-        addPage(i)
+        if (list == null) list = mutableListOf()
+        list.add(getAndMeasure(i))
     }
 
     pinnedPages.fastForEach { pageIndex ->
         if (pageIndex in (end + 1) until pagesCount) {
-            addPage(pageIndex)
+            if (list == null) list = mutableListOf()
+            list?.add(getAndMeasure(pageIndex))
         }
     }
 
@@ -457,20 +454,15 @@
 
     val start = maxOf(0, currentFirstPage - beyondBoundsPageCount)
 
-    fun addPage(index: Int) {
-        if (list == null) list = mutableListOf()
-        requireNotNull(list).add(
-            getAndMeasure(index)
-        )
-    }
-
     for (i in currentFirstPage - 1 downTo start) {
-        addPage(i)
+        if (list == null) list = mutableListOf()
+        list.add(getAndMeasure(i))
     }
 
     pinnedPages.fastForEach { pageIndex ->
         if (pageIndex < start) {
-            addPage(pageIndex)
+            if (list == null) list = mutableListOf()
+            list?.add(getAndMeasure(pageIndex))
         }
     }
 
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
index d666189..1c4e841 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/OutlinedTextFieldTest.kt
@@ -71,6 +71,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.semantics.error
+import androidx.compose.ui.semantics.getOrNull
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
@@ -79,6 +80,7 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
@@ -1080,19 +1082,32 @@
     @Test
     fun testErrorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
+        lateinit var defaultErrorMessage: String
         rule.setMaterialContent {
             var isError = remember { mutableStateOf(true) }
             OutlinedTextField(
                 value = "test",
                 onValueChange = {},
-                modifier = Modifier.semantics { if (isError.value) error(errorMessage) },
+                modifier = Modifier
+                    .testTag(TextfieldTag)
+                    .semantics { if (isError.value) error(errorMessage) },
                 isError = isError.value
             )
+            defaultErrorMessage = getString(Strings.DefaultErrorMessage)
         }
 
-        rule.onNodeWithText("test")
+        rule.onNodeWithTag(TextfieldTag)
             .assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage))
+
+        // Check that default error message is overwritten and not lingering in a child node
+        rule.onNodeWithTag(TextfieldTag, useUnmergedTree = true)
+            .onChildren()
+            .fetchSemanticsNodes()
+            .forEach { node ->
+                assertThat(node.config.getOrNull(SemanticsProperties.Error))
+                    .isNotEqualTo(defaultErrorMessage)
+            }
     }
 
     @Test
diff --git a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
index e57bdd9..214cfb7 100644
--- a/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
+++ b/compose/material/material/src/androidAndroidTest/kotlin/androidx/compose/material/textfield/TextFieldTest.kt
@@ -83,6 +83,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.semantics.error
+import androidx.compose.ui.semantics.getOrNull
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
@@ -91,6 +92,7 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
@@ -1235,19 +1237,32 @@
     @Test
     fun testErrorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
+        lateinit var defaultErrorMessage: String
         rule.setMaterialContent {
-            var isError = remember { mutableStateOf(true) }
+            val isError = remember { mutableStateOf(true) }
             TextField(
                 value = "test",
                 onValueChange = {},
-                modifier = Modifier.semantics { if (isError.value) error(errorMessage) },
+                modifier = Modifier
+                    .testTag(TextfieldTag)
+                    .semantics { if (isError.value) error(errorMessage) },
                 isError = isError.value
             )
+            defaultErrorMessage = getString(DefaultErrorMessage)
         }
 
-        rule.onNodeWithText("test")
+        rule.onNodeWithTag(TextfieldTag)
             .assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage))
+
+        // Check that default error message is overwritten and not lingering in a child node
+        rule.onNodeWithTag(TextfieldTag, useUnmergedTree = true)
+            .onChildren()
+            .fetchSemanticsNodes()
+            .forEach { node ->
+                assertThat(node.config.getOrNull(SemanticsProperties.Error))
+                    .isNotEqualTo(defaultErrorMessage)
+            }
     }
 
     @Test
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
index 5f3120a..8e90c16 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/OutlinedTextField.kt
@@ -172,6 +172,7 @@
             modifier
         }
             .background(colors.backgroundColor(enabled).value, shape)
+            .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
             .defaultMinSize(
                 minWidth = TextFieldDefaults.MinWidth,
                 minHeight = TextFieldDefaults.MinHeight
@@ -373,6 +374,7 @@
             modifier
         }
             .background(colors.backgroundColor(enabled).value, shape)
+            .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
             .defaultMinSize(
                 minWidth = TextFieldDefaults.MinWidth,
                 minHeight = TextFieldDefaults.MinHeight
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
index dfbd2c8..984e496 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextField.kt
@@ -191,6 +191,7 @@
         modifier = modifier
             .background(colors.backgroundColor(enabled).value, shape)
             .indicatorLine(enabled, isError, interactionSource, colors)
+            .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
             .defaultMinSize(
                 minWidth = TextFieldDefaults.MinWidth,
                 minHeight = TextFieldDefaults.MinHeight
@@ -379,6 +380,7 @@
         modifier = modifier
             .background(colors.backgroundColor(enabled).value, shape)
             .indicatorLine(enabled, isError, interactionSource, colors)
+            .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
             .defaultMinSize(
                 minWidth = TextFieldDefaults.MinWidth,
                 minHeight = TextFieldDefaults.MinHeight
diff --git a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
index f46c5b1..c947d0a 100644
--- a/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
+++ b/compose/material/material/src/commonMain/kotlin/androidx/compose/material/TextFieldImpl.kt
@@ -27,7 +27,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.defaultMinSize
-import androidx.compose.material.Strings.Companion.DefaultErrorMessage
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.ComposableOpenTarget
 import androidx.compose.runtime.CompositionLocalProvider
@@ -146,12 +145,6 @@
                 }
             } else null
 
-        // Developers need to handle invalid input manually. But since we don't provide error
-        // message slot API, we can set the default error message in case developers forget about
-        // it.
-        val defaultErrorMessage = getString(DefaultErrorMessage)
-        val decorationBoxModifier = Modifier.semantics { if (isError) error(defaultErrorMessage) }
-
         val leadingIconColor = if (colors is TextFieldColorsWithIcons) {
             colors.leadingIconColor(enabled, isError, interactionSource).value
         } else {
@@ -177,7 +170,7 @@
         when (type) {
             TextFieldType.Filled -> {
                 TextFieldLayout(
-                    modifier = decorationBoxModifier,
+                    modifier = Modifier,
                     textField = innerTextField,
                     placeholder = decoratedPlaceholder,
                     label = decoratedLabel,
@@ -201,7 +194,7 @@
                 }
 
                 OutlinedTextFieldLayout(
-                    modifier = decorationBoxModifier,
+                    modifier = Modifier,
                     textField = innerTextField,
                     placeholder = decoratedPlaceholder,
                     label = decoratedLabel,
@@ -255,6 +248,13 @@
     if (typography != null) ProvideTextStyle(typography, colorAndEmphasis) else colorAndEmphasis()
 }
 
+// Developers need to handle invalid input manually. But since we don't provide an error message
+// slot API, we can set the default error message in case developers forget about it.
+internal fun Modifier.defaultErrorSemantics(
+    isError: Boolean,
+    defaultErrorMessage: String,
+): Modifier = if (isError) semantics { error(defaultErrorMessage) } else this
+
 internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
 internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0
 
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
index c8a4298..fddbdf2a 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/OutlinedTextFieldTest.kt
@@ -52,6 +52,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.semantics.error
+import androidx.compose.ui.semantics.getOrNull
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
@@ -60,6 +61,7 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
@@ -1362,19 +1364,32 @@
     @Test
     fun testOutlinedTextField_errorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
+        lateinit var defaultErrorMessage: String
         rule.setMaterialContent(lightColorScheme()) {
             val isError = remember { mutableStateOf(true) }
             OutlinedTextField(
                 value = "test",
                 onValueChange = {},
-                modifier = Modifier.semantics { if (isError.value) error(errorMessage) },
+                modifier = Modifier
+                    .testTag(TextFieldTag)
+                    .semantics { if (isError.value) error(errorMessage) },
                 isError = isError.value
             )
+            defaultErrorMessage = getString(Strings.DefaultErrorMessage)
         }
 
-        rule.onNodeWithText("test")
+        rule.onNodeWithTag(TextFieldTag)
             .assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage))
+
+        // Check that default error message is overwritten and not lingering in a child node
+        rule.onNodeWithTag(TextFieldTag, useUnmergedTree = true)
+            .onChildren()
+            .fetchSemanticsNodes()
+            .forEach { node ->
+                assertThat(node.config.getOrNull(SemanticsProperties.Error))
+                    .isNotEqualTo(defaultErrorMessage)
+            }
     }
 
     @Test
diff --git a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
index ef94485..e1b215d 100644
--- a/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
+++ b/compose/material3/material3/src/androidAndroidTest/kotlin/androidx/compose/material3/TextFieldTest.kt
@@ -65,6 +65,7 @@
 import androidx.compose.ui.platform.testTag
 import androidx.compose.ui.semantics.SemanticsProperties
 import androidx.compose.ui.semantics.error
+import androidx.compose.ui.semantics.getOrNull
 import androidx.compose.ui.semantics.semantics
 import androidx.compose.ui.test.SemanticsMatcher
 import androidx.compose.ui.test.assert
@@ -74,6 +75,7 @@
 import androidx.compose.ui.test.captureToImage
 import androidx.compose.ui.test.click
 import androidx.compose.ui.test.junit4.createComposeRule
+import androidx.compose.ui.test.onChildren
 import androidx.compose.ui.test.onNodeWithTag
 import androidx.compose.ui.test.onNodeWithText
 import androidx.compose.ui.test.performClick
@@ -1466,19 +1468,32 @@
     @Test
     fun testTextField_errorSemantics_messageOverridable() {
         val errorMessage = "Special symbols not allowed"
+        lateinit var defaultErrorMessage: String
         rule.setMaterialContent(lightColorScheme()) {
             val isError = remember { mutableStateOf(true) }
             TextField(
                 value = "test",
                 onValueChange = {},
-                modifier = Modifier.semantics { if (isError.value) error(errorMessage) },
+                modifier = Modifier
+                    .testTag(TextFieldTag)
+                    .semantics { if (isError.value) error(errorMessage) },
                 isError = isError.value
             )
+            defaultErrorMessage = getString(DefaultErrorMessage)
         }
 
-        rule.onNodeWithText("test")
+        rule.onNodeWithTag(TextFieldTag)
             .assert(SemanticsMatcher.keyIsDefined(SemanticsProperties.Error))
             .assert(SemanticsMatcher.expectValue(SemanticsProperties.Error, errorMessage))
+
+        // Check that default error message is overwritten and not lingering in a child node
+        rule.onNodeWithTag(TextFieldTag, useUnmergedTree = true)
+            .onChildren()
+            .fetchSemanticsNodes()
+            .forEach { node ->
+                assertThat(node.config.getOrNull(SemanticsProperties.Error))
+                    .isNotEqualTo(defaultErrorMessage)
+            }
     }
 
     @Test
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
index 630f24b..3d47224 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/OutlinedTextField.kt
@@ -180,6 +180,7 @@
             } else {
                 modifier
             }
+                .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
                 .defaultMinSize(
                     minWidth = OutlinedTextFieldDefaults.MinWidth,
                     minHeight = OutlinedTextFieldDefaults.MinHeight
@@ -339,6 +340,7 @@
             } else {
                 modifier
             }
+                .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
                 .defaultMinSize(
                     minWidth = OutlinedTextFieldDefaults.MinWidth,
                     minHeight = OutlinedTextFieldDefaults.MinHeight
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
index cd786c6..039d06c 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextField.kt
@@ -198,6 +198,7 @@
         BasicTextField(
             value = value,
             modifier = modifier
+                .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
                 .defaultMinSize(
                     minWidth = TextFieldDefaults.MinWidth,
                     minHeight = TextFieldDefaults.MinHeight
@@ -343,6 +344,7 @@
         BasicTextField(
             value = value,
             modifier = modifier
+                .defaultErrorSemantics(isError, getString(Strings.DefaultErrorMessage))
                 .defaultMinSize(
                     minWidth = TextFieldDefaults.MinWidth,
                     minHeight = TextFieldDefaults.MinHeight
diff --git a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
index 6cfb01f..2ee2a6c 100644
--- a/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
+++ b/compose/material3/material3/src/commonMain/kotlin/androidx/compose/material3/TextFieldImpl.kt
@@ -27,7 +27,6 @@
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.PaddingValues
 import androidx.compose.foundation.layout.defaultMinSize
-import androidx.compose.material3.Strings.Companion.DefaultErrorMessage
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.CompositionLocalProvider
 import androidx.compose.runtime.getValue
@@ -172,12 +171,6 @@
                 }
             } else null
 
-        // Developers need to handle invalid input manually. But since we don't provide error
-        // message slot API, we can set the default error message in case developers forget about
-        // it.
-        val defaultErrorMessage = getString(DefaultErrorMessage)
-        val decorationBoxModifier = Modifier.semantics { if (isError) error(defaultErrorMessage) }
-
         val leadingIconColor = colors.leadingIconColor(enabled, isError, interactionSource).value
         val decoratedLeading: @Composable (() -> Unit)? = leadingIcon?.let {
             @Composable {
@@ -210,7 +203,7 @@
                 }
 
                 TextFieldLayout(
-                    modifier = decorationBoxModifier,
+                    modifier = Modifier,
                     textField = innerTextField,
                     placeholder = decoratedPlaceholder,
                     label = decoratedLabel,
@@ -240,7 +233,7 @@
                 }
 
                 OutlinedTextFieldLayout(
-                    modifier = decorationBoxModifier,
+                    modifier = Modifier,
                     textField = innerTextField,
                     placeholder = decoratedPlaceholder,
                     label = decoratedLabel,
@@ -286,6 +279,13 @@
     if (typography != null) ProvideTextStyle(typography, contentWithColor) else contentWithColor()
 }
 
+// Developers need to handle invalid input manually. But since we don't provide an error message
+// slot API, we can set the default error message in case developers forget about it.
+internal fun Modifier.defaultErrorSemantics(
+    isError: Boolean,
+    defaultErrorMessage: String,
+): Modifier = if (isError) semantics { error(defaultErrorMessage) } else this
+
 internal fun widthOrZero(placeable: Placeable?) = placeable?.width ?: 0
 internal fun heightOrZero(placeable: Placeable?) = placeable?.height ?: 0
 
diff --git a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/ColorFilter.kt b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/ColorFilter.kt
index 91bef45..6d45d4d 100644
--- a/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/ColorFilter.kt
+++ b/compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/ColorFilter.kt
@@ -59,9 +59,8 @@
          * A lighting ColorFilter is defined by two parameters, one used to multiply the source
          * color and one used to add to the source color
          *
-         * @param multiply Color that will be added to the source color when the color
-         *          filter is applied
-         * @param add Color used to multiply the source color when the color filter is applied.
+         * @param multiply Color used to multiply the source color when the color filter is applied.
+         * @param add Color that will be added to the source color when the color filter is applied.
          */
         @Stable
         fun lighting(multiply: Color, add: Color): ColorFilter =
diff --git a/compose/ui/ui/api/public_plus_experimental_current.txt b/compose/ui/ui/api/public_plus_experimental_current.txt
index 044964f..23a1cff 100644
--- a/compose/ui/ui/api/public_plus_experimental_current.txt
+++ b/compose/ui/ui/api/public_plus_experimental_current.txt
@@ -2363,22 +2363,9 @@
     method @androidx.compose.runtime.Stable public static operator long times(long, long size);
   }
 
-  @androidx.compose.ui.ExperimentalComposeUiApi public sealed interface SubcomposeIntermediateMeasureScope extends androidx.compose.ui.layout.SubcomposeMeasureScope {
-    method public long getLookaheadConstraints();
-    method public kotlin.jvm.functions.Function2<androidx.compose.ui.layout.SubcomposeMeasureScope,androidx.compose.ui.unit.Constraints,androidx.compose.ui.layout.MeasureResult> getLookaheadMeasurePolicy();
-    method public long getLookaheadSize();
-    method public java.util.List<androidx.compose.ui.layout.Measurable> measurablesForSlot(Object? slotId);
-    method public default java.util.List<androidx.compose.ui.layout.Measurable> subcompose(Object? slotId, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    property public abstract long lookaheadConstraints;
-    property public abstract kotlin.jvm.functions.Function2<androidx.compose.ui.layout.SubcomposeMeasureScope,androidx.compose.ui.unit.Constraints,androidx.compose.ui.layout.MeasureResult> lookaheadMeasurePolicy;
-    property public abstract long lookaheadSize;
-  }
-
   public final class SubcomposeLayoutKt {
     method @androidx.compose.runtime.Composable public static void SubcomposeLayout(optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
-    method @androidx.compose.runtime.Composable @androidx.compose.ui.ExperimentalComposeUiApi public static void SubcomposeLayout(optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeIntermediateMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> intermediateMeasurePolicy, kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
     method @androidx.compose.runtime.Composable @androidx.compose.ui.UiComposable public static void SubcomposeLayout(androidx.compose.ui.layout.SubcomposeLayoutState state, optional androidx.compose.ui.Modifier modifier, kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
-    method @androidx.compose.runtime.Composable @androidx.compose.ui.ExperimentalComposeUiApi @androidx.compose.ui.UiComposable public static void SubcomposeLayout(androidx.compose.ui.layout.SubcomposeLayoutState state, optional androidx.compose.ui.Modifier modifier, optional kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeIntermediateMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> intermediateMeasurePolicy, kotlin.jvm.functions.Function2<? super androidx.compose.ui.layout.SubcomposeMeasureScope,? super androidx.compose.ui.unit.Constraints,? extends androidx.compose.ui.layout.MeasureResult> measurePolicy);
     method public static androidx.compose.ui.layout.SubcomposeSlotReusePolicy SubcomposeSlotReusePolicy(int maxSlotsToRetainForReuse);
   }
 
@@ -2386,9 +2373,7 @@
     ctor public SubcomposeLayoutState(androidx.compose.ui.layout.SubcomposeSlotReusePolicy slotReusePolicy);
     ctor public SubcomposeLayoutState();
     ctor @Deprecated public SubcomposeLayoutState(int maxSlotsToRetainForReuse);
-    method @androidx.compose.ui.ExperimentalComposeUiApi public boolean isInLookaheadScope();
     method public androidx.compose.ui.layout.SubcomposeLayoutState.PrecomposedSlotHandle precompose(Object? slotId, kotlin.jvm.functions.Function0<kotlin.Unit> content);
-    property @androidx.compose.ui.ExperimentalComposeUiApi public final boolean isInLookaheadScope;
   }
 
   public static interface SubcomposeLayoutState.PrecomposedSlotHandle {
diff --git a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SubcomposeLayoutSample.kt b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SubcomposeLayoutSample.kt
index 9c932f2..b116741 100644
--- a/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SubcomposeLayoutSample.kt
+++ b/compose/ui/ui/samples/src/main/java/androidx/compose/ui/samples/SubcomposeLayoutSample.kt
@@ -17,27 +17,9 @@
 package androidx.compose.ui.samples
 
 import androidx.annotation.Sampled
-import androidx.compose.animation.core.Animatable
-import androidx.compose.animation.core.AnimationVector2D
-import androidx.compose.animation.core.VectorConverter
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.requiredSize
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.getValue
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.runtime.setValue
-import androidx.compose.ui.ExperimentalComposeUiApi
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.UiComposable
-import androidx.compose.ui.composed
-import androidx.compose.ui.layout.MeasurePolicy
 import androidx.compose.ui.layout.SubcomposeLayout
-import androidx.compose.ui.layout.intermediateLayout
-import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.IntSize
-import androidx.compose.ui.unit.dp
-import kotlinx.coroutines.launch
 
 @Sampled
 @Composable
@@ -67,97 +49,4 @@
     }
 }
 
-enum class SlotsEnum { Main, Dependent }
-
-@OptIn(ExperimentalComposeUiApi::class)
-@Sampled
-fun SubcomposeLayoutWithIntermediateMeasurePolicySample() {
-    // In this example, there is a custom modifier that animates the constraints and measures
-    // child with the animated constraints, as defined below.
-    // This modifier is built on top of `Modifier.intermediateLayout`, which
-    // allows access to the lookahead size of the layout. A resize animation will be kicked off
-    // whenever the lookahead size changes, to animate children from current size to lookahead size.
-    // Fixed constraints created based on the animation value will be used to measure
-    // child, so the child layout gradually changes its size and potentially its child's placement
-    // to fit within the animated constraints.
-    fun Modifier.animateConstraints() = composed {
-        // Creates a size animation
-        var sizeAnimation: Animatable<IntSize, AnimationVector2D>? by remember {
-            mutableStateOf(null)
-        }
-
-        this.intermediateLayout { measurable, _ ->
-            // When layout changes, the lookahead pass will calculate a new final size for the
-            // child layout. This lookahead size can be used to animate the size
-            // change, such that the animation starts from the current size and gradually
-            // change towards `lookaheadSize`.
-            if (lookaheadSize != sizeAnimation?.targetValue) {
-                sizeAnimation?.run {
-                    launch { animateTo(lookaheadSize) }
-                } ?: Animatable(lookaheadSize, IntSize.VectorConverter).let {
-                    sizeAnimation = it
-                }
-            }
-            val (width, height) = sizeAnimation!!.value
-            // Creates a fixed set of constraints using the animated size
-            val animatedConstraints = Constraints.fixed(width, height)
-            // Measure child with animated constraints.
-            val placeable = measurable.measure(animatedConstraints)
-            layout(placeable.width, placeable.height) {
-                placeable.place(0, 0)
-            }
-        }
-    }
-
-    // In the example below, the SubcomposeLayout has a parent layout that animates its width
-    // between two fixed sizes using the `animateConstraints` modifier we created above.
-    @Composable
-    fun SubcomposeLayoutWithAnimatingParentLayout(
-        isWide: Boolean,
-        modifier: Modifier = Modifier,
-        content: @Composable @UiComposable () -> Unit
-    ) {
-        // Create a MeasurePolicy to measure all children with incoming constraints and return the
-        // largest width & height.
-        val myMeasurePolicy = MeasurePolicy { measurables, constraints ->
-            val placeables = measurables.map { it.measure(constraints) }
-            val maxWidth = placeables.maxOf { it.width }
-            val maxHeight = placeables.maxOf { it.height }
-            layout(maxWidth, maxHeight) {
-                placeables.forEach { it.place(0, 0) }
-            }
-        }
-        Box(
-            Modifier
-                .requiredSize(if (isWide) 400.dp else 200.dp)
-                .animateConstraints()
-        ) {
-            // SubcomposeLayout's measurePolicy will only be invoked with lookahead constraints.
-            // The parent layout in this example is animating between two fixed widths. The
-            // [measurePolicy] parameter will only be called with lookahead constraints
-            // (i.e. constraints for 400.dp x 400.dp or 200.dp x 200.dp depending on the state.)
-            // This may cause content lambda to jump to its final size. To create a smooth
-            // experience, we need to remeasure the content with the intermediate
-            // constraints created by the `animateConstraints` that we built above. Therefore, we
-            // need to provide a [intermediateMeasurePolicy] to define how to measure the
-            // content (using the measureables of the content that was composed in [measurePolicy])
-            // with intermediate constraints.
-            SubcomposeLayout(
-                modifier,
-                intermediateMeasurePolicy = { intermediateConstraints ->
-                    // Retrieve the measureables for slotId = Unit, and measure them with
-                    // intermediate constraints using the measurePolicy we created above.
-                    with(myMeasurePolicy) {
-                        measure(
-                            measurablesForSlot(Unit),
-                            intermediateConstraints
-                        )
-                    }
-                },
-                measurePolicy = { constraints ->
-                    val measurables = subcompose(Unit) { content() }
-                    with(myMeasurePolicy) { measure(measurables, constraints) }
-                })
-        }
-    }
-}
\ No newline at end of file
+enum class SlotsEnum { Main, Dependent }
\ No newline at end of file
diff --git a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
index 378d5b7..942c141 100644
--- a/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
+++ b/compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/layout/LookaheadScopeTest.kt
@@ -196,7 +196,7 @@
                         Box(Modifier.fillMaxSize())
                     }[0].measure(constraints)
                     val size = placeable.run { IntSize(width, height) }
-                    if (this is SubcomposeIntermediateMeasureScope) {
+                    if (!isLookingAhead) {
                         actualSize = size
                     } else {
                         actualTargetSize = size
@@ -589,30 +589,12 @@
 
     @Test
     fun defaultMeasurePolicyInSubcomposeLayout() {
-        var actualLookaheadSize by mutableStateOf(IntSize.Zero)
         var defaultIntermediateMeasureSize by mutableStateOf(IntSize.Zero)
         rule.setContent {
             CompositionLocalProvider(LocalDensity provides Density(1f)) {
                 LookaheadScope {
                     SubcomposeLayout(
                         Modifier
-                            .fillMaxSize()
-                            .requiredSize(200.dp),
-                        intermediateMeasurePolicy = { constraints ->
-                            measurablesForSlot(Unit)[0].measure(constraints)
-                            actualLookaheadSize = this.lookaheadSize
-                            layout(0, 0) {}
-                        }
-                    ) { constraints ->
-                        val placeable = subcompose(Unit) {
-                            Box(Modifier.requiredSize(400.dp, 600.dp))
-                        }[0].measure(constraints)
-                        layout(500, 300) {
-                            placeable.place(0, 0)
-                        }
-                    }
-                    SubcomposeLayout(
-                        Modifier
                             .size(150.dp)
                             .intermediateLayout { measurable, _ ->
                                 measurable
@@ -636,7 +618,6 @@
             }
         }
         rule.runOnIdle {
-            assertEquals(IntSize(500, 300), actualLookaheadSize)
             assertEquals(IntSize(500, 300), defaultIntermediateMeasureSize)
         }
     }
@@ -1719,12 +1700,18 @@
             mutableStateListOf<Int>().apply { addAll(expectedPlacementOrder1) }
 
         var iteration by mutableStateOf(0)
+        var lookaheadConstraints by mutableStateOf<Constraints?>(null)
         // Expect the default placement to be the same as lookahead
         rule.setContent {
             LookaheadScope {
-                SubcomposeLayout(
-                    intermediateMeasurePolicy = { lookaheadMeasurePolicy(lookaheadConstraints) }
-                ) { constraints ->
+                SubcomposeLayout { incomingConstraints ->
+                    val constraints = if (isLookingAhead) {
+                        lookaheadConstraints = incomingConstraints
+                        incomingConstraints
+                    } else {
+                        lookaheadConstraints!!
+                    }
+
                     val placeables = mutableListOf<Placeable>()
                     repeat(3) { id ->
                         subcompose(id) {
@@ -1975,20 +1962,32 @@
                         }
                         SubcomposeLayout(
                             Modifier
-                                .fillMaxSize()
-                                .requiredSize(200.dp),
-                            intermediateMeasurePolicy = { constraints ->
-                                assertFalse(isLookingAhead)
-                                measurablesForSlot(Unit)[0].measure(constraints)
-                                layout(0, 0) {}
-                            }
+                                .layout { measurable, constraints ->
+                                    measurable.measure(constraints).run {
+                                        if (isLookingAhead) {
+                                            assertEquals(500, width)
+                                            assertEquals(300, height)
+                                        } else {
+                                            assertEquals(100, width)
+                                            assertEquals(120, height)
+                                        }
+                                        layout(width, height) {
+                                            place(0, 0)
+                                        }
+                                    }
+                                }
                         ) { constraints ->
-                            assertTrue(isLookingAhead)
                             val placeable = subcompose(Unit) {
                                 Box(Modifier.requiredSize(400.dp, 600.dp))
                             }[0].measure(constraints)
-                            layout(500, 300) {
-                                placeable.place(0, 0)
+                            if (isLookingAhead) {
+                                layout(500, 300) {
+                                    placeable.place(0, 0)
+                                }
+                            } else {
+                                layout(100, 120) {
+                                    placeable.place(0, 0)
+                                }
                             }
                         }
                     }
diff --git a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
index d95d81b..619812e 100644
--- a/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
+++ b/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/SubcomposeLayout.kt
@@ -44,7 +44,6 @@
 import androidx.compose.ui.node.requireOwner
 import androidx.compose.ui.platform.createSubcomposition
 import androidx.compose.ui.unit.Constraints
-import androidx.compose.ui.unit.IntSize
 import androidx.compose.ui.unit.LayoutDirection
 
 /**
@@ -83,155 +82,6 @@
  * for example to use the values calculated during the measurement as params for the composition
  * of the children.
  *
- * When in a [LookaheadScope], [SubcomposeLayout] will be measured up to twice per frame.
- * The two measurements will be using different measure policies and potentially different
- * constraints.
- *
- * The first measurement happens in the lookahead pass, where new layout is calculated based on
- * the target constraints. Therefore, [measurePolicy] will receive the target constraints, and
- * subcompose its content based on the target constraints. Note: Target constraints refers to
- * the constraints that the [SubcomposeLayout] will receive once all the lookahead-based
- * animations on size/constraints in the ancestor layouts have finished.
- *
- * The second measurement is done in the intermediate measure pass after the lookahead pass.
- * The intermediate measure pass allows adjustments to the measurement/placement using the
- * pre-calculated layout information as animation targets to smooth over any
- * any layout changes. In this measurement, [intermediateMeasurePolicy] will be invoked with
- * the intermediate/animating constraints. By default, [measurePolicy] will be invoked in
- * [intermediateMeasurePolicy], and hence the same measure logic in [measurePolicy] with
- * intermediate constraints will be used to measure and layout children in the intermediate
- * pass.
- *
- * Note: When [measurePolicy] is invoked in the intermediate pass, `subcompose` will simply
- * return the measurables associated with the given slot id based on the subcomposition during
- * lookahead pass. This means if a given slot id has not been subcomposed in the lookahead pass,
- * invoking subcompose during intermediate pass will result in an empty list.
- *
- * Possible use cases:
- * * You need to know the constraints passed by the parent during the composition and can't solve
- * your use case with just custom [Layout] or [LayoutModifier].
- * See [androidx.compose.foundation.layout.BoxWithConstraints].
- * * You want to use the size of one child during the composition of the second child.
- * * You want to compose your items lazily based on the available size. For example you have a
- * list of 100 items and instead of composing all of them you only compose the ones which are
- * currently visible(say 5 of them) and compose next items when the component is scrolled.
- *
- * @sample androidx.compose.ui.samples.SubcomposeLayoutWithIntermediateMeasurePolicySample
- *
- * @param modifier [Modifier] to apply for the layout.
- * @param intermediateMeasurePolicy A measure policy that will be invoked during the intermediate
- *                                  measure pass.
- * @param measurePolicy Measure policy which provides ability to subcompose during the measuring.
- */
-@ExperimentalComposeUiApi
-@Composable
-fun SubcomposeLayout(
-    modifier: Modifier = Modifier,
-    intermediateMeasurePolicy:
-    (SubcomposeIntermediateMeasureScope.(Constraints) -> MeasureResult) = { constraints ->
-        lookaheadMeasurePolicy(constraints)
-    },
-    measurePolicy: SubcomposeMeasureScope.(Constraints) -> MeasureResult
-) {
-    SubcomposeLayout(
-        state = remember { SubcomposeLayoutState() },
-        modifier = modifier,
-        intermediateMeasurePolicy = intermediateMeasurePolicy,
-        measurePolicy = measurePolicy
-    )
-}
-
-/**
- * [SubcomposeIntermediateMeasureScope] is the receiver scope for the intermediate measurer policy
- * that gets invoked during the intermediate measure pass.
- *
- * When in a [LookaheadScope], [SubcomposeLayout] will be measured up to twice per frame.
- * The two measurements will be using different measure policies and potentially different
- * constraints.
- *
- * The first measurement happens in the lookahead pass, where new layout is calculated based on
- * the target constraints. Therefore, measurePolicy will receive the target constraints, and
- * subcompose its content based on the target constraints. Note: Target constraints refers to
- * the constraints that the [SubcomposeLayout] will receive once all the lookahead-based
- * animations on size/constraints in the ancestor layouts have finished.
- *
- * The second measurement is done in the intermediate measure pass after the lookahead pass.
- * The intermediate measure pass allows adjustments to the measurement/placement using the
- * pre-calculated layout information as animation targets to smooth over any
- * any layout changes. In this measurement, intermediateMeasurePolicy will be invoked with
- * the intermediate/animating constraints. By default, measure policy will be invoked in
- * intermediateMeasurePolicy, and hence the same measure logic in measurePolicy with
- * intermediate constraints will be used to measure and layout children in the intermediate
- * pass.
- *
- * Note: When measurePolicy is invoked in [SubcomposeIntermediateMeasureScope], `subcompose` will
- * simply retrieve the measurables associated with the given slot id based on the subcomposition
- * during lookahead pass. This means if a given slot id has not been subcomposed in the lookahead
- * pass, invoking subcompose during intermediate pass will result in an empty list.
- *
- * @sample androidx.compose.ui.samples.SubcomposeLayoutWithIntermediateMeasurePolicySample
- */
-@ExperimentalComposeUiApi
-sealed interface SubcomposeIntermediateMeasureScope : SubcomposeMeasureScope {
-    /**
-     * Returns the list of measureables associated with [slotId] that was subcomposed in the
-     * [SubcomposeLayout]'s measurePolicy block during the lookahead pass. If the given [slotId]
-     * was not used in the subcomoposition, the returned list will be empty.
-     */
-    fun measurablesForSlot(slotId: Any?): List<Measurable>
-
-    /**
-     * The size returned in the [MeasureResult] by the measurePolicy invoked during lookahead pass.
-     */
-    val lookaheadSize: IntSize
-
-    /**
-     * This is the measure policy that is supplied to SubcomposeLayout in the measurePolicy
-     * parameter. It is used in the lookahead pass, and it is also invoked by default in the
-     * intermediateMeasurePolicy for the intermediate measure pass.
-     *
-     * During the intermediate pass, the [lookaheadMeasurePolicy] will receive potentially
-     * different (i.e. animating) constraints, and will subsequently remeasure and replace
-     * all children according to the new constraints.
-     *
-     * Note: Intermediate measure pass will NOT run **new** subcompositions. [subcompose]
-     * calls in from the [lookaheadMeasurePolicy] in this pass will instead retrieve the measurables
-     * for the given slot based on the subcomposition from lookahead pass. In the rare
-     * case where slots are subcomposed conditionally dependent on constraints, it's recommended
-     * to provide to [SubcomposeLayout] a custom intermediate measure policy. A less desirable
-     * solution to this use case is to invoke [lookaheadMeasurePolicy] with [lookaheadConstraints]
-     * as its parameter, which will skip any intermediate stages straight to the lookahead
-     * sizes & positions.
-     */
-    val lookaheadMeasurePolicy: SubcomposeMeasureScope.(Constraints) -> MeasureResult
-
-    /**
-     * Returns the [Constraints] used in the lookahead pass.
-     *
-     * Note: Using this with [lookaheadMeasurePolicy] will effectively skip any intermediate stages
-     * from lookahead-based layout animations. Therefore it is recommended to use [Constraints]
-     * passed to intermediate measure policy to measure and layout children during intermediate
-     * pass. The only exception to that should be when some of the subcompositions are conditional.
-     * In that case, a custom intermediate measure policy should ideally be provided to
-     * [SubcomposeLayout]. Using [lookaheadConstraints] with [lookaheadMeasurePolicy] should be
-     * considered as the last resort.
-     */
-    val lookaheadConstraints: Constraints
-
-    /**
-     * This function retrieves [Measurable]s created for [slotId] based on
-     * the subcomposition that happened in the lookahead pass. If [slotId] was not subcomposed
-     * in the lookahead pass, [subcompose] will return an [emptyList].
-     */
-    override fun subcompose(slotId: Any?, content: @Composable () -> Unit): List<Measurable> =
-        measurablesForSlot(slotId)
-}
-
-/**
- * Analogue of [Layout] which allows to subcompose the actual content during the measuring stage
- * for example to use the values calculated during the measurement as params for the composition
- * of the children.
- *
  * Possible use cases:
  * * You need to know the constraints passed by the parent during the composition and can't solve
  * your use case with just custom [Layout] or [LayoutModifier].
@@ -254,66 +104,6 @@
     modifier: Modifier = Modifier,
     measurePolicy: SubcomposeMeasureScope.(Constraints) -> MeasureResult
 ) {
-    @OptIn(ExperimentalComposeUiApi::class)
-    SubcomposeLayout(state, modifier, { lookaheadMeasurePolicy(it) }, measurePolicy)
-}
-
-/**
- * Analogue of [Layout] which allows to subcompose the actual content during the measuring stage
- * for example to use the values calculated during the measurement as params for the composition
- * of the children.
- *
- * When in a [LookaheadScope], [SubcomposeLayout] will be measured up to twice per frame.
- * The two measurements will be using different measure policies and potentially different
- * constraints.
- *
- * The first measurement happens in the lookahead pass, where new layout is calculated based on
- * the target constraints. Therefore, [measurePolicy] will receive the target constraints, and
- * subcompose its content based on the target constraints. Note: Target constraints refers to
- * the constraints that the [SubcomposeLayout] will receive once all the lookahead-based
- * animations on size/constraints in the ancestor layouts have finished.
- *
- * The second measurement is done in the intermediate measure pass after the lookahead pass.
- * The intermediate measure pass allows adjustments to the measurement/placement using the
- * pre-calculated layout information as animation targets to smooth over any
- * any layout changes. In this measurement, [intermediateMeasurePolicy] will be invoked with
- * the intermediate/animating constraints. By default, [measurePolicy] will be invoked in
- * [intermediateMeasurePolicy], and hence the same measure logic in [measurePolicy] with
- * intermediate constraints will be used to measure and layout children in the intermediate
- * pass.
- *
- * Note: When [measurePolicy] is invoked in the intermediate pass, `subcompose` will simply
- * return the measurables associated with the given slot id based on the subcomposition during
- * lookahead pass. This means if a given slot id has not been subcomposed in the lookahead pass,
- * invoking subcompose during intermediate pass will result in an empty list.
- *
- * Possible use cases:
- * * You need to know the constraints passed by the parent during the composition and can't solve
- * your use case with just custom [Layout] or [LayoutModifier].
- * See [androidx.compose.foundation.layout.BoxWithConstraints].
- * * You want to use the size of one child during the composition of the second child.
- * * You want to compose your items lazily based on the available size. For example you have a
- * list of 100 items and instead of composing all of them you only compose the ones which are
- * currently visible(say 5 of them) and compose next items when the component is scrolled.
- *
- * @param state the state object to be used by the layout.
- * @param modifier [Modifier] to apply for the layout.
- * @param intermediateMeasurePolicy A measure policy that will be invoked during the intermediate
- *                                  measure pass.
- * @param measurePolicy Measure policy which provides ability to subcompose during the measuring.
- */
-@Composable
-@UiComposable
-@ExperimentalComposeUiApi
-fun SubcomposeLayout(
-    state: SubcomposeLayoutState,
-    modifier: Modifier = Modifier,
-    intermediateMeasurePolicy:
-    (SubcomposeIntermediateMeasureScope.(Constraints) -> MeasureResult) = { constraints ->
-        lookaheadMeasurePolicy(constraints)
-    },
-    measurePolicy: SubcomposeMeasureScope.(Constraints) -> MeasureResult
-) {
     val compositionContext = rememberCompositionContext()
     val materialized = currentComposer.materialize(modifier)
     val localMap = currentComposer.currentCompositionLocalMap
@@ -323,10 +113,6 @@
             set(state, state.setRoot)
             set(compositionContext, state.setCompositionContext)
             set(measurePolicy, state.setMeasurePolicy)
-            set(
-                intermediateMeasurePolicy,
-                state.setIntermediateMeasurePolicy
-            )
             set(localMap, ComposeUiNode.SetResolvedCompositionLocals)
             set(materialized, ComposeUiNode.SetModifier)
         }
@@ -359,6 +145,11 @@
      * used during the previous measuring.
      * @param content the composable content which defines the slot. It could emit multiple
      * layouts, in this case the returned list of [Measurable]s will have multiple elements.
+     * **Note:** When a [SubcomposeLayout] is in a [LookaheadScope], the subcomposition only
+     * happens during the lookahead pass. In the post-lookahead/main pass, [subcompose] will
+     * return the list of [Measurable]s that were subcomposed during the lookahead pass. If the
+     * structure of the subtree emitted from [content] is dependent on incoming constraints,
+     * consider using constraints received from the lookahead pass for both passes.
      */
     fun subcompose(slotId: Any?, content: @Composable () -> Unit): List<Measurable>
 }
@@ -368,7 +159,6 @@
  *
  * [slotReusePolicy] the policy defining what slots should be retained to be reused later.
  */
-@OptIn(ExperimentalComposeUiApi::class)
 class SubcomposeLayoutState(
     private val slotReusePolicy: SubcomposeSlotReusePolicy
 ) {
@@ -396,16 +186,6 @@
         SubcomposeSlotReusePolicy(maxSlotsToRetainForReuse)
     )
 
-    /**
-     * Returns whether the [SubcomposeLayout] is in a [LookaheadScope]. Intermediate measure policy
-     * will be only invoked when in a [LookaheadScope].
-     */
-    @Suppress("OPT_IN_MARKER_ON_WRONG_TARGET")
-    @get:ExperimentalComposeUiApi
-    @ExperimentalComposeUiApi
-    val isInLookaheadScope: Boolean
-        get() = state.isInLookaheadScope
-
     private var _state: LayoutNodeSubcompositionsState? = null
     private val state: LayoutNodeSubcompositionsState
         get() = requireNotNull(_state) {
@@ -428,10 +208,6 @@
         LayoutNode.((SubcomposeMeasureScope.(Constraints) -> MeasureResult)) -> Unit =
         { measurePolicy = state.createMeasurePolicy(it) }
 
-    internal val setIntermediateMeasurePolicy:
-        LayoutNode.(SubcomposeIntermediateMeasureScope.(Constraints) -> MeasureResult) -> Unit =
-        { state.intermediateMeasurePolicy = it }
-
     /**
      * Composes the content for the given [slotId]. This makes the next scope.subcompose(slotId)
      * call during the measure pass faster as the content is already composed.
@@ -601,18 +377,8 @@
     // this map contains active slotIds (without precomposed or reusable nodes)
     private val slotIdToNode = mutableMapOf<Any?, LayoutNode>()
     private val scope = Scope()
-    private val intermediateMeasureScope = IntermediateMeasureScopeImpl()
+    private val postLookaheadMeasureScope = PostLookaheadMeasureScopeImpl()
 
-    /**
-     * This is the intermediateMeasurePolicy that developers set in [SubcomposeLayout]. It defaults
-     * to invoking [SubcomposeIntermediateMeasureScope.lookaheadMeasurePolicy].
-     *
-     * Note: This intermediate measure policy is only invoked when in a [LookaheadScope].
-     */
-    internal var intermediateMeasurePolicy:
-        (SubcomposeIntermediateMeasureScope.(Constraints) -> MeasureResult) = {
-        lookaheadMeasurePolicy(it)
-    }
     private val precomposeMap = mutableMapOf<Any?, LayoutNode>()
     private val reusableSlotIdsSet = SubcomposeSlotReusePolicy.SlotIdsSet()
 
@@ -840,7 +606,6 @@
     fun createMeasurePolicy(
         block: SubcomposeMeasureScope.(Constraints) -> MeasureResult
     ): MeasurePolicy {
-        intermediateMeasureScope.lookaheadMeasurePolicy = block
         return object : LayoutNode.NoIntrinsicsMeasurePolicy(error = NoIntrinsicsMessage) {
             override fun MeasureScope.measure(
                 measurables: List<Measurable>,
@@ -849,17 +614,14 @@
                 scope.layoutDirection = layoutDirection
                 scope.density = density
                 scope.fontScale = fontScale
-                val isIntermediate =
-                    (root.layoutState == LayoutState.Measuring ||
-                        root.layoutState == LayoutState.LayingOut) && root.lookaheadRoot != null
-                if (isIntermediate) {
-                    return intermediateMeasurePolicy.invoke(intermediateMeasureScope, constraints)
+                if (!isLookingAhead && root.lookaheadRoot != null) {
+                    return with(postLookaheadMeasureScope) {
+                        block(constraints)
+                    }
                 } else {
                     currentIndex = 0
-                    intermediateMeasureScope.lookaheadConstraints = constraints
                     val result = scope.block(constraints)
                     val indexAfterMeasure = currentIndex
-                    intermediateMeasureScope.lookaheadSize = IntSize(result.width, result.height)
                     return object : MeasureResult {
                         override val width: Int
                             get() = result.width
@@ -1008,19 +770,15 @@
             this@LayoutNodeSubcompositionsState.subcompose(slotId, content)
     }
 
-    private inner class IntermediateMeasureScopeImpl :
-        SubcomposeIntermediateMeasureScope, MeasureScope by scope {
-        override fun measurablesForSlot(slotId: Any?): List<Measurable> =
-            slotIdToNode[slotId]?.childMeasurables ?: emptyList()
-
+    private inner class PostLookaheadMeasureScopeImpl :
+        SubcomposeMeasureScope, MeasureScope by scope {
         /**
-         * This is the size returned in the MeasureResult in the measure policy from the lookahead
-         * pass.
+         * This function retrieves [Measurable]s created for [slotId] based on
+         * the subcomposition that happened in the lookahead pass. If [slotId] was not subcomposed
+         * in the lookahead pass, [subcompose] will return an [emptyList].
          */
-        override var lookaheadSize: IntSize = IntSize.Zero
-        override lateinit var lookaheadMeasurePolicy:
-            SubcomposeMeasureScope.(Constraints) -> MeasureResult
-        override var lookaheadConstraints: Constraints = Constraints()
+        override fun subcompose(slotId: Any?, content: @Composable () -> Unit): List<Measurable> =
+            slotIdToNode[slotId]?.childMeasurables ?: emptyList()
     }
 }
 
diff --git a/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbManagerImpl.kt b/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbManagerImpl.kt
index 34ff68e..489bef6 100644
--- a/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbManagerImpl.kt
+++ b/core/uwb/uwb/src/main/java/androidx/core/uwb/impl/UwbManagerImpl.kt
@@ -83,6 +83,10 @@
         Log.i(TAG, "Creating Gms Client session scope")
         val uwbClient = if (isController)
             Nearby.getUwbControllerClient(context) else Nearby.getUwbControleeClient(context)
+        if (!uwbClient.isAvailable().await()) {
+            Log.e(TAG, "Uwb availability : false")
+            throw RuntimeException("Cannot start a ranging session when UWB is unavailable")
+        }
         try {
             val nearbyLocalAddress = uwbClient.localAddress.await()
             val nearbyRangingCapabilities = uwbClient.rangingCapabilities.await()
diff --git a/docs-public/build.gradle b/docs-public/build.gradle
index 8ce18e2..b2b8c41 100644
--- a/docs-public/build.gradle
+++ b/docs-public/build.gradle
@@ -214,29 +214,30 @@
     docs("androidx.media2:media2-session:1.2.1")
     docs("androidx.media2:media2-widget:1.2.1")
     docs("androidx.media:media:1.6.0")
-    docs("androidx.media3:media3-cast:1.0.1")
-    docs("androidx.media3:media3-common:1.0.1")
-    docs("androidx.media3:media3-database:1.0.1")
-    docs("androidx.media3:media3-datasource:1.0.1")
-    docs("androidx.media3:media3-datasource-cronet:1.0.1")
-    docs("androidx.media3:media3-datasource-okhttp:1.0.1")
-    docs("androidx.media3:media3-datasource-rtmp:1.0.1")
-    docs("androidx.media3:media3-decoder:1.0.1")
-    docs("androidx.media3:media3-effect:1.0.1")
-    docs("androidx.media3:media3-exoplayer:1.0.1")
-    docs("androidx.media3:media3-exoplayer-dash:1.0.1")
-    docs("androidx.media3:media3-exoplayer-hls:1.0.1")
-    docs("androidx.media3:media3-exoplayer-ima:1.0.1")
-    docs("androidx.media3:media3-exoplayer-rtsp:1.0.1")
-    docs("androidx.media3:media3-exoplayer-smoothstreaming:1.0.1")
-    docs("androidx.media3:media3-exoplayer-workmanager:1.0.1")
-    docs("androidx.media3:media3-extractor:1.0.1")
-    docs("androidx.media3:media3-session:1.0.1")
-    docs("androidx.media3:media3-test-utils:1.0.1")
-    docs("androidx.media3:media3-test-utils-robolectric:1.0.1")
-    docs("androidx.media3:media3-transformer:1.0.1")
-    docs("androidx.media3:media3-ui:1.0.1")
-    docs("androidx.media3:media3-ui-leanback:1.0.1")
+    docs("androidx.media3:media3-cast:1.1.0-alpha01")
+    docs("androidx.media3:media3-common:1.1.0-alpha01")
+    docs("androidx.media3:media3-database:1.1.0-alpha01")
+    docs("androidx.media3:media3-datasource:1.1.0-alpha01")
+    docs("androidx.media3:media3-datasource-cronet:1.1.0-alpha01")
+    docs("androidx.media3:media3-datasource-okhttp:1.1.0-alpha01")
+    docs("androidx.media3:media3-datasource-rtmp:1.1.0-alpha01")
+    docs("androidx.media3:media3-decoder:1.1.0-alpha01")
+    docs("androidx.media3:media3-effect:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-dash:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-hls:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-ima:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-rtsp:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-smoothstreaming:1.1.0-alpha01")
+    docs("androidx.media3:media3-exoplayer-workmanager:1.1.0-alpha01")
+    docs("androidx.media3:media3-extractor:1.1.0-alpha01")
+    docs("androidx.media3:media3-muxer:1.1.0-alpha01")
+    docs("androidx.media3:media3-session:1.1.0-alpha01")
+    docs("androidx.media3:media3-test-utils:1.1.0-alpha01")
+    docs("androidx.media3:media3-test-utils-robolectric:1.1.0-alpha01")
+    docs("androidx.media3:media3-transformer:1.1.0-alpha01")
+    docs("androidx.media3:media3-ui:1.1.0-alpha01")
+    docs("androidx.media3:media3-ui-leanback:1.1.0-alpha01")
     docs("androidx.mediarouter:mediarouter:1.6.0-alpha03")
     docs("androidx.mediarouter:mediarouter-testing:1.6.0-alpha03")
     docs("androidx.metrics:metrics-performance:1.0.0-alpha04")
diff --git a/glance/glance-appwidget-preview/build.gradle b/glance/glance-appwidget-preview/build.gradle
index 20fd21c..392729b 100644
--- a/glance/glance-appwidget-preview/build.gradle
+++ b/glance/glance-appwidget-preview/build.gradle
@@ -14,19 +14,15 @@
  * limitations under the License.
  */
 
-import androidx.build.AndroidXComposePlugin
 import androidx.build.LibraryType
-import androidx.build.Publish
 
 plugins {
     id("AndroidXComposePlugin")
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
 
     api(libs.kotlinStdlib)
diff --git a/glance/glance-appwidget-preview/src/androidAndroidTest/AndroidManifest.xml b/glance/glance-appwidget-preview/src/androidTest/AndroidManifest.xml
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidAndroidTest/AndroidManifest.xml
rename to glance/glance-appwidget-preview/src/androidTest/AndroidManifest.xml
diff --git a/glance/glance-appwidget-preview/src/androidAndroidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetPreviews.kt b/glance/glance-appwidget-preview/src/androidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetPreviews.kt
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidAndroidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetPreviews.kt
rename to glance/glance-appwidget-preview/src/androidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetPreviews.kt
diff --git a/glance/glance-appwidget-preview/src/androidAndroidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapterTest.kt b/glance/glance-appwidget-preview/src/androidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapterTest.kt
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidAndroidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapterTest.kt
rename to glance/glance-appwidget-preview/src/androidTest/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapterTest.kt
diff --git a/glance/glance-appwidget-preview/src/androidAndroidTest/res/layout/glance_appwidget_adapter_test.xml b/glance/glance-appwidget-preview/src/androidTest/res/layout/glance_appwidget_adapter_test.xml
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidAndroidTest/res/layout/glance_appwidget_adapter_test.xml
rename to glance/glance-appwidget-preview/src/androidTest/res/layout/glance_appwidget_adapter_test.xml
diff --git a/glance/glance-appwidget-preview/src/androidAndroidTest/res/values/styles.xml b/glance/glance-appwidget-preview/src/androidTest/res/values/styles.xml
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidAndroidTest/res/values/styles.xml
rename to glance/glance-appwidget-preview/src/androidTest/res/values/styles.xml
diff --git a/glance/glance-appwidget-preview/src/androidMain/kotlin/androidx/glance/appwidget/preview/ComposableInvoker.kt b/glance/glance-appwidget-preview/src/main/java/androidx/glance/appwidget/preview/ComposableInvoker.kt
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidMain/kotlin/androidx/glance/appwidget/preview/ComposableInvoker.kt
rename to glance/glance-appwidget-preview/src/main/java/androidx/glance/appwidget/preview/ComposableInvoker.kt
diff --git a/glance/glance-appwidget-preview/src/androidMain/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapter.kt b/glance/glance-appwidget-preview/src/main/java/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapter.kt
similarity index 100%
rename from glance/glance-appwidget-preview/src/androidMain/kotlin/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapter.kt
rename to glance/glance-appwidget-preview/src/main/java/androidx/glance/appwidget/preview/GlanceAppWidgetViewAdapter.kt
diff --git a/glance/glance-appwidget/build.gradle b/glance/glance-appwidget/build.gradle
index 158c764..4b59ee3 100644
--- a/glance/glance-appwidget/build.gradle
+++ b/glance/glance-appwidget/build.gradle
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-import androidx.build.AndroidXComposePlugin
 import androidx.build.BundleInsideHelper
 import androidx.build.LibraryType
 import androidx.glance.appwidget.layoutgenerator.gradle.LayoutGeneratorTask
 
 plugins {
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
     id("AndroidXComposePlugin")
     id("com.google.protobuf")
@@ -32,9 +32,6 @@
         /* to =   */ "androidx.glance.appwidget.protobuf"
 )
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */ false)
-
 dependencies {
     bundleInside(project(path: ":glance:glance-appwidget-proto", configuration: "export"))
 
@@ -121,6 +118,6 @@
 LayoutGeneratorTask.registerLayoutGenerator(
         project,
         android,
-        /* containerLayoutDirectory= */ file("src/androidMain/layoutTemplates"),
-        /* childLayoutDirectory= */ file("src/androidMain/res/layout")
+        /* containerLayoutDirectory= */ file("src/main/layoutTemplates"),
+        /* childLayoutDirectory= */ file("src/main/res/layout")
 )
diff --git a/glance/glance-appwidget/lint-baseline.xml b/glance/glance-appwidget/lint-baseline.xml
index e61bfc7..805d083 100644
--- a/glance/glance-appwidget/lint-baseline.xml
+++ b/glance/glance-appwidget/lint-baseline.xml
@@ -7,7 +7,7 @@
         errorLine1="        Thread.sleep(5000)"
         errorLine2="               ~~~~~">
         <location
-            file="src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt"/>
+            file="src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt"/>
     </issue>
 
     <issue
@@ -16,7 +16,7 @@
         errorLine1="                        Thread.sleep(500)"
         errorLine2="                               ~~~~~">
         <location
-            file="src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt"/>
+            file="src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt"/>
     </issue>
 
     <issue
@@ -25,7 +25,7 @@
         errorLine1="            Thread.sleep(sleepMs)"
         errorLine2="                   ~~~~~">
         <location
-            file="src/androidAndroidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt"/>
+            file="src/androidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt"/>
     </issue>
 
     <issue
@@ -34,7 +34,7 @@
         errorLine1="            Thread.sleep(interval)"
         errorLine2="                   ~~~~~">
         <location
-            file="src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt"/>
+            file="src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt"/>
     </issue>
 
 </issues>
diff --git a/glance/glance-appwidget/samples/src/main/java/androidx/glance/appwidget/samples/GlanceAppWidgetSamples.kt b/glance/glance-appwidget/samples/src/main/java/androidx/glance/appwidget/samples/GlanceAppWidgetSamples.kt
index 43fec19..c290ed7 100644
--- a/glance/glance-appwidget/samples/src/main/java/androidx/glance/appwidget/samples/GlanceAppWidgetSamples.kt
+++ b/glance/glance-appwidget/samples/src/main/java/androidx/glance/appwidget/samples/GlanceAppWidgetSamples.kt
@@ -24,13 +24,17 @@
 import androidx.glance.text.Text
 
 @Sampled
-suspend fun GlanceAppWidget.provideGlanceSample(
-    @Suppress("UNUSED_PARAMETER") context: Context,
-    @Suppress("UNUSED_PARAMETER") id: GlanceId,
-) {
-    // Load data needed to render the AppWidget.
-    provideContent {
-        // create your AppWidget here
-        Text("Hello World")
+fun provideGlanceSample() {
+    class MyWidget : GlanceAppWidget() {
+        override suspend fun provideGlance(context: Context, id: GlanceId) {
+            // Load data needed to render the AppWidget here. Prefer doing heavy work before
+            // provideContent, as the provideGlance function will timeout shortly after
+            // provideContent is called.
+
+            provideContent {
+                // Declare your @Composable layout here.
+                Text("Hello World")
+            }
+        }
     }
 }
\ No newline at end of file
diff --git a/glance/glance-appwidget/src/androidAndroidTest/AndroidManifest.xml b/glance/glance-appwidget/src/androidTest/AndroidManifest.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/AndroidManifest.xml
rename to glance/glance-appwidget/src/androidTest/AndroidManifest.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AndroidTestUtils.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AndroidTestUtils.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AndroidTestUtils.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AndroidTestUtils.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostRule.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/AppWidgetHostTestActivity.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/CheckBoxTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiverTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetManagerTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetManagerTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetManagerTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetManagerTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverScreenshotTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiverTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceRemoteViewsTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceRemoteViewsTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/GlanceRemoteViewsTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/GlanceRemoteViewsTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/LazyColumnTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/RemoteCollectionItemsTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/RemoteCollectionItemsTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/RemoteCollectionItemsTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/RemoteCollectionItemsTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/ResourceResolutionTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/ResourceResolutionTest.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/ResourceResolutionTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/ResourceResolutionTest.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/ScreenshotsTests.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/ScreenshotsTests.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/ScreenshotsTests.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/ScreenshotsTests.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt
similarity index 96%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt
index 0caab64..a2f2e22 100644
--- a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt
+++ b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/StrictModeTest.kt
@@ -36,6 +36,7 @@
 import androidx.test.filters.SdkSuppress
 import androidx.test.platform.app.InstrumentationRegistry
 import com.google.common.truth.Truth
+import java.util.Arrays
 import java.util.concurrent.CountDownLatch
 import java.util.concurrent.Executors
 import java.util.concurrent.TimeUnit
@@ -65,7 +66,9 @@
                 .penaltyListener(executor) {
                     Log.e("StrictModeTest", "Logging violation:")
                     Log.e("StrictModeTest", "$it")
-                    Log.e("StrictModeTest", "Stack trace: ${it.stackTrace}", it.cause)
+                    Log.e("StrictModeTest", "Stack trace: ${Arrays.toString(it.stackTrace)}",
+                        it.cause)
+                    Log.e("StrictModeTest", "${it.cause}", it.cause)
                     fail("Received violation: $it")
                 }.build()
         )
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/TestGlanceAppWidgetReceiver.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/WithNightMode.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/WithNightMode.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/WithNightMode.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/WithNightMode.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/WithRtl.kt b/glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/WithRtl.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/kotlin/androidx/glance/appwidget/WithRtl.kt
rename to glance/glance-appwidget/src/androidTest/kotlin/androidx/glance/appwidget/WithRtl.kt
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/drawable/compose.png b/glance/glance-appwidget/src/androidTest/res/drawable/compose.png
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/drawable/compose.png
rename to glance/glance-appwidget/src/androidTest/res/drawable/compose.png
Binary files differ
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/drawable/filled_oval.xml b/glance/glance-appwidget/src/androidTest/res/drawable/filled_oval.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/drawable/filled_oval.xml
rename to glance/glance-appwidget/src/androidTest/res/drawable/filled_oval.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/drawable/oval.xml b/glance/glance-appwidget/src/androidTest/res/drawable/oval.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/drawable/oval.xml
rename to glance/glance-appwidget/src/androidTest/res/drawable/oval.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/layout/app_widget_host_activity.xml b/glance/glance-appwidget/src/androidTest/res/layout/app_widget_host_activity.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/layout/app_widget_host_activity.xml
rename to glance/glance-appwidget/src/androidTest/res/layout/app_widget_host_activity.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/layout/empty_layout.xml b/glance/glance-appwidget/src/androidTest/res/layout/empty_layout.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/layout/empty_layout.xml
rename to glance/glance-appwidget/src/androidTest/res/layout/empty_layout.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/layout/list_view_row.xml b/glance/glance-appwidget/src/androidTest/res/layout/list_view_row.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/layout/list_view_row.xml
rename to glance/glance-appwidget/src/androidTest/res/layout/list_view_row.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/layout/list_view_row_2.xml b/glance/glance-appwidget/src/androidTest/res/layout/list_view_row_2.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/layout/list_view_row_2.xml
rename to glance/glance-appwidget/src/androidTest/res/layout/list_view_row_2.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/layout/remote_views_list.xml b/glance/glance-appwidget/src/androidTest/res/layout/remote_views_list.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/layout/remote_views_list.xml
rename to glance/glance-appwidget/src/androidTest/res/layout/remote_views_list.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values-night/colors.xml b/glance/glance-appwidget/src/androidTest/res/values-night/colors.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values-night/colors.xml
rename to glance/glance-appwidget/src/androidTest/res/values-night/colors.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values-v29/themes.xml b/glance/glance-appwidget/src/androidTest/res/values-v29/themes.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values-v29/themes.xml
rename to glance/glance-appwidget/src/androidTest/res/values-v29/themes.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values/attrs.xml b/glance/glance-appwidget/src/androidTest/res/values/attrs.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values/attrs.xml
rename to glance/glance-appwidget/src/androidTest/res/values/attrs.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values/colors.xml b/glance/glance-appwidget/src/androidTest/res/values/colors.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values/colors.xml
rename to glance/glance-appwidget/src/androidTest/res/values/colors.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values/dimens.xml b/glance/glance-appwidget/src/androidTest/res/values/dimens.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values/dimens.xml
rename to glance/glance-appwidget/src/androidTest/res/values/dimens.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml b/glance/glance-appwidget/src/androidTest/res/values/themes.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/values/themes.xml
rename to glance/glance-appwidget/src/androidTest/res/values/themes.xml
diff --git a/glance/glance-appwidget/src/androidAndroidTest/res/xml/app_widget_info.xml b/glance/glance-appwidget/src/androidTest/res/xml/app_widget_info.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidAndroidTest/res/xml/app_widget_info.xml
rename to glance/glance-appwidget/src/androidTest/res/xml/app_widget_info.xml
diff --git a/glance/glance-appwidget/src/androidMain/AndroidManifest.xml b/glance/glance-appwidget/src/main/AndroidManifest.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/AndroidManifest.xml
rename to glance/glance-appwidget/src/main/AndroidManifest.xml
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AlignmentModifier.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AlignmentModifier.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AlignmentModifier.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AlignmentModifier.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AndroidRemoteViews.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AndroidRemoteViews.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AndroidRemoteViews.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AndroidRemoteViews.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetBackground.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetBackground.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetBackground.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetBackground.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetComposer.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetComposer.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetComposer.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetModifiers.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetModifiers.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetModifiers.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetModifiers.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetSession.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetSession.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetSession.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetSession.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetUtils.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/AppWidgetUtils.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/AppWidgetUtils.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ApplyModifiers.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ApplyModifiers.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ApplyModifiers.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Background.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Background.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Background.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Background.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CheckBox.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CheckBox.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CheckBox.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CircularProgressIndicator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CircularProgressIndicator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CircularProgressIndicator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CircularProgressIndicator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CompositionLocals.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CompositionLocals.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CompositionLocals.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CornerRadius.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CornerRadius.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CornerRadius.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CornerRadius.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiver.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CoroutineBroadcastReceiver.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/CoroutineBroadcastReceiver.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/CoroutineBroadcastReceiver.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ExperimentalGlanceRemoteViewsApi.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ExperimentalGlanceRemoteViewsApi.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ExperimentalGlanceRemoteViewsApi.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ExperimentalGlanceRemoteViewsApi.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidget.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidget.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetManager.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetManager.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetManager.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceAppWidgetReceiver.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceRemoteViews.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceRemoteViews.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceRemoteViews.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceRemoteViews.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceRemoteViewsService.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceRemoteViewsService.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/GlanceRemoteViewsService.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/GlanceRemoteViewsService.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/IgnoreResult.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/IgnoreResult.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/IgnoreResult.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/IgnoreResult.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ImageProviders.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ImageProviders.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/ImageProviders.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/ImageProviders.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/LayoutSelection.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/LayoutSelection.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/LayoutSelection.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/LayoutSelection.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/LinearProgressIndicator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/LinearProgressIndicator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/LinearProgressIndicator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/LinearProgressIndicator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/MyPackageReplacedReceiver.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/MyPackageReplacedReceiver.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/MyPackageReplacedReceiver.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/MyPackageReplacedReceiver.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/NormalizeCompositionTree.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/NormalizeCompositionTree.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/NormalizeCompositionTree.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RadioButton.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RadioButton.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RadioButton.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RadioButton.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteCollectionItems.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteCollectionItems.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteCollectionItems.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteCollectionItems.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteViewsRoot.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteViewsRoot.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsRoot.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteViewsTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/RemoteViewsTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/RemoteViewsTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/SizeBox.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeBox.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/SizeBox.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeBox.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/SizeMode.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/SizeMode.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/SizeMode.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Switch.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Switch.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Switch.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/TintAndAlphaColorFilterParams.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/TintAndAlphaColorFilterParams.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/TintAndAlphaColorFilterParams.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/TintAndAlphaColorFilterParams.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Utils.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Utils.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/Utils.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/Utils.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/WidgetLayout.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/WidgetLayout.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/WidgetLayout.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionCallbackBroadcastReceiver.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionCallbackBroadcastReceiver.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionCallbackBroadcastReceiver.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionCallbackBroadcastReceiver.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionTrampoline.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionTrampoline.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionTrampoline.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionTrampoline.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionTrampolineActivity.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionTrampolineActivity.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ActionTrampolineActivity.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ActionTrampolineActivity.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ApplyAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/ApplyAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/ApplyAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/CompoundButtonAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/CompoundButtonAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/CompoundButtonAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/CompoundButtonAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/InvisibleActionTrampolineActivity.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/InvisibleActionTrampolineActivity.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/InvisibleActionTrampolineActivity.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/InvisibleActionTrampolineActivity.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LambdaActionBroadcasts.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/LambdaActionBroadcasts.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/LambdaActionBroadcasts.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/LambdaActionBroadcasts.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/RunCallbackAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/RunCallbackAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/RunCallbackAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/SendBroadcastAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/SendBroadcastAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/SendBroadcastAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/SendBroadcastAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/StartActivityIntentAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/StartActivityIntentAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/StartActivityIntentAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/StartActivityIntentAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/StartServiceAction.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/StartServiceAction.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/StartServiceAction.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/StartServiceAction.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/Toggleable.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/Toggleable.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/action/Toggleable.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/action/Toggleable.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/lazy/LazyList.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyList.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/lazy/LazyList.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/lazy/LazyVerticalGrid.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/state/GlanceAppWidgetState.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/state/GlanceAppWidgetState.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/state/GlanceAppWidgetState.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/state/GlanceAppWidgetState.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CheckBoxTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CheckBoxTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CheckBoxTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CircularProgressIndicatorTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CircularProgressIndicatorTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CircularProgressIndicatorTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CircularProgressIndicatorTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CompoundButtonApi31Impl.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CompoundButtonApi31Impl.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CompoundButtonApi31Impl.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CompoundButtonApi31Impl.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CompoundButtonTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CompoundButtonTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/CompoundButtonTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/CompoundButtonTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/ImageTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/ImageTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/ImageTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/ImageTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LazyListTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LazyListTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LazyListTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LazyListTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LazyVerticalGridTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LazyVerticalGridTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LazyVerticalGridTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LazyVerticalGridTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LinearProgressIndicatorTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LinearProgressIndicatorTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/LinearProgressIndicatorTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/LinearProgressIndicatorTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/RadioButtonTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/RadioButtonTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/RadioButtonTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/RadioButtonTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/SwitchTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/SwitchTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/SwitchTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/SwitchTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/TextTranslator.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/TextTranslator.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/translators/TextTranslator.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/translators/TextTranslator.kt
diff --git a/glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/unit/ColorProvider.kt b/glance/glance-appwidget/src/main/java/androidx/glance/appwidget/unit/ColorProvider.kt
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/kotlin/androidx/glance/appwidget/unit/ColorProvider.kt
rename to glance/glance-appwidget/src/main/java/androidx/glance/appwidget/unit/ColorProvider.kt
diff --git a/glance/glance-appwidget/src/androidMain/layoutTemplates/box.xml b/glance/glance-appwidget/src/main/layoutTemplates/box.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/layoutTemplates/box.xml
rename to glance/glance-appwidget/src/main/layoutTemplates/box.xml
diff --git a/glance/glance-appwidget/src/androidMain/layoutTemplates/column.xml b/glance/glance-appwidget/src/main/layoutTemplates/column.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/layoutTemplates/column.xml
rename to glance/glance-appwidget/src/main/layoutTemplates/column.xml
diff --git a/glance/glance-appwidget/src/androidMain/layoutTemplates/radio_column.xml b/glance/glance-appwidget/src/main/layoutTemplates/radio_column.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/layoutTemplates/radio_column.xml
rename to glance/glance-appwidget/src/main/layoutTemplates/radio_column.xml
diff --git a/glance/glance-appwidget/src/androidMain/layoutTemplates/radio_row.xml b/glance/glance-appwidget/src/main/layoutTemplates/radio_row.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/layoutTemplates/radio_row.xml
rename to glance/glance-appwidget/src/main/layoutTemplates/radio_row.xml
diff --git a/glance/glance-appwidget/src/androidMain/layoutTemplates/row.xml b/glance/glance-appwidget/src/main/layoutTemplates/row.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/layoutTemplates/row.xml
rename to glance/glance-appwidget/src/main/layoutTemplates/row.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_box_inner_merged_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_box_inner_merged_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_box_inner_merged_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_box_inner_merged_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_box_outer_merged_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_box_outer_merged_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_box_outer_merged_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_box_outer_merged_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_icon_null_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_icon_null_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_checked_icon_null_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_checked_icon_null_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_box_inner_merged_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_box_inner_merged_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_box_inner_merged_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_box_inner_merged_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_check_path_merged_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_check_path_merged_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_check_path_merged_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_check_path_merged_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_icon_null_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_icon_null_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_checkbox_to_unchecked_icon_null_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_checkbox_to_unchecked_icon_null_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_dot_group_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_dot_group_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_dot_group_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_dot_group_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_path_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_path_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_path_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_off_mtrl_ring_outer_path_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_dot_group_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_dot_group_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_dot_group_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_dot_group_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_path_animation.xml b/glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_path_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_path_animation.xml
rename to glance/glance-appwidget/src/main/res/anim/glance_btn_radio_to_on_mtrl_ring_outer_path_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color-night/glance_default_switch_thumb.xml b/glance/glance-appwidget/src/main/res/color-night/glance_default_switch_thumb.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color-night/glance_default_switch_thumb.xml
rename to glance/glance-appwidget/src/main/res/color-night/glance_default_switch_thumb.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_default_check_box.xml b/glance/glance-appwidget/src/main/res/color/glance_default_check_box.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_default_check_box.xml
rename to glance/glance-appwidget/src/main/res/color/glance_default_check_box.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_default_radio_button.xml b/glance/glance-appwidget/src/main/res/color/glance_default_radio_button.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_default_radio_button.xml
rename to glance/glance-appwidget/src/main/res/color/glance_default_radio_button.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_default_switch_thumb.xml b/glance/glance-appwidget/src/main/res/color/glance_default_switch_thumb.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_default_switch_thumb.xml
rename to glance/glance-appwidget/src/main/res/color/glance_default_switch_thumb.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_default_switch_track.xml b/glance/glance-appwidget/src/main/res/color/glance_default_switch_track.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_default_switch_track.xml
rename to glance/glance-appwidget/src/main/res/color/glance_default_switch_track.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_switch_off_ambient_shadow.xml b/glance/glance-appwidget/src/main/res/color/glance_switch_off_ambient_shadow.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_switch_off_ambient_shadow.xml
rename to glance/glance-appwidget/src/main/res/color/glance_switch_off_ambient_shadow.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_switch_off_key_shadow.xml b/glance/glance-appwidget/src/main/res/color/glance_switch_off_key_shadow.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_switch_off_key_shadow.xml
rename to glance/glance-appwidget/src/main/res/color/glance_switch_off_key_shadow.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_switch_on_ambient_shadow.xml b/glance/glance-appwidget/src/main/res/color/glance_switch_on_ambient_shadow.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_switch_on_ambient_shadow.xml
rename to glance/glance-appwidget/src/main/res/color/glance_switch_on_ambient_shadow.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_switch_on_key_shadow.xml b/glance/glance-appwidget/src/main/res/color/glance_switch_on_key_shadow.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_switch_on_key_shadow.xml
rename to glance/glance-appwidget/src/main/res/color/glance_switch_on_key_shadow.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/color/glance_white_disabled_material_anim.xml b/glance/glance-appwidget/src/main/res/color/glance_white_disabled_material_anim.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/color/glance_white_disabled_material_anim.xml
rename to glance/glance-appwidget/src/main/res/color/glance_white_disabled_material_anim.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-v24/glance_switch_thumb_off.xml b/glance/glance-appwidget/src/main/res/drawable-v24/glance_switch_thumb_off.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable-v24/glance_switch_thumb_off.xml
rename to glance/glance-appwidget/src/main/res/drawable-v24/glance_switch_thumb_off.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-v24/glance_switch_thumb_on.xml b/glance/glance-appwidget/src/main/res/drawable-v24/glance_switch_thumb_on.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable-v24/glance_switch_thumb_on.xml
rename to glance/glance-appwidget/src/main/res/drawable-v24/glance_switch_thumb_on.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-v31/glance_error_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable-v31/glance_error_layout_background.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable-v31/glance_error_layout_background.xml
rename to glance/glance-appwidget/src/main/res/drawable-v31/glance_error_layout_background.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable-v31/glance_loading_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable-v31/glance_loading_layout_background.xml
rename to glance/glance-appwidget/src/main/res/drawable-v31/glance_loading_layout_background.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_abc_btn_check_material_anim_enabled.xml b/glance/glance-appwidget/src/main/res/drawable/glance_abc_btn_check_material_anim_enabled.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_abc_btn_check_material_anim_enabled.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_abc_btn_check_material_anim_enabled.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_checked_mtrl.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_checked_mtrl.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_checked_mtrl.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_checked_mtrl.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_checked_to_unchecked_mtrl_animation.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_checked_to_unchecked_mtrl_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_checked_to_unchecked_mtrl_animation.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_checked_to_unchecked_mtrl_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_unchecked_mtrl.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_unchecked_mtrl.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_unchecked_mtrl.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_unchecked_mtrl.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_unchecked_to_checked_mtrl_animation.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_unchecked_to_checked_mtrl_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_checkbox_unchecked_to_checked_mtrl_animation.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_checkbox_unchecked_to_checked_mtrl_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_material_anim.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_material_anim.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_material_anim.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_material_anim.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_off_mtrl.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_off_mtrl.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_off_mtrl.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_off_mtrl.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_off_to_on_mtrl_animation.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_off_to_on_mtrl_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_off_to_on_mtrl_animation.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_off_to_on_mtrl_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_on_mtrl.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_on_mtrl.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_on_mtrl.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_on_mtrl.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_on_to_off_mtrl_animation.xml b/glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_on_to_off_mtrl_animation.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_btn_radio_on_to_off_mtrl_animation.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_btn_radio_on_to_off_mtrl_animation.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_button_outline.xml b/glance/glance-appwidget/src/main/res/drawable/glance_button_outline.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_button_outline.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_button_outline.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_button_ripple.xml b/glance/glance-appwidget/src/main/res/drawable/glance_button_ripple.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_button_ripple.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_button_ripple.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_error_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable/glance_error_layout_background.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_error_layout_background.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_error_layout_background.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_loading_layout_background.xml b/glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_loading_layout_background.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_loading_layout_background.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_ripple.xml b/glance/glance-appwidget/src/main/res/drawable/glance_ripple.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_ripple.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_ripple.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_animated.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_animated.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_animated.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_animated.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_off.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_off.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_off.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_off.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_off_to_on.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_off_to_on.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_off_to_on.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_off_to_on.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_on.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_on.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_on.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_on.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_on_to_off.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_on_to_off.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_thumb_on_to_off.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_thumb_on_to_off.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_track.xml b/glance/glance-appwidget/src/main/res/drawable/glance_switch_track.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/drawable/glance_switch_track.xml
rename to glance/glance-appwidget/src/main/res/drawable/glance_switch_track.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_0.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_0.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_0.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_0.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_1.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_1.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_1.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_checked_mtrl_animation_interpolator_1.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_radio_to_off_mtrl_animation_interpolator_0.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_radio_to_off_mtrl_animation_interpolator_0.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_radio_to_off_mtrl_animation_interpolator_0.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_radio_to_off_mtrl_animation_interpolator_0.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_radio_to_on_mtrl_animation_interpolator_0.xml b/glance/glance-appwidget/src/main/res/interpolator/glance_btn_radio_to_on_mtrl_animation_interpolator_0.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/interpolator/glance_btn_radio_to_on_mtrl_animation_interpolator_0.xml
rename to glance/glance-appwidget/src/main/res/interpolator/glance_btn_radio_to_on_mtrl_animation_interpolator_0.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_button.xml b/glance/glance-appwidget/src/main/res/layout/glance_button.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_button.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_button.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_check_box.xml b/glance/glance-appwidget/src/main/res/layout/glance_check_box.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_check_box.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_check_box.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_backport.xml b/glance/glance-appwidget/src/main/res/layout/glance_check_box_backport.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_backport.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_check_box_backport.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_image.xml b/glance/glance-appwidget/src/main/res/layout/glance_check_box_image.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_image.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_check_box_image.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_text.xml b/glance/glance-appwidget/src/main/res/layout/glance_check_box_text.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_text.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_check_box_text.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_view.xml b/glance/glance-appwidget/src/main/res/layout/glance_check_box_view.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_check_box_view.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_check_box_view.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_circular_progress_indicator.xml b/glance/glance-appwidget/src/main/res/layout/glance_circular_progress_indicator.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_circular_progress_indicator.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_circular_progress_indicator.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_default_loading_layout.xml b/glance/glance-appwidget/src/main/res/layout/glance_default_loading_layout.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_default_loading_layout.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_default_loading_layout.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_deleted_view.xml b/glance/glance-appwidget/src/main/res/layout/glance_deleted_view.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_deleted_view.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_deleted_view.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_error_layout.xml b/glance/glance-appwidget/src/main/res/layout/glance_error_layout.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_error_layout.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_error_layout.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_frame.xml b/glance/glance-appwidget/src/main/res/layout/glance_frame.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_frame.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_frame.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_image_crop.xml b/glance/glance-appwidget/src/main/res/layout/glance_image_crop.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_image_crop.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_image_crop.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_image_fill_bounds.xml b/glance/glance-appwidget/src/main/res/layout/glance_image_fill_bounds.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_image_fill_bounds.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_image_fill_bounds.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_image_fit.xml b/glance/glance-appwidget/src/main/res/layout/glance_image_fit.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_image_fit.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_image_fit.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_linear_progress_indicator.xml b/glance/glance-appwidget/src/main/res/layout/glance_linear_progress_indicator.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_linear_progress_indicator.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_linear_progress_indicator.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_list.xml b/glance/glance-appwidget/src/main/res/layout/glance_list.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_list.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_list.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_radio_button.xml b/glance/glance-appwidget/src/main/res/layout/glance_radio_button.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_radio_button.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_radio_button.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_radio_button_backport.xml b/glance/glance-appwidget/src/main/res/layout/glance_radio_button_backport.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_radio_button_backport.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_radio_button_backport.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_radio_icon.xml b/glance/glance-appwidget/src/main/res/layout/glance_radio_icon.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_radio_icon.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_radio_icon.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_radio_text.xml b/glance/glance-appwidget/src/main/res/layout/glance_radio_text.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_radio_text.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_radio_text.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_switch_text.xml b/glance/glance-appwidget/src/main/res/layout/glance_switch_text.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_switch_text.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_switch_text.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_switch_thumb.xml b/glance/glance-appwidget/src/main/res/layout/glance_switch_thumb.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_switch_thumb.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_switch_thumb.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_switch_track.xml b/glance/glance-appwidget/src/main/res/layout/glance_switch_track.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_switch_track.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_switch_track.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_swtch.xml b/glance/glance-appwidget/src/main/res/layout/glance_swtch.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_swtch.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_swtch.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_swtch_backport.xml b/glance/glance-appwidget/src/main/res/layout/glance_swtch_backport.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_swtch_backport.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_swtch_backport.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_text.xml b/glance/glance-appwidget/src/main/res/layout/glance_text.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_text.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_text.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_auto_fit.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_auto_fit.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_auto_fit.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_auto_fit.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_five_columns.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_five_columns.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_five_columns.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_five_columns.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_four_columns.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_four_columns.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_four_columns.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_four_columns.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_one_column.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_one_column.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_one_column.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_one_column.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_three_columns.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_three_columns.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_three_columns.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_three_columns.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_two_columns.xml b/glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_two_columns.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/layout/glance_vertical_grid_two_columns.xml
rename to glance/glance-appwidget/src/main/res/layout/glance_vertical_grid_two_columns.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-af/strings.xml b/glance/glance-appwidget/src/main/res/values-af/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-af/strings.xml
rename to glance/glance-appwidget/src/main/res/values-af/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-am/strings.xml b/glance/glance-appwidget/src/main/res/values-am/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-am/strings.xml
rename to glance/glance-appwidget/src/main/res/values-am/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ar/strings.xml b/glance/glance-appwidget/src/main/res/values-ar/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ar/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ar/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-as/strings.xml b/glance/glance-appwidget/src/main/res/values-as/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-as/strings.xml
rename to glance/glance-appwidget/src/main/res/values-as/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-az/strings.xml b/glance/glance-appwidget/src/main/res/values-az/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-az/strings.xml
rename to glance/glance-appwidget/src/main/res/values-az/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-b+sr+Latn/strings.xml b/glance/glance-appwidget/src/main/res/values-b+sr+Latn/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-b+sr+Latn/strings.xml
rename to glance/glance-appwidget/src/main/res/values-b+sr+Latn/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-be/strings.xml b/glance/glance-appwidget/src/main/res/values-be/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-be/strings.xml
rename to glance/glance-appwidget/src/main/res/values-be/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-bg/strings.xml b/glance/glance-appwidget/src/main/res/values-bg/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-bg/strings.xml
rename to glance/glance-appwidget/src/main/res/values-bg/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-bn/strings.xml b/glance/glance-appwidget/src/main/res/values-bn/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-bn/strings.xml
rename to glance/glance-appwidget/src/main/res/values-bn/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-bs/strings.xml b/glance/glance-appwidget/src/main/res/values-bs/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-bs/strings.xml
rename to glance/glance-appwidget/src/main/res/values-bs/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ca/strings.xml b/glance/glance-appwidget/src/main/res/values-ca/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ca/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ca/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-cs/strings.xml b/glance/glance-appwidget/src/main/res/values-cs/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-cs/strings.xml
rename to glance/glance-appwidget/src/main/res/values-cs/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-da/strings.xml b/glance/glance-appwidget/src/main/res/values-da/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-da/strings.xml
rename to glance/glance-appwidget/src/main/res/values-da/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-de/strings.xml b/glance/glance-appwidget/src/main/res/values-de/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-de/strings.xml
rename to glance/glance-appwidget/src/main/res/values-de/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-el/strings.xml b/glance/glance-appwidget/src/main/res/values-el/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-el/strings.xml
rename to glance/glance-appwidget/src/main/res/values-el/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-en-rAU/strings.xml b/glance/glance-appwidget/src/main/res/values-en-rAU/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-en-rAU/strings.xml
rename to glance/glance-appwidget/src/main/res/values-en-rAU/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-en-rCA/strings.xml b/glance/glance-appwidget/src/main/res/values-en-rCA/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-en-rCA/strings.xml
rename to glance/glance-appwidget/src/main/res/values-en-rCA/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-en-rGB/strings.xml b/glance/glance-appwidget/src/main/res/values-en-rGB/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-en-rGB/strings.xml
rename to glance/glance-appwidget/src/main/res/values-en-rGB/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-en-rIN/strings.xml b/glance/glance-appwidget/src/main/res/values-en-rIN/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-en-rIN/strings.xml
rename to glance/glance-appwidget/src/main/res/values-en-rIN/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-en-rXC/strings.xml b/glance/glance-appwidget/src/main/res/values-en-rXC/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-en-rXC/strings.xml
rename to glance/glance-appwidget/src/main/res/values-en-rXC/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-es-rUS/strings.xml b/glance/glance-appwidget/src/main/res/values-es-rUS/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-es-rUS/strings.xml
rename to glance/glance-appwidget/src/main/res/values-es-rUS/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-es/strings.xml b/glance/glance-appwidget/src/main/res/values-es/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-es/strings.xml
rename to glance/glance-appwidget/src/main/res/values-es/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-et/strings.xml b/glance/glance-appwidget/src/main/res/values-et/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-et/strings.xml
rename to glance/glance-appwidget/src/main/res/values-et/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-eu/strings.xml b/glance/glance-appwidget/src/main/res/values-eu/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-eu/strings.xml
rename to glance/glance-appwidget/src/main/res/values-eu/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-fa/strings.xml b/glance/glance-appwidget/src/main/res/values-fa/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-fa/strings.xml
rename to glance/glance-appwidget/src/main/res/values-fa/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-fi/strings.xml b/glance/glance-appwidget/src/main/res/values-fi/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-fi/strings.xml
rename to glance/glance-appwidget/src/main/res/values-fi/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-fr-rCA/strings.xml b/glance/glance-appwidget/src/main/res/values-fr-rCA/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-fr-rCA/strings.xml
rename to glance/glance-appwidget/src/main/res/values-fr-rCA/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-fr/strings.xml b/glance/glance-appwidget/src/main/res/values-fr/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-fr/strings.xml
rename to glance/glance-appwidget/src/main/res/values-fr/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-gl/strings.xml b/glance/glance-appwidget/src/main/res/values-gl/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-gl/strings.xml
rename to glance/glance-appwidget/src/main/res/values-gl/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-gu/strings.xml b/glance/glance-appwidget/src/main/res/values-gu/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-gu/strings.xml
rename to glance/glance-appwidget/src/main/res/values-gu/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-hi/strings.xml b/glance/glance-appwidget/src/main/res/values-hi/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-hi/strings.xml
rename to glance/glance-appwidget/src/main/res/values-hi/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-hr/strings.xml b/glance/glance-appwidget/src/main/res/values-hr/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-hr/strings.xml
rename to glance/glance-appwidget/src/main/res/values-hr/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-hu/strings.xml b/glance/glance-appwidget/src/main/res/values-hu/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-hu/strings.xml
rename to glance/glance-appwidget/src/main/res/values-hu/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-hy/strings.xml b/glance/glance-appwidget/src/main/res/values-hy/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-hy/strings.xml
rename to glance/glance-appwidget/src/main/res/values-hy/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-in/strings.xml b/glance/glance-appwidget/src/main/res/values-in/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-in/strings.xml
rename to glance/glance-appwidget/src/main/res/values-in/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-is/strings.xml b/glance/glance-appwidget/src/main/res/values-is/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-is/strings.xml
rename to glance/glance-appwidget/src/main/res/values-is/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-it/strings.xml b/glance/glance-appwidget/src/main/res/values-it/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-it/strings.xml
rename to glance/glance-appwidget/src/main/res/values-it/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-iw/strings.xml b/glance/glance-appwidget/src/main/res/values-iw/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-iw/strings.xml
rename to glance/glance-appwidget/src/main/res/values-iw/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ja/strings.xml b/glance/glance-appwidget/src/main/res/values-ja/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ja/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ja/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ka/strings.xml b/glance/glance-appwidget/src/main/res/values-ka/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ka/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ka/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-kk/strings.xml b/glance/glance-appwidget/src/main/res/values-kk/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-kk/strings.xml
rename to glance/glance-appwidget/src/main/res/values-kk/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-km/strings.xml b/glance/glance-appwidget/src/main/res/values-km/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-km/strings.xml
rename to glance/glance-appwidget/src/main/res/values-km/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-kn/strings.xml b/glance/glance-appwidget/src/main/res/values-kn/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-kn/strings.xml
rename to glance/glance-appwidget/src/main/res/values-kn/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ko/strings.xml b/glance/glance-appwidget/src/main/res/values-ko/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ko/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ko/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ky/strings.xml b/glance/glance-appwidget/src/main/res/values-ky/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ky/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ky/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-lo/strings.xml b/glance/glance-appwidget/src/main/res/values-lo/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-lo/strings.xml
rename to glance/glance-appwidget/src/main/res/values-lo/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-lt/strings.xml b/glance/glance-appwidget/src/main/res/values-lt/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-lt/strings.xml
rename to glance/glance-appwidget/src/main/res/values-lt/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-lv/strings.xml b/glance/glance-appwidget/src/main/res/values-lv/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-lv/strings.xml
rename to glance/glance-appwidget/src/main/res/values-lv/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-mk/strings.xml b/glance/glance-appwidget/src/main/res/values-mk/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-mk/strings.xml
rename to glance/glance-appwidget/src/main/res/values-mk/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ml/strings.xml b/glance/glance-appwidget/src/main/res/values-ml/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ml/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ml/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-mn/strings.xml b/glance/glance-appwidget/src/main/res/values-mn/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-mn/strings.xml
rename to glance/glance-appwidget/src/main/res/values-mn/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-mr/strings.xml b/glance/glance-appwidget/src/main/res/values-mr/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-mr/strings.xml
rename to glance/glance-appwidget/src/main/res/values-mr/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ms/strings.xml b/glance/glance-appwidget/src/main/res/values-ms/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ms/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ms/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-my/strings.xml b/glance/glance-appwidget/src/main/res/values-my/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-my/strings.xml
rename to glance/glance-appwidget/src/main/res/values-my/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-nb/strings.xml b/glance/glance-appwidget/src/main/res/values-nb/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-nb/strings.xml
rename to glance/glance-appwidget/src/main/res/values-nb/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ne/strings.xml b/glance/glance-appwidget/src/main/res/values-ne/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ne/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ne/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-nl/strings.xml b/glance/glance-appwidget/src/main/res/values-nl/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-nl/strings.xml
rename to glance/glance-appwidget/src/main/res/values-nl/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-or/strings.xml b/glance/glance-appwidget/src/main/res/values-or/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-or/strings.xml
rename to glance/glance-appwidget/src/main/res/values-or/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-pa/strings.xml b/glance/glance-appwidget/src/main/res/values-pa/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-pa/strings.xml
rename to glance/glance-appwidget/src/main/res/values-pa/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-pl/strings.xml b/glance/glance-appwidget/src/main/res/values-pl/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-pl/strings.xml
rename to glance/glance-appwidget/src/main/res/values-pl/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-pt-rBR/strings.xml b/glance/glance-appwidget/src/main/res/values-pt-rBR/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-pt-rBR/strings.xml
rename to glance/glance-appwidget/src/main/res/values-pt-rBR/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-pt-rPT/strings.xml b/glance/glance-appwidget/src/main/res/values-pt-rPT/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-pt-rPT/strings.xml
rename to glance/glance-appwidget/src/main/res/values-pt-rPT/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-pt/strings.xml b/glance/glance-appwidget/src/main/res/values-pt/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-pt/strings.xml
rename to glance/glance-appwidget/src/main/res/values-pt/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ro/strings.xml b/glance/glance-appwidget/src/main/res/values-ro/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ro/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ro/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ru/strings.xml b/glance/glance-appwidget/src/main/res/values-ru/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ru/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ru/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-si/strings.xml b/glance/glance-appwidget/src/main/res/values-si/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-si/strings.xml
rename to glance/glance-appwidget/src/main/res/values-si/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sk/strings.xml b/glance/glance-appwidget/src/main/res/values-sk/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sk/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sk/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sl/strings.xml b/glance/glance-appwidget/src/main/res/values-sl/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sl/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sl/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sq/strings.xml b/glance/glance-appwidget/src/main/res/values-sq/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sq/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sq/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sr/strings.xml b/glance/glance-appwidget/src/main/res/values-sr/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sr/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sr/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sv/strings.xml b/glance/glance-appwidget/src/main/res/values-sv/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sv/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sv/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-sw/strings.xml b/glance/glance-appwidget/src/main/res/values-sw/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-sw/strings.xml
rename to glance/glance-appwidget/src/main/res/values-sw/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ta/strings.xml b/glance/glance-appwidget/src/main/res/values-ta/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ta/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ta/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-te/strings.xml b/glance/glance-appwidget/src/main/res/values-te/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-te/strings.xml
rename to glance/glance-appwidget/src/main/res/values-te/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-th/strings.xml b/glance/glance-appwidget/src/main/res/values-th/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-th/strings.xml
rename to glance/glance-appwidget/src/main/res/values-th/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-tl/strings.xml b/glance/glance-appwidget/src/main/res/values-tl/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-tl/strings.xml
rename to glance/glance-appwidget/src/main/res/values-tl/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-tr/strings.xml b/glance/glance-appwidget/src/main/res/values-tr/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-tr/strings.xml
rename to glance/glance-appwidget/src/main/res/values-tr/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-uk/strings.xml b/glance/glance-appwidget/src/main/res/values-uk/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-uk/strings.xml
rename to glance/glance-appwidget/src/main/res/values-uk/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-ur/strings.xml b/glance/glance-appwidget/src/main/res/values-ur/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-ur/strings.xml
rename to glance/glance-appwidget/src/main/res/values-ur/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-uz/strings.xml b/glance/glance-appwidget/src/main/res/values-uz/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-uz/strings.xml
rename to glance/glance-appwidget/src/main/res/values-uz/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-v23/bools.xml b/glance/glance-appwidget/src/main/res/values-v23/bools.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-v23/bools.xml
rename to glance/glance-appwidget/src/main/res/values-v23/bools.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-v29/textAppearance_styles.xml b/glance/glance-appwidget/src/main/res/values-v29/textAppearance_styles.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-v29/textAppearance_styles.xml
rename to glance/glance-appwidget/src/main/res/values-v29/textAppearance_styles.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-v31/styles.xml b/glance/glance-appwidget/src/main/res/values-v31/styles.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-v31/styles.xml
rename to glance/glance-appwidget/src/main/res/values-v31/styles.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-vi/strings.xml b/glance/glance-appwidget/src/main/res/values-vi/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-vi/strings.xml
rename to glance/glance-appwidget/src/main/res/values-vi/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-zh-rCN/strings.xml b/glance/glance-appwidget/src/main/res/values-zh-rCN/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-zh-rCN/strings.xml
rename to glance/glance-appwidget/src/main/res/values-zh-rCN/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-zh-rHK/strings.xml b/glance/glance-appwidget/src/main/res/values-zh-rHK/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-zh-rHK/strings.xml
rename to glance/glance-appwidget/src/main/res/values-zh-rHK/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-zh-rTW/strings.xml b/glance/glance-appwidget/src/main/res/values-zh-rTW/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-zh-rTW/strings.xml
rename to glance/glance-appwidget/src/main/res/values-zh-rTW/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values-zu/strings.xml b/glance/glance-appwidget/src/main/res/values-zu/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values-zu/strings.xml
rename to glance/glance-appwidget/src/main/res/values-zu/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/attrs.xml b/glance/glance-appwidget/src/main/res/values/attrs.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/attrs.xml
rename to glance/glance-appwidget/src/main/res/values/attrs.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/bools.xml b/glance/glance-appwidget/src/main/res/values/bools.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/bools.xml
rename to glance/glance-appwidget/src/main/res/values/bools.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/colors.xml b/glance/glance-appwidget/src/main/res/values/colors.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/colors.xml
rename to glance/glance-appwidget/src/main/res/values/colors.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/ids.xml b/glance/glance-appwidget/src/main/res/values/ids.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/ids.xml
rename to glance/glance-appwidget/src/main/res/values/ids.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/public.xml b/glance/glance-appwidget/src/main/res/values/public.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/public.xml
rename to glance/glance-appwidget/src/main/res/values/public.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/strings.xml b/glance/glance-appwidget/src/main/res/values/strings.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/strings.xml
rename to glance/glance-appwidget/src/main/res/values/strings.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/styles.xml b/glance/glance-appwidget/src/main/res/values/styles.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/styles.xml
rename to glance/glance-appwidget/src/main/res/values/styles.xml
diff --git a/glance/glance-appwidget/src/androidMain/res/values/textAppearance_styles.xml b/glance/glance-appwidget/src/main/res/values/textAppearance_styles.xml
similarity index 100%
rename from glance/glance-appwidget/src/androidMain/res/values/textAppearance_styles.xml
rename to glance/glance-appwidget/src/main/res/values/textAppearance_styles.xml
diff --git a/glance/glance-material/build.gradle b/glance/glance-material/build.gradle
index 17a787b..9c75b74 100644
--- a/glance/glance-material/build.gradle
+++ b/glance/glance-material/build.gradle
@@ -1,15 +1,12 @@
-import androidx.build.AndroidXComposePlugin
 import androidx.build.LibraryType
 
 plugins {
     id("AndroidXComposePlugin")
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
     implementation(libs.kotlinStdlib)
     api("androidx.annotation:annotation:1.4.0")
diff --git a/glance/glance-material/src/androidMain/kotlin/androidx/glance/material/MaterialThemes.kt b/glance/glance-material/src/main/java/androidx/glance/material/MaterialThemes.kt
similarity index 100%
rename from glance/glance-material/src/androidMain/kotlin/androidx/glance/material/MaterialThemes.kt
rename to glance/glance-material/src/main/java/androidx/glance/material/MaterialThemes.kt
diff --git a/glance/glance-material3/build.gradle b/glance/glance-material3/build.gradle
index 9439749..fbd965c 100644
--- a/glance/glance-material3/build.gradle
+++ b/glance/glance-material3/build.gradle
@@ -1,15 +1,12 @@
-import androidx.build.AndroidXComposePlugin
 import androidx.build.LibraryType
 
 plugins {
     id("AndroidXComposePlugin")
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
     implementation(libs.kotlinStdlib)
     api("androidx.annotation:annotation:1.4.0")
diff --git a/glance/glance-material3/src/androidMain/kotlin/androidx/glance/material3/Material3Themes.kt b/glance/glance-material3/src/main/java/androidx/glance/material3/Material3Themes.kt
similarity index 100%
rename from glance/glance-material3/src/androidMain/kotlin/androidx/glance/material3/Material3Themes.kt
rename to glance/glance-material3/src/main/java/androidx/glance/material3/Material3Themes.kt
diff --git a/glance/glance-preview/build.gradle b/glance/glance-preview/build.gradle
index 0857b2ee..f6be751 100644
--- a/glance/glance-preview/build.gradle
+++ b/glance/glance-preview/build.gradle
@@ -1,15 +1,12 @@
-import androidx.build.AndroidXComposePlugin
 import androidx.build.LibraryType
 
 plugins {
     id("AndroidXComposePlugin")
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
     implementation(libs.kotlinStdlib)
     api("androidx.annotation:annotation:1.4.0")
diff --git a/glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/ExperimentalGlancePreviewApi.kt b/glance/glance-preview/src/main/java/androidx/glance/preview/ExperimentalGlancePreviewApi.kt
similarity index 100%
rename from glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/ExperimentalGlancePreviewApi.kt
rename to glance/glance-preview/src/main/java/androidx/glance/preview/ExperimentalGlancePreviewApi.kt
diff --git a/glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/GlancePreview.kt b/glance/glance-preview/src/main/java/androidx/glance/preview/GlancePreview.kt
similarity index 100%
rename from glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/GlancePreview.kt
rename to glance/glance-preview/src/main/java/androidx/glance/preview/GlancePreview.kt
diff --git a/glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/Surface.kt b/glance/glance-preview/src/main/java/androidx/glance/preview/Surface.kt
similarity index 100%
rename from glance/glance-preview/src/androidMain/kotlin/androidx/glance/preview/Surface.kt
rename to glance/glance-preview/src/main/java/androidx/glance/preview/Surface.kt
diff --git a/glance/glance-template/build.gradle b/glance/glance-template/build.gradle
index 331d3e2..6ea5c4c 100644
--- a/glance/glance-template/build.gradle
+++ b/glance/glance-template/build.gradle
@@ -21,12 +21,10 @@
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("org.jetbrains.kotlin.android")
     id("AndroidXComposePlugin")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
     api(project(":glance:glance"))
     api(project(":glance:glance-appwidget"))
diff --git a/glance/glance-wear-tiles-preview/build.gradle b/glance/glance-wear-tiles-preview/build.gradle
index 9314528..d05e676 100644
--- a/glance/glance-wear-tiles-preview/build.gradle
+++ b/glance/glance-wear-tiles-preview/build.gradle
@@ -14,18 +14,15 @@
  * limitations under the License.
  */
 
-import androidx.build.AndroidXComposePlugin
 import androidx.build.LibraryType
 
 plugins {
     id("AndroidXComposePlugin")
     id("AndroidXPlugin")
+    id("org.jetbrains.kotlin.android")
     id("com.android.library")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
     api("androidx.wear.tiles:tiles-renderer:1.0.0")
 
diff --git a/glance/glance-wear-tiles-preview/src/androidAndroidTest/AndroidManifest.xml b/glance/glance-wear-tiles-preview/src/androidTest/AndroidManifest.xml
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidAndroidTest/AndroidManifest.xml
rename to glance/glance-wear-tiles-preview/src/androidTest/AndroidManifest.xml
diff --git a/glance/glance-wear-tiles-preview/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/preview/FirstGlancePreview.kt b/glance/glance-wear-tiles-preview/src/androidTest/kotlin/androidx/glance/wear/tiles/preview/FirstGlancePreview.kt
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/preview/FirstGlancePreview.kt
rename to glance/glance-wear-tiles-preview/src/androidTest/kotlin/androidx/glance/wear/tiles/preview/FirstGlancePreview.kt
diff --git a/glance/glance-wear-tiles-preview/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapterTest.kt b/glance/glance-wear-tiles-preview/src/androidTest/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapterTest.kt
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapterTest.kt
rename to glance/glance-wear-tiles-preview/src/androidTest/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapterTest.kt
diff --git a/glance/glance-wear-tiles-preview/src/androidAndroidTest/res/layout/glance_tile_service_adapter_test.xml b/glance/glance-wear-tiles-preview/src/androidTest/res/layout/glance_tile_service_adapter_test.xml
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidAndroidTest/res/layout/glance_tile_service_adapter_test.xml
rename to glance/glance-wear-tiles-preview/src/androidTest/res/layout/glance_tile_service_adapter_test.xml
diff --git a/glance/glance-wear-tiles-preview/src/androidAndroidTest/res/values/styles.xml b/glance/glance-wear-tiles-preview/src/androidTest/res/values/styles.xml
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidAndroidTest/res/values/styles.xml
rename to glance/glance-wear-tiles-preview/src/androidTest/res/values/styles.xml
diff --git a/glance/glance-wear-tiles-preview/src/androidMain/kotlin/androidx/glance/wear/tiles/preview/ComposableInvoker.kt b/glance/glance-wear-tiles-preview/src/main/java/androidx/glance/wear/tiles/preview/ComposableInvoker.kt
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidMain/kotlin/androidx/glance/wear/tiles/preview/ComposableInvoker.kt
rename to glance/glance-wear-tiles-preview/src/main/java/androidx/glance/wear/tiles/preview/ComposableInvoker.kt
diff --git a/glance/glance-wear-tiles-preview/src/androidMain/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapter.kt b/glance/glance-wear-tiles-preview/src/main/java/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapter.kt
similarity index 100%
rename from glance/glance-wear-tiles-preview/src/androidMain/kotlin/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapter.kt
rename to glance/glance-wear-tiles-preview/src/main/java/androidx/glance/wear/tiles/preview/GlanceTileServiceViewAdapter.kt
diff --git a/glance/glance-wear-tiles/build.gradle b/glance/glance-wear-tiles/build.gradle
index 155bfab..e158ee6 100644
--- a/glance/glance-wear-tiles/build.gradle
+++ b/glance/glance-wear-tiles/build.gradle
@@ -15,18 +15,14 @@
  */
 
 import androidx.build.LibraryType
-import androidx.build.Publish
-import androidx.build.AndroidXComposePlugin
 
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("org.jetbrains.kotlin.android")
     id("AndroidXComposePlugin")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
 
     api(project(":glance:glance"))
diff --git a/glance/glance-wear-tiles/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/ScreenshotTests.kt b/glance/glance-wear-tiles/src/androidTest/kotlin/androidx/glance/wear/tiles/ScreenshotTests.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidAndroidTest/kotlin/androidx/glance/wear/tiles/ScreenshotTests.kt
rename to glance/glance-wear-tiles/src/androidTest/kotlin/androidx/glance/wear/tiles/ScreenshotTests.kt
diff --git a/glance/glance-wear-tiles/src/androidAndroidTest/res/drawable/oval.xml b/glance/glance-wear-tiles/src/androidTest/res/drawable/oval.xml
similarity index 100%
rename from glance/glance-wear-tiles/src/androidAndroidTest/res/drawable/oval.xml
rename to glance/glance-wear-tiles/src/androidTest/res/drawable/oval.xml
diff --git a/glance/glance-wear-tiles/src/androidAndroidTest/res/values/dimens.xml b/glance/glance-wear-tiles/src/androidTest/res/values/dimens.xml
similarity index 100%
rename from glance/glance-wear-tiles/src/androidAndroidTest/res/values/dimens.xml
rename to glance/glance-wear-tiles/src/androidTest/res/values/dimens.xml
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/AndroidLayoutElement.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/AndroidLayoutElement.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/AndroidLayoutElement.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/AndroidLayoutElement.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/Border.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/Border.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/Border.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/Border.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/CompositionLocals.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/CompositionLocals.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/CompositionLocals.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/CompositionLocals.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/ErrorUiLayout.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/ErrorUiLayout.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/ErrorUiLayout.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/ErrorUiLayout.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/ExperimentalGlanceWearTilesApi.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/ExperimentalGlanceWearTilesApi.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/ExperimentalGlanceWearTilesApi.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/ExperimentalGlanceWearTilesApi.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/GlanceTileService.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/GlanceTileService.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/GlanceTileService.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/GlanceTileService.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/GlanceWearTiles.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/GlanceWearTiles.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/GlanceWearTiles.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/GlanceWearTiles.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/NormalizeCompositionTree.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/NormalizeCompositionTree.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/NormalizeCompositionTree.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/NormalizeCompositionTree.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/TimelineMode.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/TimelineMode.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/TimelineMode.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/TimelineMode.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/WearCompositionTranslator.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/WearCompositionTranslator.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/WearCompositionTranslator.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/action/RunCallbackAction.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/action/RunCallbackAction.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/action/RunCallbackAction.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/action/RunCallbackAction.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/CurvedProperties.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/CurvedProperties.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/CurvedProperties.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/CurvedProperties.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/CurvedRow.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/CurvedRow.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/CurvedRow.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/CurvedRow.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/GlanceCurvedModifier.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/GlanceCurvedModifier.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/curved/GlanceCurvedModifier.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/curved/GlanceCurvedModifier.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/state/GlanceWearTilesState.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/state/GlanceWearTilesState.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/state/GlanceWearTilesState.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/state/GlanceWearTilesState.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/template/SingleEntityTemplateLayouts.kt b/glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/template/SingleEntityTemplateLayouts.kt
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/kotlin/androidx/glance/wear/tiles/template/SingleEntityTemplateLayouts.kt
rename to glance/glance-wear-tiles/src/main/java/androidx/glance/wear/tiles/template/SingleEntityTemplateLayouts.kt
diff --git a/glance/glance-wear-tiles/src/androidMain/res/drawable/glance_single_entity_bg.xml b/glance/glance-wear-tiles/src/main/res/drawable/glance_single_entity_bg.xml
similarity index 100%
rename from glance/glance-wear-tiles/src/androidMain/res/drawable/glance_single_entity_bg.xml
rename to glance/glance-wear-tiles/src/main/res/drawable/glance_single_entity_bg.xml
diff --git a/glance/glance/build.gradle b/glance/glance/build.gradle
index 1d44a68..0a8e136 100644
--- a/glance/glance/build.gradle
+++ b/glance/glance/build.gradle
@@ -15,18 +15,14 @@
  */
 
 import androidx.build.LibraryType
-import androidx.build.Publish
-import androidx.build.AndroidXComposePlugin
 
 plugins {
     id("AndroidXPlugin")
     id("com.android.library")
+    id("org.jetbrains.kotlin.android")
     id("AndroidXComposePlugin")
 }
 
-// Disable multi-platform; this will only be used on Android.
-AndroidXComposePlugin.applyAndConfigureKotlinPlugin(project, /* isMultiplatformEnabled= */false)
-
 dependencies {
 
     api("androidx.annotation:annotation:1.2.0")
diff --git a/glance/glance/src/androidAndroidTest/AndroidManifest.xml b/glance/glance/src/androidTest/AndroidManifest.xml
similarity index 100%
rename from glance/glance/src/androidAndroidTest/AndroidManifest.xml
rename to glance/glance/src/androidTest/AndroidManifest.xml
diff --git a/glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt b/glance/glance/src/androidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
similarity index 100%
rename from glance/glance/src/androidAndroidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
rename to glance/glance/src/androidTest/kotlin/androidx/glance/session/GlanceSessionManagerTest.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Applier.kt b/glance/glance/src/main/java/androidx/glance/Applier.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Applier.kt
rename to glance/glance/src/main/java/androidx/glance/Applier.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Background.kt b/glance/glance/src/main/java/androidx/glance/Background.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Background.kt
rename to glance/glance/src/main/java/androidx/glance/Background.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Button.kt b/glance/glance/src/main/java/androidx/glance/Button.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Button.kt
rename to glance/glance/src/main/java/androidx/glance/Button.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/CompositionLocals.kt b/glance/glance/src/main/java/androidx/glance/CompositionLocals.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/CompositionLocals.kt
rename to glance/glance/src/main/java/androidx/glance/CompositionLocals.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Emittables.kt b/glance/glance/src/main/java/androidx/glance/Emittables.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Emittables.kt
rename to glance/glance/src/main/java/androidx/glance/Emittables.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/GlanceComposable.kt b/glance/glance/src/main/java/androidx/glance/GlanceComposable.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/GlanceComposable.kt
rename to glance/glance/src/main/java/androidx/glance/GlanceComposable.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/GlanceId.kt b/glance/glance/src/main/java/androidx/glance/GlanceId.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/GlanceId.kt
rename to glance/glance/src/main/java/androidx/glance/GlanceId.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/GlanceModifier.kt b/glance/glance/src/main/java/androidx/glance/GlanceModifier.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/GlanceModifier.kt
rename to glance/glance/src/main/java/androidx/glance/GlanceModifier.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/GlanceNode.kt b/glance/glance/src/main/java/androidx/glance/GlanceNode.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/GlanceNode.kt
rename to glance/glance/src/main/java/androidx/glance/GlanceNode.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/GlanceTheme.kt b/glance/glance/src/main/java/androidx/glance/GlanceTheme.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/GlanceTheme.kt
rename to glance/glance/src/main/java/androidx/glance/GlanceTheme.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Image.kt b/glance/glance/src/main/java/androidx/glance/Image.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Image.kt
rename to glance/glance/src/main/java/androidx/glance/Image.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Utils.kt b/glance/glance/src/main/java/androidx/glance/Utils.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Utils.kt
rename to glance/glance/src/main/java/androidx/glance/Utils.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/Visibility.kt b/glance/glance/src/main/java/androidx/glance/Visibility.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/Visibility.kt
rename to glance/glance/src/main/java/androidx/glance/Visibility.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/Action.kt b/glance/glance/src/main/java/androidx/glance/action/Action.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/action/Action.kt
rename to glance/glance/src/main/java/androidx/glance/action/Action.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt b/glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/action/ActionParameters.kt
rename to glance/glance/src/main/java/androidx/glance/action/ActionParameters.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/LambdaAction.kt b/glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/action/LambdaAction.kt
rename to glance/glance/src/main/java/androidx/glance/action/LambdaAction.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/action/StartActivityAction.kt b/glance/glance/src/main/java/androidx/glance/action/StartActivityAction.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/action/StartActivityAction.kt
rename to glance/glance/src/main/java/androidx/glance/action/StartActivityAction.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/color/ColorProviders.kt b/glance/glance/src/main/java/androidx/glance/color/ColorProviders.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/color/ColorProviders.kt
rename to glance/glance/src/main/java/androidx/glance/color/ColorProviders.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/color/DayNightColorProviders.kt b/glance/glance/src/main/java/androidx/glance/color/DayNightColorProviders.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/color/DayNightColorProviders.kt
rename to glance/glance/src/main/java/androidx/glance/color/DayNightColorProviders.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Alignment.kt b/glance/glance/src/main/java/androidx/glance/layout/Alignment.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Alignment.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Alignment.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Box.kt b/glance/glance/src/main/java/androidx/glance/layout/Box.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Box.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Box.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Column.kt b/glance/glance/src/main/java/androidx/glance/layout/Column.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Column.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Column.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/ContentScale.kt b/glance/glance/src/main/java/androidx/glance/layout/ContentScale.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/ContentScale.kt
rename to glance/glance/src/main/java/androidx/glance/layout/ContentScale.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Padding.kt b/glance/glance/src/main/java/androidx/glance/layout/Padding.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Padding.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Padding.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Row.kt b/glance/glance/src/main/java/androidx/glance/layout/Row.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Row.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Row.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/SizeModifiers.kt b/glance/glance/src/main/java/androidx/glance/layout/SizeModifiers.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/SizeModifiers.kt
rename to glance/glance/src/main/java/androidx/glance/layout/SizeModifiers.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/layout/Spacer.kt b/glance/glance/src/main/java/androidx/glance/layout/Spacer.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/layout/Spacer.kt
rename to glance/glance/src/main/java/androidx/glance/layout/Spacer.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/semantics/SemanticsModifier.kt b/glance/glance/src/main/java/androidx/glance/semantics/SemanticsModifier.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/semantics/SemanticsModifier.kt
rename to glance/glance/src/main/java/androidx/glance/semantics/SemanticsModifier.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/semantics/SemanticsProperties.kt b/glance/glance/src/main/java/androidx/glance/semantics/SemanticsProperties.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/semantics/SemanticsProperties.kt
rename to glance/glance/src/main/java/androidx/glance/semantics/SemanticsProperties.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt b/glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/GlobalSnapshotManager.kt
rename to glance/glance/src/main/java/androidx/glance/session/GlobalSnapshotManager.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/IdleEventBroadcastReceiver.kt b/glance/glance/src/main/java/androidx/glance/session/IdleEventBroadcastReceiver.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/IdleEventBroadcastReceiver.kt
rename to glance/glance/src/main/java/androidx/glance/session/IdleEventBroadcastReceiver.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/InteractiveFrameClock.kt b/glance/glance/src/main/java/androidx/glance/session/InteractiveFrameClock.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/InteractiveFrameClock.kt
rename to glance/glance/src/main/java/androidx/glance/session/InteractiveFrameClock.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/Session.kt b/glance/glance/src/main/java/androidx/glance/session/Session.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/Session.kt
rename to glance/glance/src/main/java/androidx/glance/session/Session.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionManager.kt b/glance/glance/src/main/java/androidx/glance/session/SessionManager.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionManager.kt
rename to glance/glance/src/main/java/androidx/glance/session/SessionManager.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt b/glance/glance/src/main/java/androidx/glance/session/SessionWorker.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/SessionWorker.kt
rename to glance/glance/src/main/java/androidx/glance/session/SessionWorker.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/session/TimerScope.kt b/glance/glance/src/main/java/androidx/glance/session/TimerScope.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/session/TimerScope.kt
rename to glance/glance/src/main/java/androidx/glance/session/TimerScope.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt b/glance/glance/src/main/java/androidx/glance/state/GlanceStateDefinition.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/state/GlanceStateDefinition.kt
rename to glance/glance/src/main/java/androidx/glance/state/GlanceStateDefinition.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/FontFamily.kt b/glance/glance/src/main/java/androidx/glance/text/FontFamily.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/FontFamily.kt
rename to glance/glance/src/main/java/androidx/glance/text/FontFamily.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/FontStyle.kt b/glance/glance/src/main/java/androidx/glance/text/FontStyle.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/FontStyle.kt
rename to glance/glance/src/main/java/androidx/glance/text/FontStyle.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/FontWeight.kt b/glance/glance/src/main/java/androidx/glance/text/FontWeight.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/FontWeight.kt
rename to glance/glance/src/main/java/androidx/glance/text/FontWeight.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/Text.kt b/glance/glance/src/main/java/androidx/glance/text/Text.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/Text.kt
rename to glance/glance/src/main/java/androidx/glance/text/Text.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/TextAlign.kt b/glance/glance/src/main/java/androidx/glance/text/TextAlign.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/TextAlign.kt
rename to glance/glance/src/main/java/androidx/glance/text/TextAlign.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/TextDecoration.kt b/glance/glance/src/main/java/androidx/glance/text/TextDecoration.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/TextDecoration.kt
rename to glance/glance/src/main/java/androidx/glance/text/TextDecoration.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/text/TextStyle.kt b/glance/glance/src/main/java/androidx/glance/text/TextStyle.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/text/TextStyle.kt
rename to glance/glance/src/main/java/androidx/glance/text/TextStyle.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/unit/ColorProvider.kt b/glance/glance/src/main/java/androidx/glance/unit/ColorProvider.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/unit/ColorProvider.kt
rename to glance/glance/src/main/java/androidx/glance/unit/ColorProvider.kt
diff --git a/glance/glance/src/androidMain/kotlin/androidx/glance/unit/Dimension.kt b/glance/glance/src/main/java/androidx/glance/unit/Dimension.kt
similarity index 100%
rename from glance/glance/src/androidMain/kotlin/androidx/glance/unit/Dimension.kt
rename to glance/glance/src/main/java/androidx/glance/unit/Dimension.kt
diff --git a/glance/glance/src/androidMain/res/values-night-v31/colors.xml b/glance/glance/src/main/res/values-night-v31/colors.xml
similarity index 100%
rename from glance/glance/src/androidMain/res/values-night-v31/colors.xml
rename to glance/glance/src/main/res/values-night-v31/colors.xml
diff --git a/glance/glance/src/androidMain/res/values-night/colors.xml b/glance/glance/src/main/res/values-night/colors.xml
similarity index 100%
rename from glance/glance/src/androidMain/res/values-night/colors.xml
rename to glance/glance/src/main/res/values-night/colors.xml
diff --git a/glance/glance/src/androidMain/res/values-v31/colors.xml b/glance/glance/src/main/res/values-v31/colors.xml
similarity index 100%
rename from glance/glance/src/androidMain/res/values-v31/colors.xml
rename to glance/glance/src/main/res/values-v31/colors.xml
diff --git a/glance/glance/src/androidMain/res/values/colors.xml b/glance/glance/src/main/res/values/colors.xml
similarity index 100%
rename from glance/glance/src/androidMain/res/values/colors.xml
rename to glance/glance/src/main/res/values/colors.xml
diff --git a/gradle/verification-keyring.keys b/gradle/verification-keyring.keys
index a595aaf..9d82f9b 100644
--- a/gradle/verification-keyring.keys
+++ b/gradle/verification-keyring.keys
@@ -3838,6 +3838,64 @@
 =hALf
 -----END PGP PUBLIC KEY BLOCK-----
 
+pub    3D12CA2AC19F3181
+uid    Tatu Saloranta (cowtowncoder) <tatu.saloranta@iki.fi>
+
+sub    575D6C921D84AC76
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGL4BxIBEAC+lX44fd/zrVQPzdKygarBd/X0bBpGakT++Kfk4UBGl3q+wd2G
+R9puB9R377ds8hU7U3To8sHguUZo6DbD9Gb/is/WajSb9g92z+rMow3KbqfCYqWr
+kaIj27OJgbziFcnMAtvGoFRfaPI/7TOwEw3jT7B87RXeiATX4iL8fzMUmkfZm0Hk
+qjnepMQeaz3KzMY4DfBcI45kwzl3EIBFIlk428mhBU5iAAANoyPsimfqEPRCUDjx
+vT8g7PvpkBdNZgRS6R9vLxyzKi/f5KswZIMvop/pRXIhAKDhCCyr2GD+T3JoIKp9
+kvS1MQucWeX8+TFWh5qEA3e06Xu0JSdPCEej0BH06EiTMsAOU5bWqgLAO9DVpS32
+I092KAuMJlEPCnz7IGXVkeNY5KYrlsmoKrBO3GF/zsCyiZDvSULkVJcrtBCYOrgq
+HRIzvJWQaTJ5V15MD8CZIELyjCGZ8Jy8hdZpaTjYalw0bUq+yRAqMD5slp6A1tnv
+jyqVTgU+yRGq2HB90vJ0D3P1w4xRDuNF8c02futO415Yc/qkyh3/5AjGSoocrlfX
+cMreJXpQWVsvXn3NsitjsA6XOJpMOgipCDxfvn8SSLl9fWNJf55j7fCkBokF/lIi
+81RVQbyjVCOV0OEqHJLP9asPHyAFvUppNWtcvViPxVmb52djnw/x/61WVQARAQAB
+tDVUYXR1IFNhbG9yYW50YSAoY293dG93bmNvZGVyKSA8dGF0dS5zYWxvcmFudGFA
+aWtpLmZpPokCVAQTAQgAPhYhBCgRjAcMsioBdaLo1D0SyirBnzGBBQJi+AcSAhsD
+BQkJZgGABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJED0SyirBnzGBnxsQALTJ
+d/chCW8zWgR6x9ZDfU2f5fgMhi8jjILCieiQdQ/vec3QqCVLpJmE+l6MrI75E7GY
+eL8Iu0DXO26nHHSEbDa9kGk+ohdODbOd+y6KE5t6qPFaHSG5Gj1iiQ7libmrO7EZ
+qPQzl4fwmzUvl/2x+kaL5WsC4SxbwTG2mGo8WRCz+hqM40yeBeKYxpTlN2VBrlU2
+xkJ1I0rQITtHwck1dClgf4up13uBna7TlCBJc7vio3OwAFbXTPHEL+efrn8zk0au
+J+cwocHmm4d9shGiwiSUAOEnQ8FZ08IwO5MoOUWKz/ARYLuR6FAd8HqFERbfUxU2
+AlcyLSAhSi0c+j2Gi9PFkNTABEDHpdTosaAgKpbYdGke/2sfA0BKmcNRIfGjs+W0
+GnX2c7tP6qc7iFCCP0TjXvR8jnCmH8BT1JiSN5C/JPH0hDE1Zvmvgs0hid48e6Zv
+k1yXvEdtd/rH0uM3yUs28EfdcqokhwKZi5duUeizgG1gGNCW8RGvhi5ks1bABK9i
+52JMZznINMb35mZ0bEK7YLi3K8DE2hfIU6yg8WnlXlx3eOK4e6jWxWbjuEmUJ7BE
+ZWvz5IJ9nFI1UAIq7Ug7ruM+CH8ntpHueuGp6goq39+0lTd/1Sc29kVadg/DXQtC
+mDDrw4Btpz8hXthmTnNVvP/GUu5K1fttW3gNU/ofuQINBGL4BxIBEACwpcarOeEN
+5TztQDTvemc+DXZuWirmHv1TyJmjOhU0hGGMzEnKKU6VZlUIg5YQNYknUOfOf/05
+pgQmsEhjjI8NBD3Cys6SVQ6wOlkA+KpDKs/dXwyJttYE+EG/IMzjwZW2DbF50Hkm
+T2VK/oFhRSf0Par+cbVQ/mNLAVC7ueZWBVXldezqVvk3tDYYZef9T8Qlf999LVXF
+giMzRFrzLLcd2KEHAX4se65FTxIfFYYCrshFIKDRi4IWNzQqtPV7mb94wXY0Vwse
+5mMEgjmieGPjBGYne2JU0xYNBxtly1y3aeDXcxNlNrcS/Ake9AqWAYU4agtocCef
+b1pt5Q3li0qg3PsVKDJ5qWDceb+kgcUuHgtwHFCVICoQUMsv9p5F/kWL38/OWcTR
+2lQ4tGerE2dmlyqFWu7mpELckAfXSpJobZltUbp8CO679g0lk+OJWSmxddlVybdX
+CFaAeOKQb0woQOkR1vo2tJHyGmGr20Eea+UX+kdLojVQwYCqICdvnK4YpHuhpT5c
+rzk6lohfZpBPMHdpR7FQQZeQEW5EbcFNfoUEwsgb2qkG+hQIL5Q7wRajHkGaG3Wu
+hY2xEyoHuLSb20hP5hI2uhtxswUl/+IOjjZtDCjzLz59Q+ADkDZYM+PN3eR0UJDq
+YKly49KTuz23zLluNjNwqo8K0y05XGCQMwARAQABiQI8BBgBCAAmFiEEKBGMBwyy
+KgF1oujUPRLKKsGfMYEFAmL4BxICGwwFCQlmAYAACgkQPRLKKsGfMYGQbQ//bxZq
+IUIrPa86oXELq19E+OFTvCKVQzgohiaKPS6Hx2rgtvPS2bJvO+rXlAvRAFyI8sX7
+Dq0deeZP0pXefidjpfjKz1bhW8Wf7RU6QOKc0Eyl8/YqCVZign1DzJlF1r2mrkZa
+0VRNLjh86P/Y1T7ZhrAiR0PNv++LEgNsPbL8Tu1ryWl8vWFdlos40W8xleP1nBU1
+9OWheOPU9VYN80eBD5ij2Cn0LCxJQdyNOpVD03P3Ycauk9OHOVCd+UVX2A7VwemX
+b4wRDL59gAfSGyYLHYqAF1XJbOXkheTPRsttxXRIkzvA/gjpmQmioNU3UhiMZ1EJ
+kbJ42loFPv7YplbmBXoMAKJF1402+sOVusC1FULMQQtpZvC/bgobqEqdTzhZa/Hr
+KA45BFpcaTO80jJto8kiZR7infwX1gBGrYgwXisxiiYPI5yVwAvYTcNnU1nD9Vk5
+iyTgx0BNBG1hLPaZBtkYarDmUo0KyYf0Y8mQZmd7U0nOHptdkR+5yND5yO29/wGf
+se1KeZcRNGgcYQFKGw72HDiYsOELiiwsFqyUMWPLEwQJave/tO4SYSY1wP4rA3IA
+IU24GMQFZ64lljAKQCRXLwDKK2tMyHz8I+GT+0+bbpz4ojkEmxCDxXfgUy1362tG
+FdEbaZ88HZxTa30iXtOXOLvWIYRp8hv3pSb8id8=
+=hALf
+-----END PGP PUBLIC KEY BLOCK-----
+
 pub    CC6346F2CE3872D9
 uid    Jisi Liu <liujisi@google.com>
 
@@ -12161,6 +12219,41 @@
 =S4Fa
 -----END PGP PUBLIC KEY BLOCK-----
 
+pub    26E74B6874AEE127
+uid    Sam Judd <sam.a.judd@gmail.com>
+
+sub    B4E75C15C3C701AE
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQENBFPsGJIBCADOxQoTLxpZVRIbLaRfsHa2y/TEIGvxLP7TgqTwspZYnwBd0cOW
+OHAvF8yGfdk5gvkGTlQ/xchwu2Ix05FO2c+fBoOgIG1Gn2Q+PwheZklS7S+V+GFk
+t5S3m6b54Pl2lKbcasaM99r5g2+MhxwVnG66ldLS9fdPWqWrviOC+EipHfGyuhj0
+R0E2Oh+dNHrsZR0vtoJawA8xDP5D1Ii3jEVdi71PF8OlavG7saAZXtOW1kU77oPa
+SmGFTmcFLjDP1alo95TTfBihaYiwFFnW7NQEi5Bw1u3G0+Vaoo5eJBQwYsNxLs3h
+I1d7wsqFW5LK6LSxEjfvEhJypi0XzrFkFzMvABEBAAG0H1NhbSBKdWRkIDxzYW0u
+YS5qdWRkQGdtYWlsLmNvbT6JATgEEwECACIFAlPsGJICGwMGCwkIBwMCBhUIAgkK
+CwQWAgMBAh4BAheAAAoJECbnS2h0ruEn9DUIAItn8TzZh44JQ0aRO3dgmh4kUnnJ
+cJyw+0m5m4gGyjZ3vFzbCXgzCHAz2jN3bh6crnUoheIUCn206NRz+aG0JGXAkgV7
+9R7QAKY3K8QzW0QWqHOKv1n4FbfPKhaGMnXYUcQjV9pkVgDmqV4QzjmegATVLkOE
+VVNUjWIP6wXwj0I/UW4jO608tTi9juH+XkDkpf+qqix8FUn81tw7/weWuZXFTpAe
+qAYzjtzzDse8uI1tZWxc8H6AvKCuigoTsD6xkfuPfL4a3JepER0R3WlGhW9hDLBc
+/VXGULLl612XfeG+xREy/pjILzp4ajTC9FdAmdWF2wQWhM9ZXt38FSBHg4+5AQ0E
+U+wYkgEIALu35o9Q309zBBZD6WLTMvFt/X+N6S/cUrNLMv3YvR/Bo1mtDxsYwmzo
+dWOHo6TNthWm1FIkDhHUMB58q9oHzL2/JIL2k/jCULOhj+YAT2N5fQwvZ2WBtWtf
+suFYFO5y7UKKUqo+2Dhnk8YuorPbKjVXELrHFIq0IRlKEKnDfNrkxwHBpfeU4QaC
+UcCW+OjRZFsgZVVc8ZjhvvKd9/vX4Jt/c4/O52Ym+YEYtZaiawcNYFAdMhaiwSF+
+dof+v2e6BIYOJrBifZuILqA87XsHQyBCABO1zhspt5X2QGGqkjVHiFJnYiTwqYX7
+2n1OpoMOklJZ+ShbbGpCst81i7lyz28AEQEAAYkBHwQYAQIACQUCU+wYkgIbDAAK
+CRAm50todK7hJ8OJCACtdgGnPNmYILYJ3jyXh+WPDvxr3y3yMKmC0pRhgs/WxGK6
+cmRV/ej8OB5aIWCaoWeJ03twgqiaSMbn+7ONkr1DbPLzqQGY+QJBJEvLE9m9YcAd
+BMHCT0fn9Op0AYQhoInOPcKLD6NFO+c91uLBOg0q316Wlpl0p3ULH526a2YVPeKw
+mjCVlhrQSoHgxagNrol4gC8bfpypsjTwCccjesiYMOPPU6eyHelFAAGEuVDmkh9g
+Gb9wOqgum0vJEummqOStTopEGr63PoWVMXSQbkrTrayCcxjSiKRfK10myhIGFU2n
+pCL9QbIT7Aw2vZ5VjIm6fWIOPJJz4dsRuYL9Ar8c
+=es9L
+-----END PGP PUBLIC KEY BLOCK-----
+
 pub    82B5574242C20D6F
 -----BEGIN PGP PUBLIC KEY BLOCK-----
 Version: BCPG v1.68
@@ -14226,6 +14319,64 @@
 =TnZo
 -----END PGP PUBLIC KEY BLOCK-----
 
+pub    5A68A2249128E2C6
+uid    Tink Developers (Signing key for Maven artifacts) <tink-dev@google.com>
+
+sub    4E5C59DBFF7DACF9
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: BCPG v1.68
+
+mQINBGPcwwABEADTw/gqmHh4LTSDsBP0KMoXFtFQnv7xmVPPrPjt0NxGn3w2WIou
+7UaLUTViKkgm92h72gyM7N9JfNBLcYrqVf9ed75MPdGQgzIhkVg3SLWZGFoIQUJ4
+VznKuqJmd0dSRtApXL9ZoVXf1mLnbLkOvfLfw2hVIsMJcW9/G4It7pPY82IiwTLn
+XG/pw6+wLa5FGCM4mldPnyBDR935nSkgnZzQJyDESXZKS1uiU1rMcGWkVLJ1UYfg
+fT5c6jAk+75vhyQEvHReoa1T8fgBPD0jAlE7T80460x8dramshhAAIOZLnlAuiBN
+A7KPY7cUDxDyFNLdhj7lGjPP1UTv5mdcZc0H6tgaapOB8QzqnkAJN7GrPHjAWnu7
+ujdiT+lmng+waiBfoQN7HQyJXng8Skj1tVYjuAUNgUuA6p1hL30k9Ny9wO2BBg23
+OXYn8yLptZCUg4T31w2ko2PReSxMeEI6S2jWTALP9HH1Q1sinQnlJ8SfPAssG8wn
+qjaV4PtS8bO+Gy2NosG389dzibrmVJAHqymTLlaviWgeqAXEwZhbVcSOv+B3JgAX
+h1dI2zDJUMGV7jNbKa+UNGb+di8T3J5JEXCNM/Zvm3KNudfZFbcNS1pEzNRzm4gh
+kmNHQEtknSm6NHaWIP5eMIxsKGUA6qTR8XE9qrvpwV35rwbxmPHSowHzzwARAQAB
+tEdUaW5rIERldmVsb3BlcnMgKFNpZ25pbmcga2V5IGZvciBNYXZlbiBhcnRpZmFj
+dHMpIDx0aW5rLWRldkBnb29nbGUuY29tPokCTgQTAQoAOBYhBHOXbJw5wUebhOJk
+GlpooiSRKOLGBQJj3MMAAhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEFpo
+oiSRKOLGX3YP/iAVKH2H5ZKxO78FTLS8Jf1bl48Z31kTnvZg/sMFA51D9p+kBxns
+dNe/4UAt7R7hchlJ6tah9+L5bBf3eU0r4vNwE7+d6WiYoKgGVaegRHfOJEqSlnXo
+a6b3J2ML2vgnRpWTFJPdtZXKekodf76We6YshbHfuix5B0Zfztn2UC54cuhCsi83
+FhEMW9WvMe4Men9u4MsiQU+wCYUtsRV6bZpLWbrYFJyB75/IwWiLZv4AiVIqUpB6
+yw/lTDsPTyrncEfE2+DYwyHduieY+gIR6SGkJh+7VF3ESj6UR1i7+sdcvWbLgJXe
+JoqQBROxnApKh/3LIDUGuONfiryEaC5Xy/l1YkEUsgp5RA5YrotFkTEZCvud6M9m
+iBrFOz0xAHwu84OfcSJsmzARh8lItd4wImykXnhyiTInVUrq9OeDN94RSTFQ7+Mh
+RT+CBnh6Z8y3jL9ekCpGZrxB0K4T4FBxQ0QNLnPZK2OfTEvmC2haP2sofbrYbo31
+TlafpzPfLXyp5sBGevT/vUd3YbXS69L3lDRKoOnJy3PK3UUpeSxTP0sN53mnembu
+8R6eHzuisrb1vl9wsIJ0EFn5F331xQagKYzDn0Vp63KltD3xOnB+itcsZETYamuL
+MHk3TXrNg47Iu6fbLEw9M2HHYDBm70AI1PpXtT4mtQ+TU18JtPM4ZpvHuQINBGPc
+wwABEADh/vvuWr2Pl5xD/gF1vKIdy+sNTTadx7EoAsdnrYShtP3jvUPL9VDvbpyH
+K9B6wFEulUM037L7BOl9khg9oO4G/NXlU3wiIJk4dI4tBrj1IAFD7z3qQ2Sgpy/b
+TsBRZZCwOiW28IxqQsx5DE4i5YYOEjjyqZiza4/I3TchKN0sEOwb77MEUrYS1CUe
+lpl/zFlYZNGXT/oDjJI2bVs1pvCMtb2iQW7m6JvDEY0xZ7zoRm2rJA567oV3WAO6
+u2T2tpAzfu1SYJRRPbUt45pdzWSZUzCQwcB0ZTAuQbK4nIsjPGv6oAPm3PgpEpW2
+PBHPux+UHN03k/vEpb5XLLTBuWIdgtXRzD2vSkEO7A6CBkYTY4TY5UodLgV+szYl
+G+N00m0h2SOf/9FEijRIA2XMfNYZ6E8x3I0ADXmOEE1MfdBGSEtk/Tzb/NX8Bb8/
+zk1tKRI00vEz1bjOTsiRZQ6Aod+hUcCPasTUAKIgTpe30zd1v1krF4leVRXHWJbU
+mpsr7CoJRIrKBghkP7K0vLUQzes0djxl/J9C8Ru7bjM6Ndjmy5+oSCMMPJyJ/Wpd
++fEWZxgIukAnjLtuZTUVeMESzP1CkUeNv+aGadPNGw97VRAFEfk6508ihg+TVEiy
+FORV/njYUB+4zm/+aczd6KKT24t6DIVdm1FkSds8SpcDT8Ei0wARAQABiQI2BBgB
+CgAgFiEEc5dsnDnBR5uE4mQaWmiiJJEo4sYFAmPcwwACGwwACgkQWmiiJJEo4sbA
+dRAAlzA7kLCzFnCSYr2TgCfQEoI8yslnPL0flq7ghw5yBK4OdUbYoUBYBroZMJLw
+hPvyaEdp3t63Sl/9GsYNfub+TAOJA64WuRtOT1QbOh6+U5T7X5yvPM3FAGUuYOlk
+1ABuTAtbOWW+iPOpE7sZaai0j9zH2vPyviBqZ6GtvsuVT7ynRbrYuWe9127ZkJet
+6zPzGXoyTE+FaGOdv/wd+9u1Qjk/lYowNoQ7xXWbnF4jD3o6lM56uOgvPUFoSnzb
+sd1fCXcfQ4wj+O3yEoMDVa1K9eIrSz7TrL5K4VzfOxaHxPh2orE8dFgjXy0Vm/KC
+XTOc9DcJXCjqJVh9RoDxTaNkjWfkN+1bq9NUaPauRduMwlkbk904ygXxMJ485hm5
+uSaCKM8eYBp4y/CdwOcnonBEg+lS3rVIcfDUByRrim5pOsIlSe3f2OX3txMYQvXJ
+ivYOA4phKSpntp4TDzGkZfLbCIpaFowR3px/c2LKuQmTmr+Vl8v5W4kBgQGEDdxY
+a7jhYx9HbLimtQG2XcCC+javwdubT/ItHrfcAB6B+dV0iRA5b4QDGtU0CsD9tY3N
+oaTSCeYc7Xae5YCXr3viH8vWPap984XZWLJZXM2s2Vm1XdeBTQxWCGVER9dnzGGE
+DsHNOZoy3UpsL+GQ+AORGsEAjOVJQnCjqUh7gtB8cwiPvps=
+=TnZo
+-----END PGP PUBLIC KEY BLOCK-----
+
 pub    5E1F79A7C298661E
 uid    David P. Baker <dpb@google.com>
 
diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml
index 23ee8db..9a07f43 100644
--- a/gradle/verification-metadata.xml
+++ b/gradle/verification-metadata.xml
@@ -327,6 +327,7 @@
          <trusted-key id="b46dc71e03feeb7f89d1f2491f7a8f87b9d8f501" group="org.jetbrains.trove4j"/>
          <trusted-key id="b47034c19c9b1f3dc3702f8d476634a4694e716a" group="com.googlecode.java-diff-utils"/>
          <trusted-key id="b4ac8cdc141af0ae468d16921da784ccb5c46dd5" group="net.bytebuddy"/>
+         <trusted-key id="b69a63a5ef7183dbc09199ac26e74b6874aee127" group="com.github.bumptech.glide"/>
          <trusted-key id="b6e73d84ea4fcc47166087253faad2cd5ecbb314" group="org.apache.commons"/>
          <trusted-key id="b801e2f8ef035068ec1139cc29579f18fa8fd93b" group="com.google.j2objc"/>
          <trusted-key id="b9cca13c59f21c6ce841a8d1a4b1a03fb9c2ce23" group="com.squareup.leakcanary"/>
@@ -381,6 +382,7 @@
          </trusted-key>
          <trusted-key id="db0597e3144342256bc81e3ec727d053c4481cf5" group="org.tensorflow"/>
          <trusted-key id="dbd744ace7ade6aa50dd591f66b50994442d2d40">
+            <trusting group="com.squareup.okhttp3"/>
             <trusting group="com.squareup.okio"/>
             <trusting group="com.squareup.wire"/>
          </trusted-key>
@@ -477,6 +479,14 @@
             <sha256 value="9fb18fd29b9dfe2e7ed5fe98a3be433a4c3cc4ea8f47f2b444155c39b4afddf5" origin="Generated by Gradle" reason="Unsigned. Used by media3."/>
          </artifact>
       </component>
+      <component group="com.google.ads.interactivemedia.v3" name="interactivemedia" version="3.30.1">
+         <artifact name="interactivemedia-3.30.1.aar">
+            <sha256 value="e2cc79031befb48c6212a0c71cf1535416a8903a9a373ba6c8b95dec95db83c0" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+         <artifact name="interactivemedia-3.30.1.pom">
+            <sha256 value="19f7d921a20d3be022620dd78bd708b2c16362cece59781c94b74a51f078243c" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+      </component>
       <component group="com.google.android.apps.common.testing.accessibility.framework" name="accessibility-test-framework" version="2.1">
          <artifact name="accessibility-test-framework-2.1.jar">
             <sha256 value="7b0aa6ed7553597ce0610684a9f7eca8021eee218f2e2f427c04a7fbf5f920bd" origin="Generated by Gradle" reason="Artifact is not signed"/>
@@ -549,6 +559,14 @@
             <sha256 value="c6898b1f71e69b15bf90c31fc3ef2de1cffbf454a770700f755b5a47ea48b540" origin="Generated by Gradle"/>
          </artifact>
       </component>
+      <component group="com.google.android.tv" name="tv-ads" version="1.0.0-alpha02">
+         <artifact name="tv-ads-1.0.0-alpha02.aar">
+            <sha256 value="d92a8eb07b926cdd199f3bdaf33478565cab125b92859e84f7abb5b7219bc5e4" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+         <artifact name="tv-ads-1.0.0-alpha02.pom">
+            <sha256 value="7b4315f0127628f2203ab66dfe490a9a07e06a38fb8e15ea2df1a35f1619308d" origin="Generated by Gradle" reason="Artifact is not signed"/>
+         </artifact>
+      </component>
       <component group="com.google.camerax.effects" name="portrait" version="0.0.1">
          <artifact name="portrait-0.0.1.aar">
             <sha256 value="86d3e99a6123e3f830bf3f70392b30fc8d238374104ce00a02de20d8613af607" origin="Generated by Gradle"/>
diff --git a/metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/JankStatsTest.kt b/metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/JankStatsTest.kt
index a933cfc..8f79640 100644
--- a/metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/JankStatsTest.kt
+++ b/metrics/metrics-performance/src/androidTest/java/androidx/metrics/performance/test/JankStatsTest.kt
@@ -18,6 +18,7 @@
 import android.os.Build
 import android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
 import android.os.Build.VERSION_CODES.JELLY_BEAN
+import android.util.Log
 import android.view.Choreographer
 import androidx.annotation.RequiresApi
 import androidx.metrics.performance.FrameData
@@ -295,6 +296,8 @@
 
         frameInit.initFramePipeline()
 
+        resetFrameStateData()
+
         val state0 = StateInfo("Testing State 0", "sampleStateA")
         val state1 = StateInfo("Testing State 1", "sampleStateB")
         val state2 = StateInfo("Testing State 2", "sampleStateC")
@@ -332,6 +335,7 @@
         }
 
         // reset and clear states
+        resetFrameStateData()
         latchedListener.reset()
         metricsState.removeState(state0.key)
         metricsState.removeState(state1.key)
@@ -339,7 +343,7 @@
         runDelayTest(frameDelay, 1, latchedListener)
         item0 = latchedListener.jankData[0]
         assertEquals(
-            "States should be empty after being cleared",
+            "States should be empty after being cleared, but got ${item0.states}",
             0,
             item0.states.size
         )
@@ -350,15 +354,16 @@
         metricsState.putState(state4.first, state4.second)
         runDelayTest(frameDelay, 1, latchedListener)
         item0 = latchedListener.jankData[0]
-        assertEquals(2, item0.states.size)
+        assertEquals("states: ${item0.states}", 2, item0.states.size)
         latchedListener.reset()
 
         // Test removal of state3 and replacement of state4
+        resetFrameStateData()
         metricsState.removeState(state3.first)
         metricsState.putState(state4.first, "sampleStateF")
         runDelayTest(frameDelay, 1, latchedListener)
         item0 = latchedListener.jankData[0]
-        assertEquals(1, item0.states.size)
+        assertEquals("states: ${item0.states}", 1, item0.states.size)
         assertEquals(state4.first, item0.states[0].key)
         assertEquals("sampleStateF", item0.states[0].value)
         latchedListener.reset()
@@ -496,6 +501,7 @@
             mapOf("stateNameA" to "1"),
         )
 
+        resetFrameStateData()
         runDelayTest(frameDelay = 0, numFrames = perFrameStateData.size,
             latchedListener, perFrameStateData)
 
@@ -514,7 +520,8 @@
          */
         var expectedIndex = 0
         var resultIndex = 0
-        while (expectedIndex < expectedResults.size) {
+        while (expectedIndex < expectedResults.size &&
+            resultIndex < latchedListener.jankData.size) {
             val testResultStates = latchedListener.jankData[resultIndex].states
             // Test against this and next expected result, in case system skipped a frame
             var matched = checkFrameStates(expectedResults[expectedIndex], testResultStates)
@@ -522,7 +529,8 @@
                 expectedIndex++
                 matched = checkFrameStates(expectedResults[expectedIndex], testResultStates)
             }
-            assertTrue("States do not match at frame $expectedIndex", matched)
+            assertTrue("Expected states do not match $testResultStates at frame " +
+                "$expectedIndex", matched)
             expectedIndex++
             resultIndex++
         }
@@ -541,6 +549,38 @@
         return true
     }
 
+    /**
+     * We need to ensure that state data only gets set when the system is ready to send frameData
+     * for future frames. It is possible for some of the initial frames to have start times that
+     * pre-date the current time, which is when we might be setting/removing state.
+     *
+     * To ensure that the right thing happens, call this function prior to setting any frame state.
+     * It will run frames through the system until the frameData start timeis after the
+     * current time when this function is called.
+     */
+    private fun resetFrameStateData() {
+        val currentNanos = System.nanoTime()
+        // failsafe - limit the iterations, don't want to loop forever
+        var numAttempts = 0
+        try {
+            while (numAttempts < 100) {
+                runDelayTest(0, 1, latchedListener)
+                if (latchedListener.jankData.size > 0) {
+                    if (latchedListener.jankData[0].frameStartNanos > currentNanos) {
+                        return
+                    }
+                }
+                Log.d("JankStatsTest", "resetFrameStateData attempt $numAttempts:" +
+                    "frame start < currentTime: " +
+                    "${latchedListener.jankData[0].frameStartNanos}, $currentNanos")
+                latchedListener.reset()
+                numAttempts++
+            }
+        } finally {
+            latchedListener.reset()
+        }
+    }
+
     private fun runDelayTest(
         frameDelay: Int,
         numFrames: Int,
diff --git a/navigation/navigation-fragment/build.gradle b/navigation/navigation-fragment/build.gradle
index 5edeaf7..7d08548 100644
--- a/navigation/navigation-fragment/build.gradle
+++ b/navigation/navigation-fragment/build.gradle
@@ -23,12 +23,12 @@
 }
 
 dependencies {
-    api(projectOrArtifact(":fragment:fragment-ktx"))
+    api("androidx.fragment:fragment-ktx:1.6.0-rc01")
     api(project(":navigation:navigation-runtime"))
     api("androidx.slidingpanelayout:slidingpanelayout:1.2.0")
     api(libs.kotlinStdlib)
     androidTestImplementation(project(":navigation:navigation-testing"))
-    androidTestImplementation(projectOrArtifact(":fragment:fragment-testing"))
+    androidTestImplementation("androidx.fragment:fragment-testing:1.6.0-rc01")
     androidTestImplementation(libs.testExtJunit)
     androidTestImplementation(libs.testCore)
     androidTestImplementation(libs.testRunner)
diff --git a/privacysandbox/tools/tools-apicompiler/src/main/java/androidx/privacysandbox/tools/apicompiler/generator/SdkCodeGenerator.kt b/privacysandbox/tools/tools-apicompiler/src/main/java/androidx/privacysandbox/tools/apicompiler/generator/SdkCodeGenerator.kt
index c46fb02..d3332ac 100644
--- a/privacysandbox/tools/tools-apicompiler/src/main/java/androidx/privacysandbox/tools/apicompiler/generator/SdkCodeGenerator.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/main/java/androidx/privacysandbox/tools/apicompiler/generator/SdkCodeGenerator.kt
@@ -22,6 +22,7 @@
 import androidx.privacysandbox.tools.core.generator.ClientProxyTypeGenerator
 import androidx.privacysandbox.tools.core.generator.CoreLibInfoAndBinderWrapperConverterGenerator
 import androidx.privacysandbox.tools.core.generator.GenerationTarget
+import androidx.privacysandbox.tools.core.generator.SdkActivityLauncherWrapperGenerator
 import androidx.privacysandbox.tools.core.generator.ServerBinderCodeConverter
 import androidx.privacysandbox.tools.core.generator.ServiceFactoryFileGenerator
 import androidx.privacysandbox.tools.core.generator.StubDelegatesGenerator
@@ -29,6 +30,7 @@
 import androidx.privacysandbox.tools.core.generator.TransportCancellationGenerator
 import androidx.privacysandbox.tools.core.generator.ValueConverterFileGenerator
 import androidx.privacysandbox.tools.core.model.ParsedApi
+import androidx.privacysandbox.tools.core.model.containsSdkActivityLauncher
 import androidx.privacysandbox.tools.core.model.getOnlyService
 import androidx.privacysandbox.tools.core.model.hasSuspendFunctions
 import com.google.devtools.ksp.processing.CodeGenerator
@@ -68,6 +70,7 @@
         generateCallbackProxies()
         generateToolMetadata()
         generateSuspendFunctionUtilities()
+        generateSdkActivityLauncherUtilities()
         generateServiceFactoryFile()
     }
 
@@ -151,6 +154,11 @@
             .also(::write)
     }
 
+    private fun generateSdkActivityLauncherUtilities() {
+        if (!api.containsSdkActivityLauncher()) return
+        SdkActivityLauncherWrapperGenerator(basePackageName()).generate().also(::write)
+    }
+
     private fun write(spec: FileSpec) {
         codeGenerator.createNewFile(Dependencies.ALL_FILES, spec.packageName, spec.name)
             .bufferedWriter().use(spec::writeTo)
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/input/com/mysdk/MySdk.kt b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/input/com/mysdk/MySdk.kt
index c096f86..c23eaad 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/input/com/mysdk/MySdk.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/input/com/mysdk/MySdk.kt
@@ -5,6 +5,7 @@
 import androidx.privacysandbox.tools.PrivacySandboxService
 import androidx.privacysandbox.tools.PrivacySandboxValue
 import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SdkActivityLauncher
 
 @PrivacySandboxService
 interface MySdk {
@@ -31,6 +32,8 @@
     suspend fun returnUiInterface(): MyUiInterface
 
     fun acceptUiInterfaceParam(input: MyUiInterface)
+
+    fun acceptSdkActivityLauncherParam(activityLauncher: SdkActivityLauncher)
 }
 
 @PrivacySandboxInterface
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/MySdkStubDelegate.kt b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/MySdkStubDelegate.kt
index 0d5c413..79bd6e5 100644
--- a/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/MySdkStubDelegate.kt
+++ b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/MySdkStubDelegate.kt
@@ -1,6 +1,7 @@
 package com.mysdk
 
 import android.content.Context
+import android.os.Bundle
 import androidx.privacysandbox.ui.provider.toCoreLibInfo
 import com.mysdk.PrivacySandboxThrowableParcelConverter
 import com.mysdk.PrivacySandboxThrowableParcelConverter.toThrowableParcel
@@ -172,4 +173,10 @@
       delegate.acceptUiInterfaceParam((input.binder as MyUiInterfaceStubDelegate).delegate)
     }
   }
+
+  public override fun acceptSdkActivityLauncherParam(activityLauncher: Bundle): Unit {
+    coroutineScope.launch {
+      delegate.acceptSdkActivityLauncherParam(SdkActivityLauncherAndBinderWrapper(activityLauncher))
+    }
+  }
 }
diff --git a/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/SdkActivityLauncherAndBinderWrapper.kt b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/SdkActivityLauncherAndBinderWrapper.kt
new file mode 100644
index 0000000..8ef1af5
--- /dev/null
+++ b/privacysandbox/tools/tools-apicompiler/src/test/test-data/fullfeaturedsdk/output/com/mysdk/SdkActivityLauncherAndBinderWrapper.kt
@@ -0,0 +1,13 @@
+package com.mysdk
+
+import android.os.Bundle
+import androidx.privacysandbox.ui.core.SdkActivityLauncher
+import androidx.privacysandbox.ui.provider.SdkActivityLauncherFactory
+
+public class SdkActivityLauncherAndBinderWrapper private constructor(
+    private val `delegate`: SdkActivityLauncher,
+    public val launcherInfo: Bundle,
+) : SdkActivityLauncher by delegate {
+    public constructor(launcherInfo: Bundle) :
+            this(SdkActivityLauncherFactory.fromLauncherInfo(launcherInfo), launcherInfo)
+}
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
index 4c4c071..dae0d2ac 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/java/androidx/privacysandbox/tools/apigenerator/parser/ApiStubParserTest.kt
@@ -26,6 +26,7 @@
 import androidx.privacysandbox.tools.core.model.Types
 import androidx.privacysandbox.tools.core.model.Types.asNullable
 import androidx.privacysandbox.tools.core.model.ValueProperty
+import androidx.privacysandbox.tools.core.model.containsSdkActivityLauncher
 import androidx.privacysandbox.tools.testing.CompilationTestHelper.assertCompiles
 import androidx.room.compiler.processing.util.Source
 import androidx.testutils.assertThrows
@@ -263,6 +264,59 @@
     }
 
     @Test
+    fun sandboxedUiAdapter_correctlyDetectedInService() {
+        val source = Source.kotlin(
+            "com/mysdk/MySdk.kt", """
+                    import androidx.privacysandbox.tools.PrivacySandboxService
+                    import androidx.privacysandbox.ui.core.SdkActivityLauncher
+                    @PrivacySandboxService
+                    interface MySdk {
+                        fun useLauncher(launcher: SdkActivityLauncher)
+                    }
+                """
+        )
+
+        assertThat(compileAndParseApi(source).containsSdkActivityLauncher()).isTrue()
+    }
+
+    @Test
+    fun sandboxedUiAdapter_correctlyDetectedInInterface() {
+        val source = Source.kotlin(
+            "com/mysdk/MySdk.kt", """
+                    import androidx.privacysandbox.tools.PrivacySandboxService
+                    import androidx.privacysandbox.tools.PrivacySandboxInterface
+                    import androidx.privacysandbox.ui.core.SdkActivityLauncher
+                    @PrivacySandboxService
+                    interface MySdk
+
+                    @PrivacySandboxInterface
+                    interface MyInterface {
+                        fun useLauncher(launcher: SdkActivityLauncher)
+                    }
+                """
+        )
+
+        assertThat(compileAndParseApi(source).containsSdkActivityLauncher()).isTrue()
+    }
+
+    @Test
+    fun sandboxedUiAdapter_notDetectedWhenNotPresent() {
+        val source = Source.kotlin(
+            "com/mysdk/MySdk.kt", """
+                    import androidx.privacysandbox.tools.PrivacySandboxService
+                    // Deliberate unused import
+                    import androidx.privacysandbox.ui.core.SdkActivityLauncher
+                    @PrivacySandboxService
+                    interface MySdk {
+                        fun doStuff(input: String)
+                    }
+                """
+        )
+
+        assertThat(compileAndParseApi(source).containsSdkActivityLauncher()).isFalse()
+    }
+
+    @Test
     fun nonKotlinAnnotatedInterface_throws() {
         val source = Source.java(
             "com/mysdk/MySdk", """
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
index 74b3e78..413a47a 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/input/com/sdk/MySdk.kt
@@ -4,6 +4,7 @@
 import androidx.privacysandbox.tools.PrivacySandboxInterface
 import androidx.privacysandbox.tools.PrivacySandboxService
 import androidx.privacysandbox.ui.core.SandboxedUiAdapter
+import androidx.privacysandbox.ui.core.SdkActivityLauncher
 
 @PrivacySandboxService
 interface MySdk {
@@ -21,6 +22,8 @@
     fun doSomething(firstInterface: MyInterface, secondInterface: MySecondInterface)
 
     fun doSomethingWithNullableInterface(maybeInterface: MySecondInterface?)
+
+    public fun doSomethingWithSdkActivityLauncher(launcher: SdkActivityLauncher)
 }
 
 @PrivacySandboxInterface
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterface.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterface.kt
index e04de66..cc0fb50 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterface.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterface.kt
@@ -1,9 +1,13 @@
 package com.sdk
 
+import androidx.privacysandbox.ui.core.SdkActivityLauncher
+
 public interface MyInterface {
     public suspend fun add(x: Int, y: Int): Int
 
     public fun doSomething(firstInterface: MyInterface, secondInterface: MySecondInterface): Unit
 
     public fun doSomethingWithNullableInterface(maybeInterface: MySecondInterface?): Unit
+
+    public fun doSomethingWithSdkActivityLauncher(launcher: SdkActivityLauncher): Unit
 }
diff --git a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterfaceClientProxy.kt b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterfaceClientProxy.kt
index 05069c3..1a874d7 100644
--- a/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterfaceClientProxy.kt
+++ b/privacysandbox/tools/tools-apigenerator/src/test/test-data/interfaces/output/com/sdk/MyInterfaceClientProxy.kt
@@ -1,5 +1,7 @@
 package com.sdk
 
+import androidx.privacysandbox.ui.client.toLauncherInfo
+import androidx.privacysandbox.ui.core.SdkActivityLauncher
 import com.sdk.PrivacySandboxThrowableParcelConverter.fromThrowableParcel
 import kotlin.coroutines.resumeWithException
 import kotlinx.coroutines.suspendCancellableCoroutine
@@ -41,4 +43,8 @@
                 IMySecondInterfaceCoreLibInfoAndBinderWrapperConverter.toParcelable((notNullValue as
                 MySecondInterfaceClientProxy).coreLibInfo, notNullValue.remote) })
     }
+
+    public override fun doSomethingWithSdkActivityLauncher(launcher: SdkActivityLauncher): Unit {
+        remote.doSomethingWithSdkActivityLauncher(launcher.toLauncherInfo())
+    }
 }
diff --git a/privacysandbox/tools/tools-apipackager/build.gradle b/privacysandbox/tools/tools-apipackager/build.gradle
index 19089d3..006779b 100644
--- a/privacysandbox/tools/tools-apipackager/build.gradle
+++ b/privacysandbox/tools/tools-apipackager/build.gradle
@@ -15,6 +15,8 @@
  */
 
 import androidx.build.LibraryType
+import androidx.build.SdkHelperKt
+import androidx.build.SupportConfig
 
 plugins {
     id("AndroidXPlugin")
@@ -35,6 +37,13 @@
     testImplementation(project(":room:room-compiler-processing-testing"))
     testImplementation(libs.junit)
     testImplementation(libs.truth)
+
+    // TODO(b/281638337): Remove below dependency once SdkActivityLauncher stubs are removed
+    // Include android jar for compilation of generated sources.
+    testImplementation(fileTree(
+            dir: "${SdkHelperKt.getSdkPath(project)}/platforms/$SupportConfig.COMPILE_SDK_VERSION/",
+            include: "android.jar"
+    ))
 }
 
 androidx {
diff --git a/privacysandbox/tools/tools-apipackager/src/test/java/androidx/privacysandbox/tools/apipackager/PrivacySandboxApiPackagerTest.kt b/privacysandbox/tools/tools-apipackager/src/test/java/androidx/privacysandbox/tools/apipackager/PrivacySandboxApiPackagerTest.kt
index e537412..eb4b128 100644
--- a/privacysandbox/tools/tools-apipackager/src/test/java/androidx/privacysandbox/tools/apipackager/PrivacySandboxApiPackagerTest.kt
+++ b/privacysandbox/tools/tools-apipackager/src/test/java/androidx/privacysandbox/tools/apipackager/PrivacySandboxApiPackagerTest.kt
@@ -208,7 +208,7 @@
 
     /** Compiles the given source file and returns a classpath with the results. */
     private fun compileAndReturnUnzippedPackagedClasspath(source: Source): File {
-        val result = compileAll(listOf(source))
+        val result = compileAll(listOf(source), includeLibraryStubs = false)
         assertThat(result).succeeds()
         assertThat(result.outputClasspath).hasSize(1)
 
@@ -221,7 +221,7 @@
             generateSequence { input.nextEntry }
                 .forEach {
                     val file: File = outputDir.resolve(it.name)
-                    file.parentFile.mkdirs()
+                    file.parentFile?.mkdirs()
                     file.createNewFile()
                     input.copyTo(file.outputStream())
                 }
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/AidlGenerator.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/AidlGenerator.kt
index 2cf4f2f..abb403b 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/AidlGenerator.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/AidlGenerator.kt
@@ -118,10 +118,7 @@
 
     private fun uiAidlWrapper(annotatedInterface: AnnotatedInterface) =
         aidlParcelable(annotatedInterface.uiAdapterAidlWrapper()) {
-            addProperty(
-                "coreLibInfo",
-                AidlTypeSpec(bundleType(), kind = AidlTypeKind.PARCELABLE)
-            )
+            addProperty("coreLibInfo", bundleAidlType)
             addProperty("binder", annotatedInterface.aidlType())
         }
 
@@ -246,7 +243,12 @@
 
     private fun throwableParcelType() = Type(packageName(), throwableParcelName)
     private fun parcelableStackFrameType() = Type(packageName(), parcelableStackFrameName)
-    private fun bundleType() = Type("android.os", "Bundle")
+    private val bundleType = Type("android.os", "Bundle")
+    private val bundleAidlType =
+        AidlTypeSpec(
+            bundleType,
+            AidlTypeKind.PARCELABLE
+        )
 
     private fun transactionCallback(type: Type) =
         AidlTypeSpec(
@@ -276,6 +278,7 @@
             Short::class.qualifiedName -> primitive("int")
             Unit::class.qualifiedName -> primitive("void")
             List::class.qualifiedName -> getAidlTypeDeclaration(type.typeParameters[0]).listSpec()
+            Types.sdkActivityLauncher.qualifiedName -> bundleAidlType
             else -> throw IllegalArgumentException(
                 "Unsupported type conversion ${type.qualifiedName}"
             )
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/BinderCodeConverter.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/BinderCodeConverter.kt
index 0ef84b3e..c029621 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/BinderCodeConverter.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/BinderCodeConverter.kt
@@ -16,6 +16,7 @@
 
 package androidx.privacysandbox.tools.core.generator
 
+import androidx.privacysandbox.tools.core.generator.SpecNames.bundleClass
 import androidx.privacysandbox.tools.core.generator.SpecNames.contextPropertyName
 import androidx.privacysandbox.tools.core.model.AnnotatedInterface
 import androidx.privacysandbox.tools.core.model.AnnotatedValue
@@ -25,6 +26,7 @@
 import androidx.privacysandbox.tools.core.model.Types.asNonNull
 import com.squareup.kotlinpoet.ClassName
 import com.squareup.kotlinpoet.CodeBlock
+import com.squareup.kotlinpoet.MemberName
 import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
 import com.squareup.kotlinpoet.TypeName
 
@@ -80,6 +82,9 @@
                     CodeBlock.of(".map { %L }", convertToModelCodeBlock)
             )
         }
+        if (type.qualifiedName == Types.sdkActivityLauncher.qualifiedName) {
+            return CodeBlock.of("SdkActivityLauncherAndBinderWrapper(%L)", expression)
+        }
         if (type == Types.short) {
             return CodeBlock.of("%L.toShort()", expression)
         }
@@ -140,6 +145,13 @@
                 toBinderList(type.typeParameters[0])
             )
         }
+        if (type.qualifiedName == Types.sdkActivityLauncher.qualifiedName) {
+            return CodeBlock.of(
+                "%L.%M()",
+                expression,
+                MemberName("androidx.privacysandbox.ui.client", "toLauncherInfo"),
+            )
+        }
         if (type == Types.short) {
             return CodeBlock.of("%L.toInt()", expression)
         }
@@ -215,6 +227,8 @@
         }
         if (type.qualifiedName == List::class.qualifiedName)
             return convertToBinderListType(type.typeParameters[0])
+        if (type.qualifiedName == Types.sdkActivityLauncher.qualifiedName)
+            return bundleClass
         return type.poetTypeName()
     }
 
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/SdkActivityLauncherWrapperGenerator.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/SdkActivityLauncherWrapperGenerator.kt
new file mode 100644
index 0000000..a90a3ef
--- /dev/null
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/generator/SdkActivityLauncherWrapperGenerator.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.privacysandbox.tools.core.generator
+
+import androidx.privacysandbox.tools.core.model.Types
+import com.squareup.kotlinpoet.ClassName
+import com.squareup.kotlinpoet.CodeBlock
+import com.squareup.kotlinpoet.FileSpec
+import com.squareup.kotlinpoet.FunSpec
+import com.squareup.kotlinpoet.KModifier
+import com.squareup.kotlinpoet.PropertySpec
+import com.squareup.kotlinpoet.TypeSpec
+
+/**
+ * Used in server-side code generation to ensure that `SdkActivityLauncher`s are not repeatedly
+ * repackaged into binders.
+ */
+class SdkActivityLauncherWrapperGenerator(private val basePackageName: String) {
+    companion object {
+        const val className = "SdkActivityLauncherAndBinderWrapper"
+    }
+
+    fun generate(): FileSpec {
+        val classSpec = TypeSpec.classBuilder(className).build {
+            addSuperinterface(Types.sdkActivityLauncher.poetClassName(), CodeBlock.of("delegate"))
+            addModifiers(KModifier.PUBLIC)
+            primaryConstructor(
+                listOf(
+                    PropertySpec.builder(
+                        "delegate",
+                        Types.sdkActivityLauncher.poetTypeName(),
+                    ).addModifiers(KModifier.PRIVATE).build(),
+                    PropertySpec.builder(
+                        "launcherInfo",
+                        SpecNames.bundleClass,
+                    ).build(),
+                ),
+                KModifier.PRIVATE,
+            )
+            addFunction(
+                FunSpec.constructorBuilder()
+                    .addParameter("launcherInfo", SpecNames.bundleClass)
+                    .callThisConstructor(
+                        CodeBlock.of(
+                            "%T.fromLauncherInfo(launcherInfo)",
+                            ClassName(
+                                "androidx.privacysandbox.ui.provider",
+                                "SdkActivityLauncherFactory"
+                            ),
+                        ),
+                        CodeBlock.of("launcherInfo"),
+                    ).build()
+            )
+        }
+
+        return FileSpec.builder(basePackageName, className).build {
+            addCommonSettings()
+            addType(classSpec)
+        }
+    }
+}
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/model/Models.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/model/Models.kt
index 88245e9..15d0e4b 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/model/Models.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/model/Models.kt
@@ -30,6 +30,26 @@
         .any(Method::isSuspend)
 }
 
+fun ParsedApi.containsSdkActivityLauncher(): Boolean {
+    return values.any { it.containsSdkActivityLauncher() } ||
+        interfaces.any { it.containsSdkActivityLauncher() } ||
+        callbacks.any { it.containsSdkActivityLauncher() } ||
+        services.any { it.containsSdkActivityLauncher() }
+}
+
+private fun AnnotatedInterface.containsSdkActivityLauncher(): Boolean {
+    val isInReturns = methods
+        .any { it.returnType.qualifiedName == Types.sdkActivityLauncher.qualifiedName }
+    val isInParams = methods
+        .flatMap { it.parameters }
+        .any { it.type.qualifiedName == Types.sdkActivityLauncher.qualifiedName }
+
+    return isInReturns || isInParams
+}
+
+private fun AnnotatedValue.containsSdkActivityLauncher(): Boolean =
+    properties.any { it.type.qualifiedName == Types.sdkActivityLauncher.qualifiedName }
+
 object Types {
     val unit = Type(packageName = "kotlin", simpleName = "Unit")
     val boolean = Type(packageName = "kotlin", simpleName = "Boolean")
@@ -45,6 +65,8 @@
     val any = Type("kotlin", simpleName = "Any")
     val sandboxedUiAdapter =
         Type(packageName = "androidx.privacysandbox.ui.core", simpleName = "SandboxedUiAdapter")
+    val sdkActivityLauncher =
+        Type(packageName = "androidx.privacysandbox.ui.core", simpleName = "SdkActivityLauncher")
 
     fun list(elementType: Type) = Type(
         packageName = "kotlin.collections",
@@ -57,6 +79,7 @@
             return this
         return copy(isNullable = true)
     }
+
     fun Type.asNonNull(): Type {
         if (isNullable)
             return copy(isNullable = false)
diff --git a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
index bc6aeb5..90603e5 100644
--- a/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
+++ b/privacysandbox/tools/tools-core/src/main/java/androidx/privacysandbox/tools/core/validator/ModelValidator.kt
@@ -147,7 +147,9 @@
     }
 
     private fun isValidInterfaceParameterType(type: Type) =
-        isValue(type) || isInterface(type) || isPrimitive(type) || isList(type) || isCallback(type)
+        isValue(type) || isInterface(type) || isPrimitive(type) || isList(type) ||
+            isCallback(type) || isBundledType(type)
+
     private fun isValidInterfaceReturnType(type: Type) =
         isValue(type) || isInterface(type) || isPrimitive(type) || isList(type)
     private fun isValidValuePropertyType(type: Type) =
@@ -171,6 +173,8 @@
         }
         return false
     }
+
+    private fun isBundledType(type: Type) = type == Types.sdkActivityLauncher
 }
 
 data class ValidationResult(val errors: List<String>) {
diff --git a/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/generator/AidlInterfaceGeneratorTest.kt b/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/generator/AidlInterfaceGeneratorTest.kt
index 780e27c..a536da8 100644
--- a/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/generator/AidlInterfaceGeneratorTest.kt
+++ b/privacysandbox/tools/tools-core/src/test/java/androidx/privacysandbox/tools/core/generator/AidlInterfaceGeneratorTest.kt
@@ -72,7 +72,15 @@
                             parameters = listOf(),
                             returnType = Type("com.mysdk", "MyInterface"),
                             isSuspend = true,
-                        )
+                        ),
+                        Method(
+                            name = "methodWithActivityLauncherParam",
+                            parameters = listOf(
+                                Parameter("activityLauncher", Types.sdkActivityLauncher)
+                            ),
+                            returnType = Types.unit,
+                            isSuspend = false,
+                        ),
                     )
                 )
             )
diff --git a/privacysandbox/tools/tools-core/src/test/test-data/aidlinterfacegeneratortest/output/com/mysdk/IMyInterface.aidl b/privacysandbox/tools/tools-core/src/test/test-data/aidlinterfacegeneratortest/output/com/mysdk/IMyInterface.aidl
index 2a532b7..4815029 100644
--- a/privacysandbox/tools/tools-core/src/test/test-data/aidlinterfacegeneratortest/output/com/mysdk/IMyInterface.aidl
+++ b/privacysandbox/tools/tools-core/src/test/test-data/aidlinterfacegeneratortest/output/com/mysdk/IMyInterface.aidl
@@ -1,8 +1,10 @@
 package com.mysdk;
 
+import android.os.Bundle;
 import com.mysdk.IMyInterfaceTransactionCallback;
 
 oneway interface IMyInterface {
+    void methodWithActivityLauncherParam(in Bundle activityLauncher) = 12556385;
     void methodWithInterfaceParam(IMyInterface myInterface) = 5537946;
     void suspendMethodWithInterfaceReturn(IMyInterfaceTransactionCallback transactionCallback) = 13841773;
 }
\ No newline at end of file
diff --git a/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/CompilationTestHelper.kt b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/CompilationTestHelper.kt
index 0a9c958..175800e 100644
--- a/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/CompilationTestHelper.kt
+++ b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/CompilationTestHelper.kt
@@ -40,13 +40,17 @@
         sources: List<Source>,
         extraClasspath: List<File> = emptyList(),
         symbolProcessorProviders: List<SymbolProcessorProvider> = emptyList(),
-        processorOptions: Map<String, String> = emptyMap()
+        processorOptions: Map<String, String> = emptyMap(),
+        includeLibraryStubs: Boolean = true,
     ): TestCompilationResult {
         val tempDir = Files.createTempDirectory("compile").toFile().also { it.deleteOnExit() }
+        // TODO(b/281638337): Remove library stubs once SdkActivityLauncher is upstreamed
+        val fullSources = sources +
+            if (includeLibraryStubs) syntheticUiLibraryStubs else emptyList()
         return compile(
             tempDir,
             TestCompilationArguments(
-                sources = sources,
+                sources = fullSources,
                 classpath = extraClasspath,
                 symbolProcessorProviders = symbolProcessorProviders,
                 processorOptions = processorOptions,
diff --git a/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt
new file mode 100644
index 0000000..95116e5
--- /dev/null
+++ b/privacysandbox/tools/tools-testing/src/main/java/androidx/privacysandbox/tools/testing/LibraryStubs.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.privacysandbox.tools.testing
+
+import androidx.room.compiler.processing.util.Source
+
+val syntheticUiLibraryStubs = listOf(
+    Source.kotlin(
+        "androidx/privacysandbox/ui/core/SandboxedUiAdapter.kt", """
+        |package androidx.privacysandbox.ui.core
+        |
+        |import android.os.IBinder
+        |
+        |interface SdkActivityLauncher {
+        |    suspend fun launchSdkActivity(sdkActivityHandlerToken: IBinder): Boolean
+        |}
+        |""".trimMargin()
+    ),
+    Source.kotlin(
+        "androidx/privacysandbox/ui/client/SdkActivityLaunchers.kt", """
+        |@file:JvmName("SdkActivityLaunchers")
+        |
+        |package androidx.privacysandbox.ui.client
+        |
+        |import android.os.Bundle
+        |import androidx.privacysandbox.ui.core.SdkActivityLauncher
+        |
+        |fun SdkActivityLauncher.toLauncherInfo(): Bundle {
+        |    TODO("Stub!")
+        |}
+        |""".trimMargin()
+    ),
+    Source.kotlin(
+        "androidx/privacysandbox/ui/provider/SdkActivityLauncherFactory.kt", """
+        |package androidx.privacysandbox.ui.provider
+        |
+        |import android.os.Bundle
+        |import androidx.privacysandbox.ui.core.SdkActivityLauncher
+        |
+        |object SdkActivityLauncherFactory {
+        |
+        |    @JvmStatic
+        |    @Suppress("UNUSED_PARAMETER")
+        |    fun fromLauncherInfo(launcherInfo: Bundle): SdkActivityLauncher {
+        |        TODO("Stub!")
+        |    }
+        |}""".trimMargin()
+    ),
+    Source.kotlin(
+        "androidx/core/os/BundleCompat.kt", """
+        |package androidx.core.os
+        |
+        |import android.os.IBinder
+        |import android.os.Bundle
+        |
+        |object BundleCompat {
+        |    @Suppress("UNUSED_PARAMETER")
+        |    fun getBinder(bundle: Bundle, key: String?): IBinder? {
+        |        TODO("Stub!")
+        |    }
+        |}
+        |""".trimMargin()
+    ),
+)
diff --git a/settings.gradle b/settings.gradle
index 0f11a3a..063496e 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1012,11 +1012,13 @@
 includeProject(":wear:compose:compose-material3-benchmark", "wear/compose/compose-material3/benchmark", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-material-core", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-material-samples", "wear/compose/compose-material/samples", [BuildType.COMPOSE])
+includeProject(":wear:compose:compose-material3-integration-tests", "wear/compose/compose-material3/integration-tests", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-material3-samples", "wear/compose/compose-material3/samples", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-navigation", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-navigation-samples", "wear/compose/compose-navigation/samples", [BuildType.COMPOSE])
 includeProject(":wear:compose:compose-ui-tooling", [BuildType.COMPOSE])
 includeProject(":wear:compose:integration-tests:demos", [BuildType.COMPOSE])
+includeProject(":wear:compose:integration-tests:demos:common", [BuildType.COMPOSE])
 includeProject(":wear:compose:integration-tests:macrobenchmark", [BuildType.COMPOSE])
 includeProject(":wear:compose:integration-tests:macrobenchmark-target", [BuildType.COMPOSE])
 includeProject(":wear:compose:integration-tests:navigation", [BuildType.COMPOSE])
diff --git a/wear/compose/compose-material3/integration-tests/build.gradle b/wear/compose/compose-material3/integration-tests/build.gradle
new file mode 100644
index 0000000..b139b83
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/build.gradle
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2023 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 androidx.build.Publish
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("AndroidXComposePlugin")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+
+    implementation(project(":compose:animation:animation"))
+    implementation(project(":compose:foundation:foundation"))
+    implementation(project(":compose:foundation:foundation-layout"))
+    implementation(project(":compose:runtime:runtime"))
+    implementation(project(":compose:ui:ui"))
+    implementation(project(":compose:ui:ui-text"))
+
+    implementation(project(':wear:compose:compose-foundation'))
+    implementation(project(':wear:compose:compose-material3'))
+    implementation(project(':wear:compose:integration-tests:demos:common'))
+}
+
+androidx {
+    name = "AndroidX Wear Compose Material3 Components Demos"
+    publish = Publish.NONE
+    inceptionYear = "2023"
+    description = "Contains the demo code for the AndroidX Wear Compose Material 3 components."
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 25
+    }
+    namespace "androidx.wear.compose.material3.demos"
+}
\ No newline at end of file
diff --git a/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
new file mode 100644
index 0000000..6492902
--- /dev/null
+++ b/wear/compose/compose-material3/integration-tests/src/main/java/androidx/wear/compose/material3/demos/WearMaterial3Demos.kt
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.wear.compose.material3.demos
+
+import androidx.wear.compose.integration.demos.common.DemoCategory
+
+val WearMaterial3Demos = DemoCategory(
+    "Material3",
+    listOf(
+        DemoCategory(
+            "ScrollAway",
+            listOf(
+                // Add Material 3 demos here
+            )
+        ),
+    )
+)
\ No newline at end of file
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
index 7503da4..4523dc5 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/Button.kt
@@ -803,8 +803,8 @@
     fun outlinedButtonBorder(
         enabled: Boolean,
         borderColor: Color = MaterialTheme.colorScheme.outline,
-        disabledBorderColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = DisabledBorderAndContainerAlpha
+        disabledBorderColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor(
+            disabledAlpha = DisabledBorderAndContainerAlpha
         ),
         borderWidth: Dp = 1.dp
     ): BorderStroke {
@@ -853,18 +853,13 @@
         contentColor: Color = contentColorFor(containerColor),
         secondaryContentColor: Color = contentColor,
         iconColor: Color = contentColor,
-        disabledContainerColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = DisabledBorderAndContainerAlpha
+        disabledContainerColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor(
+            disabledAlpha = DisabledBorderAndContainerAlpha
         ),
-        disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = ContentAlpha.disabled
-        ),
-        disabledSecondaryContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = ContentAlpha.disabled
-        ),
-        disabledIconColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = ContentAlpha.disabled
-        ),
+        disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor(),
+        disabledSecondaryContentColor: Color =
+            MaterialTheme.colorScheme.onSurface.toDisabledColor(),
+        disabledIconColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor()
     ): ButtonColors = ButtonColors(
         containerColor = containerColor,
         contentColor = contentColor,
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt
index 1216db9..1ee0789 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/ColorScheme.kt
@@ -454,3 +454,11 @@
 }
 
 internal val LocalColors = staticCompositionLocalOf<ColorScheme> { ColorScheme() }
+
+/**
+ * Convert given color to disabled color.
+ * @param disabledAlpha Alpha used to represent disabled colors.
+ */
+@Composable
+internal fun Color.toDisabledColor(disabledAlpha: Float = ContentAlpha.disabled) =
+    this.copy(alpha = this.alpha * disabledAlpha)
diff --git a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt
index d4b2a43..75dd372 100644
--- a/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt
+++ b/wear/compose/compose-material3/src/commonMain/kotlin/androidx/wear/compose/material3/IconButton.kt
@@ -332,12 +332,10 @@
     fun iconButtonColors(
         containerColor: Color = Color.Transparent,
         contentColor: Color = MaterialTheme.colorScheme.onBackground,
-        disabledContainerColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = DisabledBorderAndContainerAlpha
+        disabledContainerColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor(
+            disabledAlpha = DisabledBorderAndContainerAlpha
         ),
-        disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = ContentAlpha.disabled
-        )
+        disabledContentColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor()
     ): IconButtonColors = IconButtonColors(
         containerColor = containerColor,
         contentColor = contentColor,
@@ -359,8 +357,8 @@
     fun outlinedIconButtonBorder(
         enabled: Boolean,
         borderColor: Color = MaterialTheme.colorScheme.outline,
-        disabledBorderColor: Color = MaterialTheme.colorScheme.onSurface.copy(
-            alpha = DisabledBorderAndContainerAlpha
+        disabledBorderColor: Color = MaterialTheme.colorScheme.onSurface.toDisabledColor(
+            disabledAlpha = DisabledBorderAndContainerAlpha
         ),
         borderWidth: Dp = 1.dp
     ): BorderStroke {
diff --git a/wear/compose/integration-tests/demos/build.gradle b/wear/compose/integration-tests/demos/build.gradle
index 478b99e..0d46a1e 100644
--- a/wear/compose/integration-tests/demos/build.gradle
+++ b/wear/compose/integration-tests/demos/build.gradle
@@ -63,6 +63,8 @@
     implementation(project(":wear:compose:compose-foundation-samples"))
     implementation(project(':wear:compose:compose-material'))
     implementation(project(":wear:compose:compose-material-samples"))
+    implementation(project(':wear:compose:integration-tests:demos:common'))
+    implementation(project(":wear:compose:compose-material3-integration-tests"))
 
     androidTestImplementation(project(":compose:ui:ui-test-junit4"))
     androidTestImplementation(project(":emoji2:emoji2"))
diff --git a/wear/compose/integration-tests/demos/common/build.gradle b/wear/compose/integration-tests/demos/common/build.gradle
new file mode 100644
index 0000000..9e6cd01e
--- /dev/null
+++ b/wear/compose/integration-tests/demos/common/build.gradle
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2023 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.
+ */
+
+plugins {
+    id("AndroidXPlugin")
+    id("AndroidXComposePlugin")
+    id("com.android.library")
+    id("org.jetbrains.kotlin.android")
+}
+
+dependencies {
+    implementation(libs.kotlinStdlib)
+
+    api("androidx.activity:activity:1.2.0")
+    implementation(project(':wear:compose:compose-material'))
+
+}
+
+android {
+    defaultConfig {
+        minSdkVersion 25
+    }
+    namespace "androidx.wear.compose.integration.demos.common"
+}
diff --git a/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt
new file mode 100644
index 0000000..52a987a
--- /dev/null
+++ b/wear/compose/integration-tests/demos/common/src/main/java/androidx/wear/compose/integration/demos/common/Demo.kt
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.wear.compose.integration.demos.common
+
+import android.app.Activity
+import androidx.activity.ComponentActivity
+import androidx.compose.runtime.Composable
+import androidx.wear.compose.material.SwipeToDismissBoxState
+import kotlin.reflect.KClass
+
+/**
+ * Generic demo with a [title] that will be displayed in the list of demos.
+ */
+sealed class Demo(val title: String, val description: String? = null) {
+    override fun toString() = title
+}
+
+/**
+ * Demo that launches an [Activity] when selected.
+ *
+ * This should only be used for demos that need to customize the activity, the large majority of
+ * demos should just use [ComposableDemo] instead.
+ *
+ * @property activityClass the KClass (Foo::class) of the activity that will be launched when
+ * this demo is selected.
+ */
+class ActivityDemo<T : ComponentActivity>(title: String, val activityClass: KClass<T>) : Demo(title)
+
+/**
+ * A category of [Demo]s, that will display a list of [demos] when selected.
+ */
+class DemoCategory(
+    title: String,
+    val demos: List<Demo>
+) : Demo(title)
+
+/**
+ * Parameters which are used by [Demo] screens.
+ */
+class DemoParameters(
+    val navigateBack: () -> Unit,
+    val swipeToDismissBoxState: SwipeToDismissBoxState
+)
+
+/**
+ * Demo that displays [Composable] [content] when selected,
+ * with a method to navigate back to the parent.
+ */
+class ComposableDemo(
+    title: String,
+    description: String? = null,
+    val content: @Composable (params: DemoParameters) -> Unit,
+) : Demo(title, description)
diff --git a/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt b/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
index 9fe82bca..646addf 100644
--- a/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
+++ b/wear/compose/integration-tests/demos/src/androidTest/java/androidx/wear/compose/integration/demos/test/DemoTest.kt
@@ -28,10 +28,10 @@
 import androidx.test.espresso.Espresso
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
-import androidx.wear.compose.integration.demos.Demo
 import androidx.wear.compose.integration.demos.DemoActivity
-import androidx.wear.compose.integration.demos.DemoCategory
 import androidx.wear.compose.integration.demos.WearComposeDemos
+import androidx.wear.compose.integration.demos.common.Demo
+import androidx.wear.compose.integration.demos.common.DemoCategory
 import com.google.common.truth.Truth.assertThat
 import org.junit.Ignore
 import org.junit.Rule
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
index 361fb0e..7de734f 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoActivity.kt
@@ -36,6 +36,9 @@
 import androidx.compose.ui.platform.LocalFocusManager
 import androidx.compose.ui.platform.LocalView
 import androidx.core.app.ActivityCompat
+import androidx.wear.compose.integration.demos.common.ActivityDemo
+import androidx.wear.compose.integration.demos.common.Demo
+import androidx.wear.compose.integration.demos.common.DemoCategory
 import androidx.wear.compose.material.MaterialTheme
 
 /**
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
index 108b9ad..7e6aa69 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoApp.kt
@@ -32,7 +32,6 @@
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Alignment
-import androidx.compose.ui.ExperimentalComposeUiApi
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.composed
 import androidx.compose.ui.focus.FocusRequester
@@ -49,6 +48,11 @@
 import androidx.wear.compose.foundation.lazy.ScalingLazyListState
 import androidx.wear.compose.foundation.lazy.ScalingParams
 import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
+import androidx.wear.compose.integration.demos.common.ActivityDemo
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.integration.demos.common.Demo
+import androidx.wear.compose.integration.demos.common.DemoCategory
+import androidx.wear.compose.integration.demos.common.DemoParameters
 import androidx.wear.compose.material.Chip
 import androidx.wear.compose.material.ChipDefaults
 import androidx.wear.compose.material.ListHeader
@@ -154,13 +158,13 @@
                     modifier = Modifier.fillMaxWidth()
                 )
             }
-            if (demo.description != null) {
+            demo.description?.let { description ->
                 item {
                     CompositionLocalProvider(
                         LocalTextStyle provides MaterialTheme.typography.caption3
                     ) {
                         Text(
-                            text = demo.description,
+                            text = description,
                             modifier = Modifier.fillMaxWidth().align(Alignment.Center),
                             textAlign = TextAlign.Center
                         )
@@ -187,7 +191,6 @@
 
 internal data class TimestampedDelta(val time: Long, val delta: Float)
 
-@OptIn(ExperimentalComposeUiApi::class)
 @Suppress("ComposableModifierFactory")
 @Composable
 fun Modifier.rsbScroll(
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
index ea5174c..4876340 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/DemoComponents.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2021 The Android Open Source Project
+ * Copyright 2023 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.
@@ -16,8 +16,6 @@
 
 package androidx.wear.compose.integration.demos
 
-import android.app.Activity
-import androidx.activity.ComponentActivity
 import androidx.compose.foundation.Image
 import androidx.compose.foundation.layout.Arrangement
 import androidx.compose.foundation.layout.Box
@@ -43,53 +41,7 @@
 import androidx.wear.compose.material.Icon
 import androidx.wear.compose.material.LocalContentAlpha
 import androidx.wear.compose.material.MaterialTheme
-import androidx.wear.compose.material.SwipeToDismissBoxState
 import androidx.wear.compose.material.Text
-import kotlin.reflect.KClass
-
-/**
- * Generic demo with a [title] that will be displayed in the list of demos.
- */
-sealed class Demo(val title: String, val description: String? = null) {
-    override fun toString() = title
-}
-
-/**
- * Demo that launches an [Activity] when selected.
- *
- * This should only be used for demos that need to customize the activity, the large majority of
- * demos should just use [ComposableDemo] instead.
- *
- * @property activityClass the KClass (Foo::class) of the activity that will be launched when
- * this demo is selected.
- */
-class ActivityDemo<T : ComponentActivity>(title: String, val activityClass: KClass<T>) : Demo(title)
-
-/**
- * A category of [Demo]s, that will display a list of [demos] when selected.
- */
-class DemoCategory(
-    title: String,
-    val demos: List<Demo>
-) : Demo(title)
-
-/**
- * Parameters which are used by [Demo] screens.
- */
-class DemoParameters(
-    val navigateBack: () -> Unit,
-    val swipeToDismissBoxState: SwipeToDismissBoxState
-)
-
-/**
- * Demo that displays [Composable] [content] when selected,
- * with a method to navigate back to the parent.
- */
-class ComposableDemo(
-    title: String,
-    description: String? = null,
-    val content: @Composable (params: DemoParameters) -> Unit,
-) : Demo(title, description)
 
 /**
  * A simple [Icon] with default size
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
index 6fa889e..8efc582 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/Demos.kt
@@ -23,7 +23,10 @@
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalContext
 import androidx.compose.ui.text.style.TextAlign
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.integration.demos.common.DemoCategory
 import androidx.wear.compose.material.Text
+import androidx.wear.compose.material3.demos.WearMaterial3Demos
 
 val Info = DemoCategory(
     "App Info",
@@ -56,6 +59,7 @@
     listOf(
         WearFoundationDemos,
         WearMaterialDemos,
+        WearMaterial3Demos,
         Info
     )
 )
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
index c54950a..730a272 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/FoundationDemos.kt
@@ -34,6 +34,8 @@
 import androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithContentPadding
 import androidx.wear.compose.foundation.samples.SimpleScalingLazyColumnWithSnap
 import androidx.wear.compose.foundation.samples.SwipeToRevealWithExpandables
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.integration.demos.common.DemoCategory
 
 val WearFoundationDemos = DemoCategory(
     "Foundation",
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
index 205da0d..82d84b9 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/MaterialDemos.kt
@@ -27,6 +27,8 @@
 import androidx.compose.ui.graphics.Color
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.integration.demos.common.ComposableDemo
+import androidx.wear.compose.integration.demos.common.DemoCategory
 import androidx.wear.compose.material.samples.AlertDialogSample
 import androidx.wear.compose.material.samples.AlertWithButtons
 import androidx.wear.compose.material.samples.AlertWithChips
diff --git a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollingWithRotaryInputDemo.kt b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollingWithRotaryInputDemo.kt
index 7153372..33c1b57 100644
--- a/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollingWithRotaryInputDemo.kt
+++ b/wear/compose/integration-tests/demos/src/main/java/androidx/wear/compose/integration/demos/ScrollingWithRotaryInputDemo.kt
@@ -26,6 +26,7 @@
 import androidx.compose.ui.samples.PreRotaryEventSample
 import androidx.compose.ui.samples.RotaryEventSample
 import androidx.compose.ui.unit.dp
+import androidx.wear.compose.integration.demos.common.ComposableDemo
 import androidx.wear.compose.material.Text
 
 internal val RotaryInputDemos = listOf(
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
index 5893701..1d69a87 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/Int32Nodes.java
@@ -26,8 +26,8 @@
 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32;
 import androidx.wear.protolayout.expression.DynamicDataKey;
 import androidx.wear.protolayout.expression.PlatformHealthSources;
-import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
 import androidx.wear.protolayout.expression.proto.AnimationParameterProto.AnimationSpec;
+import androidx.wear.protolayout.expression.proto.DynamicDataProto.DynamicDataValue;
 import androidx.wear.protolayout.expression.proto.DynamicProto.AnimatableFixedInt32;
 import androidx.wear.protolayout.expression.proto.DynamicProto.ArithmeticInt32Op;
 import androidx.wear.protolayout.expression.proto.DynamicProto.DurationPartType;
@@ -39,6 +39,7 @@
 import androidx.wear.protolayout.expression.proto.FixedProto.FixedInt32;
 
 import java.time.Duration;
+import java.util.function.Function;
 
 /** Dynamic data nodes which yield integers. */
 class Int32Nodes {
@@ -83,7 +84,7 @@
             super(
                     stateStore,
                     getDataKey(protoNode.getSourceType()),
-                    se -> se.getInt32Val().getValue(),
+                    getStateExtractor(protoNode.getSourceType()),
                     downstream);
         }
 
@@ -100,6 +101,21 @@
             throw new IllegalArgumentException(
                     "Unknown DynamicInt32 platform source type: " + type);
         }
+
+        @NonNull
+        private static Function<DynamicDataValue, Integer> getStateExtractor(
+                PlatformInt32SourceType type) {
+            if (type == PlatformInt32SourceType.PLATFORM_INT32_SOURCE_TYPE_CURRENT_HEART_RATE) {
+                return se -> (int) se.getFloatVal().getValue();
+            }
+
+            if (type == PlatformInt32SourceType.PLATFORM_INT32_SOURCE_TYPE_DAILY_STEP_COUNT) {
+                return se -> se.getInt32Val().getValue();
+            }
+
+            throw new IllegalArgumentException(
+                    "Unknown DynamicInt32 platform source type: " + type);
+        }
     }
 
     /** Dynamic integer node that supports arithmetic operations. */
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/SensorGatewaySingleDataProvider.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/SensorGatewaySingleDataProvider.java
index ee1671e..564bab1 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/SensorGatewaySingleDataProvider.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/SensorGatewaySingleDataProvider.java
@@ -22,11 +22,13 @@
 import androidx.annotation.RestrictTo.Scope;
 import androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue;
 import androidx.wear.protolayout.expression.PlatformDataKey;
+import androidx.wear.protolayout.expression.PlatformHealthSources;
 import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
 
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.function.Function;
 
 /** This provider provides sensor data as state value. */
 @RestrictTo(Scope.LIBRARY_GROUP_PREFIX)
@@ -35,12 +37,20 @@
     @NonNull final PlatformDataKey<?> mSupportedKey;
     @Nullable private SensorGateway.Consumer mSensorGatewayConsumer = null;
 
+    @NonNull Function<Double, DynamicDataValue> mConvertFunc;
+
     public SensorGatewaySingleDataProvider(
             @NonNull SensorGateway sensorGateway,
             @NonNull PlatformDataKey<?> supportedKey
     ) {
         this.mSensorGateway = sensorGateway;
         this.mSupportedKey = supportedKey;
+
+        if (mSupportedKey.equals(PlatformHealthSources.HEART_RATE_BPM)) {
+            mConvertFunc = value -> DynamicDataValue.fromFloat(value.floatValue());
+        } else { // mSupportedKey.equals(PlatformHealthSources.DAILY_STEPS)
+            mConvertFunc = value -> DynamicDataValue.fromInt(value.intValue());
+        }
     }
 
     @Override
@@ -52,7 +62,7 @@
                     @Override
                     public void onData(double value) {
                         executor.execute(() -> callback.onData(
-                                Map.of(mSupportedKey, DynamicDataValue.fromFloat((float) value)))
+                                Map.of(mSupportedKey, mConvertFunc.apply(value)))
                         );
                     }
 
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/StateSourceNode.java b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/StateSourceNode.java
index 1cd0634..ef45da0 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/StateSourceNode.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/main/java/androidx/wear/protolayout/expression/pipeline/StateSourceNode.java
@@ -29,6 +29,7 @@
 class StateSourceNode<T>
         implements DynamicDataSourceNode<T>,
         DynamicTypeValueReceiverWithPreUpdate<DynamicDataValue> {
+    @NonNull private static final String RESERVED_NAMESPACE = "protolayout";
     private final StateStore mStateStore;
     private final DynamicDataKey<?> mKey;
     private final Function<DynamicDataValue, T> mStateExtractor;
@@ -92,6 +93,11 @@
         if (namespace.isEmpty()) {
             return new AppDataKey<T>(key);
         }
+
+        if (RESERVED_NAMESPACE.equalsIgnoreCase(namespace)) {
+            return new PlatformDataKey<T>(key);
+        }
+
         return new PlatformDataKey<T>(namespace, key);
     }
 }
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FakeSensorGateway.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FakeSensorGateway.java
new file mode 100644
index 0000000..c661e3f
--- /dev/null
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FakeSensorGateway.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 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.
+ */
+
+package androidx.wear.protolayout.expression.pipeline;
+
+import androidx.annotation.NonNull;
+import androidx.wear.protolayout.expression.PlatformDataKey;
+import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+class FakeSensorGateway implements SensorGateway {
+    final List<Consumer> registeredConsumers = new ArrayList<>();
+
+    @Override
+    public void enableUpdates() {
+    }
+
+    @Override
+    public void disableUpdates() {
+    }
+
+    @Override
+    public void registerSensorGatewayConsumer(
+            @NonNull PlatformDataKey<?> key, @NonNull Consumer consumer) {
+        registeredConsumers.add(consumer);
+    }
+
+    @Override
+    public void registerSensorGatewayConsumer(
+            @NonNull PlatformDataKey<?> key,
+            @NonNull Executor executor,
+            @NonNull Consumer consumer) {
+        registerSensorGatewayConsumer(key, consumer);
+    }
+
+    @Override
+    public void unregisterSensorGatewayConsumer(
+            @NonNull PlatformDataKey<?> key, @NonNull Consumer consumer) {
+        registeredConsumers.remove(consumer);
+    }
+}
\ No newline at end of file
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FloatNodeTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FloatNodeTest.java
index a1acb98..4f2b87a 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FloatNodeTest.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/FloatNodeTest.java
@@ -24,9 +24,11 @@
 
 import android.os.Looper;
 
+import androidx.collection.ArrayMap;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat;
 import androidx.wear.protolayout.expression.AppDataKey;
+import androidx.wear.protolayout.expression.PlatformHealthSources;
 import androidx.wear.protolayout.expression.pipeline.FloatNodes.AnimatableFixedFloatNode;
 import androidx.wear.protolayout.expression.pipeline.FloatNodes.ArithmeticFloatNode;
 import androidx.wear.protolayout.expression.pipeline.FloatNodes.DynamicAnimatedFloatNode;
@@ -51,6 +53,7 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
 @RunWith(AndroidJUnit4.class)
@@ -127,6 +130,40 @@
     }
 
     @Test
+    public void stateFloatSource_canSubscribeToHeartRateUpdates() {
+        FakeSensorGateway fakeSensorGateway = new FakeSensorGateway();
+        StateStore stateStore = new StateStore(new ArrayMap<>());
+        stateStore.putAllPlatformProviders(
+                Collections.singletonMap(
+                        PlatformHealthSources.HEART_RATE_BPM,
+                        new SensorGatewaySingleDataProvider(
+                                fakeSensorGateway, PlatformHealthSources.HEART_RATE_BPM)));
+        StateFloatSource dailyStepsSource =
+                StateFloatSource.newBuilder()
+                        .setSourceKey(PlatformHealthSources.HEART_RATE_BPM.getKey())
+                        .setSourceNamespace(PlatformHealthSources.HEART_RATE_BPM.getNamespace())
+                        .build();
+        List<Float> results = new ArrayList<>();
+        StateFloatSourceNode dailyStepsSourceNode =
+                new StateFloatSourceNode(
+                        stateStore,
+                        dailyStepsSource,
+                        new AddToListCallback<>(results));
+
+        dailyStepsSourceNode.preInit();
+        dailyStepsSourceNode.init();
+        assertThat(fakeSensorGateway.registeredConsumers).hasSize(1);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(70.0);
+        assertThat(results).hasSize(1);
+        assertThat(results).containsExactly(70.0f);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(80.0);
+        assertThat(results).hasSize(2);
+        assertThat(results).containsExactly(70.0f, 80.0f);
+    }
+
+    @Test
     public void stateFloatSourceNode_noUpdatesAfterDestroy() {
         List<Float> results = new ArrayList<>();
         float oldValue = 6.5f;
diff --git a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/Int32NodesTest.java b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/Int32NodesTest.java
index 2738f50..043eab7 100644
--- a/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/Int32NodesTest.java
+++ b/wear/protolayout/protolayout-expression-pipeline/src/test/java/androidx/wear/protolayout/expression/pipeline/Int32NodesTest.java
@@ -25,12 +25,10 @@
 
 import android.os.Looper;
 
-import androidx.annotation.NonNull;
 import androidx.collection.ArrayMap;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.wear.protolayout.expression.AppDataKey;
 import androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32;
-import androidx.wear.protolayout.expression.PlatformDataKey;
 import androidx.wear.protolayout.expression.PlatformHealthSources;
 import androidx.wear.protolayout.expression.pipeline.Int32Nodes.AnimatableFixedInt32Node;
 import androidx.wear.protolayout.expression.pipeline.Int32Nodes.DynamicAnimatedInt32Node;
@@ -38,7 +36,6 @@
 import androidx.wear.protolayout.expression.pipeline.Int32Nodes.GetDurationPartOpNode;
 import androidx.wear.protolayout.expression.pipeline.Int32Nodes.LegacyPlatformInt32SourceNode;
 import androidx.wear.protolayout.expression.pipeline.Int32Nodes.StateInt32SourceNode;
-import androidx.wear.protolayout.expression.pipeline.sensor.SensorGateway;
 import androidx.wear.protolayout.expression.proto.AnimationParameterProto.AnimationSpec;
 import androidx.wear.protolayout.expression.proto.DynamicProto.AnimatableFixedInt32;
 import androidx.wear.protolayout.expression.proto.DynamicProto.DurationPartType;
@@ -230,6 +227,40 @@
     }
 
     @Test
+    public void stateInt32Source_canSubscribeToDailyStepsUpdates() {
+        FakeSensorGateway fakeSensorGateway = new FakeSensorGateway();
+        StateStore stateStore = new StateStore(new ArrayMap<>());
+        stateStore.putAllPlatformProviders(
+                Collections.singletonMap(
+                        PlatformHealthSources.DAILY_STEPS,
+                        new SensorGatewaySingleDataProvider(
+                                fakeSensorGateway, PlatformHealthSources.DAILY_STEPS)));
+        StateInt32Source dailyStepsSource =
+                StateInt32Source.newBuilder()
+                        .setSourceKey(PlatformHealthSources.DAILY_STEPS.getKey())
+                        .setSourceNamespace(PlatformHealthSources.DAILY_STEPS.getNamespace())
+                        .build();
+        List<Integer> results = new ArrayList<>();
+        StateInt32SourceNode dailyStepsSourceNode =
+                new StateInt32SourceNode(
+                        stateStore,
+                        dailyStepsSource,
+                        new AddToListCallback<>(results));
+
+        dailyStepsSourceNode.preInit();
+        dailyStepsSourceNode.init();
+        assertThat(fakeSensorGateway.registeredConsumers).hasSize(1);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(70);
+        assertThat(results).hasSize(1);
+        assertThat(results).containsExactly(70);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(80);
+        assertThat(results).hasSize(2);
+        assertThat(results).containsExactly(70, 80);
+    }
+
+    @Test
     public void animatableFixedInt32_animates() {
         int startValue = 3;
         int endValue = 33;
@@ -363,6 +394,76 @@
     }
 
     @Test
+    public void platformInt32Source_canSubscribeToHeartRateUpdates() {
+        FakeSensorGateway fakeSensorGateway = new FakeSensorGateway();
+        StateStore stateStore = new StateStore(new ArrayMap<>());
+        stateStore.putAllPlatformProviders(
+                Collections.singletonMap(
+                        PlatformHealthSources.HEART_RATE_BPM,
+                        new SensorGatewaySingleDataProvider(
+                                fakeSensorGateway, PlatformHealthSources.HEART_RATE_BPM)));
+        PlatformInt32Source platformSource =
+                PlatformInt32Source.newBuilder()
+                        .setSourceType(
+                                PlatformInt32SourceType
+                                        .PLATFORM_INT32_SOURCE_TYPE_CURRENT_HEART_RATE)
+                        .build();
+        List<Integer> results = new ArrayList<>();
+        LegacyPlatformInt32SourceNode platformSourceNode =
+                new LegacyPlatformInt32SourceNode(
+                        stateStore,
+                        platformSource,
+                        new AddToListCallback<>(results));
+
+        platformSourceNode.preInit();
+        platformSourceNode.init();
+        assertThat(fakeSensorGateway.registeredConsumers).hasSize(1);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(70);
+        assertThat(results).hasSize(1);
+        assertThat(results).containsExactly(70);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(80);
+        assertThat(results).hasSize(2);
+        assertThat(results).containsExactly(70, 80);
+    }
+
+    @Test
+    public void platformInt32Source_canSubscribeToDailyStepsUpdates() {
+        FakeSensorGateway fakeSensorGateway = new FakeSensorGateway();
+        StateStore stateStore = new StateStore(new ArrayMap<>());
+        stateStore.putAllPlatformProviders(
+                Collections.singletonMap(
+                        PlatformHealthSources.DAILY_STEPS,
+                        new SensorGatewaySingleDataProvider(
+                                fakeSensorGateway, PlatformHealthSources.DAILY_STEPS)));
+        PlatformInt32Source platformSource =
+                PlatformInt32Source.newBuilder()
+                        .setSourceType(
+                                PlatformInt32SourceType
+                                        .PLATFORM_INT32_SOURCE_TYPE_DAILY_STEP_COUNT)
+                        .build();
+        List<Integer> results = new ArrayList<>();
+        LegacyPlatformInt32SourceNode platformSourceNode =
+                new LegacyPlatformInt32SourceNode(
+                        stateStore,
+                        platformSource,
+                        new AddToListCallback<>(results));
+
+        platformSourceNode.preInit();
+        platformSourceNode.init();
+        assertThat(fakeSensorGateway.registeredConsumers).hasSize(1);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(70.0);
+        assertThat(results).hasSize(1);
+        assertThat(results).containsExactly(70);
+
+        fakeSensorGateway.registeredConsumers.get(0).onData(80.0);
+        assertThat(results).hasSize(2);
+        assertThat(results).containsExactly(70, 80);
+    }
+
+    @Test
     public void platformInt32Source_propagatesInvalidatedSignal() {
         FakeSensorGateway fakeSensorGateway = new FakeSensorGateway();
         StateStore stateStore = new StateStore(new ArrayMap<>());
@@ -392,36 +493,4 @@
         fakeSensorGateway.registeredConsumers.get(0).onInvalidated();
         verify(mMockValueReceiver).onInvalidated();
     }
-
-    private static class FakeSensorGateway implements SensorGateway {
-        final List<Consumer> registeredConsumers = new ArrayList<>();
-
-        @Override
-        public void enableUpdates() {
-        }
-
-        @Override
-        public void disableUpdates() {
-        }
-
-        @Override
-        public void registerSensorGatewayConsumer(
-                @NonNull PlatformDataKey<?> key, @NonNull Consumer consumer) {
-            registeredConsumers.add(consumer);
-        }
-
-        @Override
-        public void registerSensorGatewayConsumer(
-                @NonNull PlatformDataKey<?> key,
-                @NonNull Executor executor,
-                @NonNull Consumer consumer) {
-            registerSensorGatewayConsumer(key, consumer);
-        }
-
-        @Override
-        public void unregisterSensorGatewayConsumer(
-                @NonNull PlatformDataKey<?> key, @NonNull Consumer consumer) {
-            registeredConsumers.remove(consumer);
-        }
-    }
 }
diff --git a/wear/protolayout/protolayout-expression/api/current.txt b/wear/protolayout/protolayout-expression/api/current.txt
index 7f2e9cb..1ca79e0 100644
--- a/wear/protolayout/protolayout-expression/api/current.txt
+++ b/wear/protolayout/protolayout-expression/api/current.txt
@@ -104,10 +104,13 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool negate();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool or(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicBoolByteArray();
+    method public default int toDynamicBoolByteArray(byte[]);
+    method public default int toDynamicBoolByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicColor extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
@@ -120,18 +123,24 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor constant(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicColorByteArray();
+    method public default int toDynamicColorByteArray(byte[]);
+    method public default int toDynamicColorByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!,java.time.Duration!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicDurationByteArray();
+    method public default int toDynamicDurationByteArray(byte[]);
+    method public default int toDynamicDurationByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
@@ -157,6 +166,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
@@ -181,6 +191,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default byte[] toDynamicFloatByteArray();
+    method public default int toDynamicFloatByteArray(byte[]);
+    method public default int toDynamicFloatByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicFloat.FloatFormatter {
@@ -202,9 +214,12 @@
   public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!,java.time.Instant!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
     method public default byte[] toDynamicInstantByteArray();
+    method public default int toDynamicInstantByteArray(byte[]);
+    method public default int toDynamicInstantByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
   }
 
@@ -227,6 +242,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
@@ -255,6 +271,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default byte[] toDynamicInt32ByteArray();
+    method public default int toDynamicInt32ByteArray(byte[]);
+    method public default int toDynamicInt32ByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicInt32.IntFormatter {
@@ -274,8 +292,11 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString constant(String);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!,java.lang.String!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicStringByteArray();
+    method public default int toDynamicStringByteArray(byte[]);
+    method public default int toDynamicStringByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicType {
@@ -286,10 +307,15 @@
 
   public static interface DynamicDataBuilders.DynamicDataValue {
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromBool(boolean);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromColor(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromFloat(float);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromInt(int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromString(String);
+    method public default byte[] toDynamicDataValueByteArray();
+    method public default int toDynamicDataValueByteArray(byte[]);
+    method public default int toDynamicDataValueByteArray(byte[], int, int);
   }
 
   public abstract class DynamicDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
diff --git a/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt b/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
index ace5549..ba0d81d 100644
--- a/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
+++ b/wear/protolayout/protolayout-expression/api/public_plus_experimental_current.txt
@@ -104,10 +104,13 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool negate();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool or(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicBoolByteArray();
+    method public default int toDynamicBoolByteArray(byte[]);
+    method public default int toDynamicBoolByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicColor extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
@@ -120,18 +123,24 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor constant(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicColorByteArray();
+    method public default int toDynamicColorByteArray(byte[]);
+    method public default int toDynamicColorByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!,java.time.Duration!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicDurationByteArray();
+    method public default int toDynamicDurationByteArray(byte[]);
+    method public default int toDynamicDurationByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
@@ -157,6 +166,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
@@ -181,6 +191,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default byte[] toDynamicFloatByteArray();
+    method public default int toDynamicFloatByteArray(byte[]);
+    method public default int toDynamicFloatByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicFloat.FloatFormatter {
@@ -202,9 +214,12 @@
   public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!,java.time.Instant!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
     method public default byte[] toDynamicInstantByteArray();
+    method public default int toDynamicInstantByteArray(byte[]);
+    method public default int toDynamicInstantByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
   }
 
@@ -227,6 +242,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
@@ -255,6 +271,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default byte[] toDynamicInt32ByteArray();
+    method public default int toDynamicInt32ByteArray(byte[]);
+    method public default int toDynamicInt32ByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicInt32.IntFormatter {
@@ -274,8 +292,11 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString constant(String);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!,java.lang.String!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicStringByteArray();
+    method public default int toDynamicStringByteArray(byte[]);
+    method public default int toDynamicStringByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicType {
@@ -286,10 +307,15 @@
 
   public static interface DynamicDataBuilders.DynamicDataValue {
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromBool(boolean);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromColor(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromFloat(float);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromInt(int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromString(String);
+    method public default byte[] toDynamicDataValueByteArray();
+    method public default int toDynamicDataValueByteArray(byte[]);
+    method public default int toDynamicDataValueByteArray(byte[], int, int);
   }
 
   public abstract class DynamicDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
diff --git a/wear/protolayout/protolayout-expression/api/restricted_current.txt b/wear/protolayout/protolayout-expression/api/restricted_current.txt
index 7f2e9cb..1ca79e0 100644
--- a/wear/protolayout/protolayout-expression/api/restricted_current.txt
+++ b/wear/protolayout/protolayout-expression/api/restricted_current.txt
@@ -104,10 +104,13 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool eq(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool ne(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool negate();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool or(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicBoolByteArray();
+    method public default int toDynamicBoolByteArray(byte[]);
+    method public default int toDynamicBoolByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicColor extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
@@ -120,18 +123,24 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor constant(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicColor!,java.lang.Integer!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicColorByteArray();
+    method public default int toDynamicColorByteArray(byte[]);
+    method public default int toDynamicColorByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicDuration extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getHoursPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getIntDaysPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getMinutesPart();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 getSecondsPart();
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration!,java.time.Duration!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicDurationByteArray();
+    method public default int toDynamicDurationByteArray(byte[]);
+    method public default int toDynamicDurationByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntDays();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntHours();
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 toIntMinutes();
@@ -157,6 +166,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat.FloatFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat);
@@ -181,6 +191,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default byte[] toDynamicFloatByteArray();
+    method public default int toDynamicFloatByteArray(byte[]);
+    method public default int toDynamicFloatByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicFloat.FloatFormatter {
@@ -202,9 +214,12 @@
   public static interface DynamicBuilders.DynamicInstant extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType {
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicDuration durationUntil(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant!,java.time.Instant!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant platformTimeWithSecondsPrecision();
     method public default byte[] toDynamicInstantByteArray();
+    method public default int toDynamicInstantByteArray(byte[]);
+    method public default int toDynamicInstantByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInstant withSecondsPrecision(java.time.Instant);
   }
 
@@ -227,6 +242,7 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicString format(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32.IntFormatter);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 fromByteArray(byte[], int, int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gt(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool gte(androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32);
@@ -255,6 +271,8 @@
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicInt32 times(int);
     method public default androidx.wear.protolayout.expression.DynamicBuilders.DynamicFloat times(float);
     method public default byte[] toDynamicInt32ByteArray();
+    method public default int toDynamicInt32ByteArray(byte[]);
+    method public default int toDynamicInt32ByteArray(byte[], int, int);
   }
 
   public static class DynamicBuilders.DynamicInt32.IntFormatter {
@@ -274,8 +292,11 @@
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString constant(String);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString from(androidx.wear.protolayout.expression.DynamicDataKey<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!>);
     method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicBuilders.DynamicString fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.ConditionScopes.ConditionScope<androidx.wear.protolayout.expression.DynamicBuilders.DynamicString!,java.lang.String!> onCondition(androidx.wear.protolayout.expression.DynamicBuilders.DynamicBool);
     method public default byte[] toDynamicStringByteArray();
+    method public default int toDynamicStringByteArray(byte[]);
+    method public default int toDynamicStringByteArray(byte[], int, int);
   }
 
   public static interface DynamicBuilders.DynamicType {
@@ -286,10 +307,15 @@
 
   public static interface DynamicDataBuilders.DynamicDataValue {
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromBool(boolean);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[]);
+    method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromByteArray(byte[], int, int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromColor(@ColorInt int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromFloat(float);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromInt(int);
     method public static androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue fromString(String);
+    method public default byte[] toDynamicDataValueByteArray();
+    method public default int toDynamicDataValueByteArray(byte[]);
+    method public default int toDynamicDataValueByteArray(byte[], int, int);
   }
 
   public abstract class DynamicDataKey<T extends androidx.wear.protolayout.expression.DynamicBuilders.DynamicType> {
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
index 162b840..284104c 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicBuilders.java
@@ -38,9 +38,11 @@
 import androidx.wear.protolayout.expression.FixedValueBuilders.FixedString;
 import androidx.wear.protolayout.expression.DynamicDataBuilders.DynamicDataValue;
 import androidx.wear.protolayout.expression.proto.DynamicProto;
+import androidx.wear.protolayout.protobuf.CodedInputStream;
+import androidx.wear.protolayout.protobuf.CodedOutputStream;
 import androidx.wear.protolayout.protobuf.ExtensionRegistryLite;
-import androidx.wear.protolayout.protobuf.InvalidProtocolBufferException;
 
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.time.Duration;
@@ -1506,25 +1508,72 @@
         /**
          * Creates a {@link DynamicInt32} from a byte array generated by {@link
          * #toDynamicInt32ByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicInt32 fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicInt32} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicInt32ByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicInt32 fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicInt32FromProto(
                         DynamicProto.DynamicInt32.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicInt32", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicInt32} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicInt32ByteArray() {
             return toDynamicInt32Proto().toByteArray();
         }
 
+        /**
+         * Serializes the {@link DynamicInt32} into the provided byte array, returning the amount of
+         * bytes written, that can later be used with {@code DynamicInt32.fromByteArray(byteArray,
+         * 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicInt32ByteArray(@NonNull byte[] byteArray) {
+            return toDynamicInt32ByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicInt32} into the provided byte array, returning the amount of
+         * bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicInt32.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicInt32ByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicInt32Proto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicInt32", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
         /** Creates a constant-valued {@link DynamicInt32}. */
         @NonNull
         static DynamicInt32 constant(int constant) {
@@ -3283,26 +3332,73 @@
         /**
          * Creates a {@link DynamicString} from a byte array generated by {@link
          * #toDynamicStringByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicString fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicString} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicStringByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicString fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicStringFromProto(
                         DynamicProto.DynamicString.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicString", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicString} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicStringByteArray() {
             return toDynamicStringProto().toByteArray();
         }
 
         /**
+         * Serializes the {@link DynamicString} into the provided byte array, returning the amount
+         * of bytes written, that can later be used with {@code DynamicString.fromByteArray(
+         * byteArray, 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicStringByteArray(@NonNull byte[] byteArray) {
+            return toDynamicStringByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicString} into the provided byte array, returning the amount
+         * of bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicString.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicStringByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicStringProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicString", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
+        /**
          * Creates a constant-valued {@link DynamicString}. The resulted {@link DynamicString} is
          * subject to being truncated if it's too long.
          */
@@ -4081,26 +4177,73 @@
         /**
          * Creates a {@link DynamicFloat} from a byte array generated by {@link
          * #toDynamicFloatByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicFloat fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicFloat} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicFloatByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicFloat fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicFloatFromProto(
                         DynamicProto.DynamicFloat.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicFloat", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicFloat} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicFloatByteArray() {
             return toDynamicFloatProto().toByteArray();
         }
 
         /**
+         * Serializes the {@link DynamicFloat} into the provided byte array, returning the amount of
+         * bytes written, that can later be used with {@code DynamicFloat.fromByteArray(byteArray,
+         * 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicFloatByteArray(@NonNull byte[] byteArray) {
+            return toDynamicFloatByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicFloat} into the provided byte array, returning the amount of
+         * bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicFloat.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicFloatByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicFloatProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicFloat", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
+        /**
          * Creates a constant-valued {@link DynamicFloat}.
          *
          * <p>If {@code Float.isNan(constant)} is true, the value will be invalid. And any
@@ -5668,25 +5811,72 @@
         /**
          * Creates a {@link DynamicBool} from a byte array generated by {@link
          * #toDynamicBoolByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicBool fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicBool} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicBoolByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicBool fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicBoolFromProto(
                         DynamicProto.DynamicBool.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicBool", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicBool} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicBoolByteArray() {
             return toDynamicBoolProto().toByteArray();
         }
 
+        /**
+         * Serializes the {@link DynamicBool} into the provided byte array, returning the amount of
+         * bytes written, that can later be used with {@code DynamicBool.fromByteArray(byteArray, 0,
+         * bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicBoolByteArray(@NonNull byte[] byteArray) {
+            return toDynamicBoolByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicBool} into the provided byte array, returning the amount of
+         * bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicBool.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicBoolByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicBoolProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicBool", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
         /** Creates a constant-valued {@link DynamicBool}. */
         @NonNull
         static DynamicBool constant(boolean constant) {
@@ -6401,25 +6591,72 @@
         /**
          * Creates a {@link DynamicColor} from a byte array generated by {@link
          * #toDynamicColorByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicColor fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicColor} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicColorByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicColor fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicColorFromProto(
                         DynamicProto.DynamicColor.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicColor", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicColor} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicColorByteArray() {
             return toDynamicColorProto().toByteArray();
         }
 
+        /**
+         * Serializes the {@link DynamicColor} into the provided byte array, returning the amount of
+         * bytes written, that can later be used with {@code DynamicColor.fromByteArray(byteArray,
+         * 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicColorByteArray(@NonNull byte[] byteArray) {
+            return toDynamicColorByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicColor} into the provided byte array, returning the amount of
+         * bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicColor.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicColorByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicColorProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicColor", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
         /** Creates a constant-valued {@link DynamicColor}. */
         @NonNull
         static DynamicColor constant(@ColorInt int constant) {
@@ -6840,26 +7077,73 @@
         /**
          * Creates a {@link DynamicInstant} from a byte array generated by {@link
          * #toDynamicInstantByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicInstant fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicInstant} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicInstantByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicInstant fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicInstantFromProto(
                         DynamicProto.DynamicInstant.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicInstant", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicInstant} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicInstantByteArray() {
             return toDynamicInstantProto().toByteArray();
         }
 
         /**
+         * Serializes the {@link DynamicInstant} into the provided byte array, returning the amount
+         * of bytes written, that can later be used with {@code DynamicInstant.fromByteArray(
+         * byteArray, 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicInstantByteArray(@NonNull byte[] byteArray) {
+            return toDynamicInstantByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicInstant} into the provided byte array, returning the amount
+         * of bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicInstant.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicInstantByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicInstantProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicInstant", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
+        /**
          * Creates a constant-valued {@link DynamicInstant} from an {@link Instant}. If {@link
          * Instant} precision is greater than seconds, then any excess precision information will be
          * dropped.
@@ -7266,26 +7550,73 @@
         /**
          * Creates a {@link DynamicDuration} from a byte array generated by {@link
          * #toDynamicDurationByteArray()}.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
          */
         @NonNull
         static DynamicDuration fromByteArray(@NonNull byte[] byteArray) {
+            return fromByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Creates a {@link DynamicDuration} from the provided byte array at the provided offset and
+         * length, that was generated by one of the {@link #toDynamicDurationByteArray} overloads.
+         *
+         * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+         *     in the provided offset and length
+         */
+        @NonNull
+        static DynamicDuration fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
             try {
                 return dynamicDurationFromProto(
                         DynamicProto.DynamicDuration.parseFrom(
-                                byteArray, ExtensionRegistryLite.getEmptyRegistry()));
-            } catch (InvalidProtocolBufferException e) {
+                                CodedInputStream.newInstance(byteArray, offset, length),
+                                ExtensionRegistryLite.getEmptyRegistry()));
+            } catch (IOException e) {
                 throw new IllegalArgumentException(
                         "Byte array could not be parsed into DynamicDuration", e);
             }
         }
 
-        /** Creates a byte array that can later be used with {@link #fromByteArray(byte[])}. */
+        /**
+         * Serializes the {@link DynamicDuration} into a new byte array that can later be used with
+         * {@link #fromByteArray(byte[])}.
+         */
         @NonNull
         default byte[] toDynamicDurationByteArray() {
             return toDynamicDurationProto().toByteArray();
         }
 
         /**
+         * Serializes the {@link DynamicDuration} into the provided byte array, returning the amount
+         * of bytes written, that can later be used with {@code DynamicDuration.fromByteArray(
+         * byteArray, 0, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicDurationByteArray(@NonNull byte[] byteArray) {
+            return toDynamicDurationByteArray(byteArray, 0, byteArray.length);
+        }
+
+        /**
+         * Serializes the {@link DynamicDuration} into the provided byte array, returning the amount
+         * of bytes written, limited by the provided offset and length, that can later be used with
+         * {@code DynamicDuration.fromByteArray(byteArray, offset, bytesWritten)}.
+         *
+         * @throws IllegalArgumentException if the byte array is too small
+         */
+        default int toDynamicDurationByteArray(@NonNull byte[] byteArray, int offset, int length) {
+            CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+            try {
+                toDynamicDurationProto().writeTo(stream);
+            } catch (IOException e) {
+                throw new IllegalArgumentException(
+                        "Provided byte array not large enough to contain this DynamicDuration", e);
+            }
+            return stream.getTotalBytesWritten();
+        }
+
+        /**
          * Creates a constant-valued {@link DynamicDuration} from a {@link Duration}. If {@link
          * Duration} precision is greater than seconds, then any excess precision information will
          * be dropped.
diff --git a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicDataBuilders.java b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicDataBuilders.java
index 7f4eddd..8f91189 100644
--- a/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicDataBuilders.java
+++ b/wear/protolayout/protolayout-expression/src/main/java/androidx/wear/protolayout/expression/DynamicDataBuilders.java
@@ -27,6 +27,11 @@
 import androidx.wear.protolayout.expression.FixedValueBuilders.FixedInt32;
 import androidx.wear.protolayout.expression.FixedValueBuilders.FixedString;
 import androidx.wear.protolayout.expression.proto.DynamicDataProto;
+import androidx.wear.protolayout.protobuf.CodedInputStream;
+import androidx.wear.protolayout.protobuf.CodedOutputStream;
+import androidx.wear.protolayout.protobuf.ExtensionRegistryLite;
+
+import java.io.IOException;
 
 /** Builders for dynamic data value of a provider. */
 public final class DynamicDataBuilders {
@@ -46,6 +51,75 @@
     @NonNull
     DynamicDataProto.DynamicDataValue toDynamicDataValueProto();
 
+    /**
+     * Creates a {@link DynamicDataValue} from a byte array generated by {@link
+     * #toDynamicDataValueByteArray()}.
+     *
+     * @throws IllegalArgumentException if the byte array does not contain a valid serialization
+     */
+    @NonNull
+    static DynamicDataValue fromByteArray(@NonNull byte[] byteArray) {
+      return fromByteArray(byteArray, 0, byteArray.length);
+    }
+
+    /**
+     * Creates a {@link DynamicDataValue} from the provided byte array at the provided offset and
+     * length, that was generated by one of the {@link #toDynamicDataValueByteArray} overloads.
+     *
+     * @throws IllegalArgumentException if the byte array does not contain a valid serialization in
+     *     the provided offset and length
+     */
+    @NonNull
+    static DynamicDataValue fromByteArray(@NonNull byte[] byteArray, int offset, int length) {
+      try {
+        return dynamicDataValueFromProto(
+                DynamicDataProto.DynamicDataValue.parseFrom(
+                        CodedInputStream.newInstance(byteArray, offset, length),
+                        ExtensionRegistryLite.getEmptyRegistry()));
+      } catch (IOException e) {
+        throw new IllegalArgumentException(
+                "Byte array could not be parsed into DynamicDataValue", e);
+      }
+    }
+
+    /**
+     * Serializes the {@link DynamicDataValue} into a new byte array that can later be used with
+     * {@link #fromByteArray(byte[])}.
+     */
+    @NonNull
+    default byte[] toDynamicDataValueByteArray() {
+      return toDynamicDataValueProto().toByteArray();
+    }
+
+    /**
+     * Serializes the {@link DynamicDataValue} into the provided byte array, returning the amount of
+     * bytes written, that can later be used with {@code DynamicDataValue.fromByteArray(byteArray,
+     * 0, bytesWritten)}.
+     *
+     * @throws IllegalArgumentException if the byte array is too small
+     */
+    default int toDynamicDataValueByteArray(@NonNull byte[] byteArray) {
+      return toDynamicDataValueByteArray(byteArray, 0, byteArray.length);
+    }
+
+    /**
+     * Serializes the {@link DynamicDataValue} into the provided byte array, returning the amount of
+     * bytes written, limited by the provided offset and length, that can later be used with {@code
+     * DynamicDataValue.fromByteArray(byteArray, offset, bytesWritten)}.
+     *
+     * @throws IllegalArgumentException if the byte array is too small
+     */
+    default int toDynamicDataValueByteArray(@NonNull byte[] byteArray, int offset, int length) {
+      CodedOutputStream stream = CodedOutputStream.newInstance(byteArray, offset, length);
+      try {
+        toDynamicDataValueProto().writeTo(stream);
+      } catch (IOException e) {
+        throw new IllegalArgumentException(
+                "Provided byte array not large enough to contain this DynamicDataValue", e);
+      }
+      return stream.getTotalBytesWritten();
+    }
+
     /** Creates a boolean {@link DynamicDataValue}. */
     @NonNull
     static DynamicDataValue fromBool(boolean constant) {
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicBoolTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicBoolTest.java
index c7263ec..3c0bc87 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicBoolTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicBoolTest.java
@@ -144,7 +144,7 @@
     }
 
     @Test
-    public void validProto() {
+    public void fromByteArray_validProto() {
         DynamicBool from = DynamicBool.constant(true);
         DynamicBool to = DynamicBool.fromByteArray(from.toDynamicBoolByteArray());
 
@@ -152,8 +152,56 @@
     }
 
     @Test
-    public void invalidProto() {
+    public void fromByteArray_invalidProto() {
         assertThrows(
                 IllegalArgumentException.class, () -> DynamicBool.fromByteArray(new byte[] {1}));
     }
+
+    @Test
+    public void fromByteArray_existingByteArray() {
+        DynamicBool from = DynamicBool.constant(true);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicBoolByteArray(buffer, 10, 50);
+
+        DynamicBool to = DynamicBool.fromByteArray(buffer, 10, written);
+
+        assertThat(to.toDynamicBoolProto().getFixed().getValue()).isTrue();
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooSmall() {
+        DynamicBool from = DynamicBool.constant(true);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicBoolByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicBool.fromByteArray(buffer, 0, written - 1));
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooLarge() {
+        DynamicBool from = DynamicBool.constant(true);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicBoolByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicBool.fromByteArray(buffer, 0, written + 1));
+    }
+
+    @Test
+    public void toByteArray_existingByteArrayTooSmall() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicBool.constant(true).toDynamicBoolByteArray(new byte[1]));
+    }
+
+    @Test
+    public void toByteArray_existingByteArraySameSize() {
+        DynamicBool from = DynamicBool.constant(true);
+
+        assertThat(from.toDynamicBoolByteArray(new byte[100]))
+                .isEqualTo(from.toDynamicBoolByteArray().length);
+    }
 }
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
index 2751e61..d879ce5 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicColorTest.java
@@ -140,7 +140,7 @@
   }
 
   @Test
-  public void validProto() {
+  public void fromByteArray_validProto() {
     DynamicColor from = DynamicColor.constant(CONSTANT_VALUE);
     DynamicColor to = DynamicColor.fromByteArray(from.toDynamicColorByteArray());
 
@@ -148,7 +148,55 @@
   }
 
   @Test
-  public void invalidProto() {
+  public void fromByteArray_invalidProto() {
     assertThrows(IllegalArgumentException.class, () -> DynamicColor.fromByteArray(new byte[] {1}));
   }
+
+  @Test
+  public void fromByteArray_existingByteArray() {
+    DynamicColor from = DynamicColor.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicColorByteArray(buffer, 10, 50);
+
+    DynamicColor to = DynamicColor.fromByteArray(buffer, 10, written);
+
+    assertThat(to.toDynamicColorProto().getFixed().getArgb()).isEqualTo(CONSTANT_VALUE);
+  }
+
+  @Test
+  public void fromByteArray_existingByteArrayTooSmall() {
+    DynamicColor from = DynamicColor.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicColorByteArray(buffer);
+
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicColor.fromByteArray(buffer, 0, written - 1));
+  }
+
+  @Test
+  public void fromByteArray_existingByteArrayTooLarge() {
+    DynamicColor from = DynamicColor.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicColorByteArray(buffer);
+
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicColor.fromByteArray(buffer, 0, written + 1));
+  }
+
+  @Test
+  public void toByteArray_existingByteArrayTooSmall() {
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicColor.constant(CONSTANT_VALUE).toDynamicColorByteArray(new byte[1]));
+  }
+
+  @Test
+  public void toByteArray_existingByteArraySameSize() {
+    DynamicColor from = DynamicColor.constant(CONSTANT_VALUE);
+
+    assertThat(from.toDynamicColorByteArray(new byte[100]))
+            .isEqualTo(from.toDynamicColorByteArray().length);
+  }
 }
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
index 3036fbed..c7b9e7e 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicFloatTest.java
@@ -238,7 +238,7 @@
     }
 
     @Test
-    public void validProto() {
+    public void fromByteArray_validProto() {
         DynamicFloat from = DynamicFloat.constant(CONSTANT_VALUE);
         DynamicFloat to = DynamicFloat.fromByteArray(from.toDynamicFloatByteArray());
 
@@ -246,8 +246,56 @@
     }
 
     @Test
-    public void invalidProto() {
+    public void fromByteArray_invalidProto() {
         assertThrows(
                 IllegalArgumentException.class, () -> DynamicFloat.fromByteArray(new byte[] {1}));
     }
+
+    @Test
+    public void fromByteArray_existingByteArray() {
+        DynamicFloat from = DynamicFloat.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicFloatByteArray(buffer, 10, 50);
+
+        DynamicFloat to = DynamicFloat.fromByteArray(buffer, 10, written);
+
+        assertThat(to.toDynamicFloatProto().getFixed().getValue()).isEqualTo(CONSTANT_VALUE);
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooSmall() {
+        DynamicFloat from = DynamicFloat.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicFloatByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicFloat.fromByteArray(buffer, 0, written - 1));
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooLarge() {
+        DynamicFloat from = DynamicFloat.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicFloatByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicFloat.fromByteArray(buffer, 0, written + 1));
+    }
+
+    @Test
+    public void toByteArray_existingByteArrayTooSmall() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicFloat.constant(CONSTANT_VALUE).toDynamicFloatByteArray(new byte[1]));
+    }
+
+    @Test
+    public void toByteArray_existingByteArraySameSize() {
+        DynamicFloat from = DynamicFloat.constant(CONSTANT_VALUE);
+
+        assertThat(from.toDynamicFloatByteArray(new byte[100]))
+                .isEqualTo(from.toDynamicFloatByteArray().length);
+    }
 }
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicInt32Test.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicInt32Test.java
index a130199..ff1bc0f 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicInt32Test.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicInt32Test.java
@@ -131,7 +131,7 @@
     }
 
     @Test
-    public void validProto() {
+    public void fromByteArray_validProto() {
         DynamicInt32 from = DynamicInt32.constant(CONSTANT_VALUE);
         DynamicInt32 to = DynamicInt32.fromByteArray(from.toDynamicInt32ByteArray());
 
@@ -139,8 +139,56 @@
     }
 
     @Test
-    public void invalidProto() {
+    public void fromByteArray_invalidProto() {
         assertThrows(
                 IllegalArgumentException.class, () -> DynamicInt32.fromByteArray(new byte[] {1}));
     }
+
+    @Test
+    public void fromByteArray_existingByteArray() {
+        DynamicInt32 from = DynamicInt32.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicInt32ByteArray(buffer, 10, 50);
+
+        DynamicInt32 to = DynamicInt32.fromByteArray(buffer, 10, written);
+
+        assertThat(to.toDynamicInt32Proto().getFixed().getValue()).isEqualTo(CONSTANT_VALUE);
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooSmall() {
+        DynamicInt32 from = DynamicInt32.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicInt32ByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicInt32.fromByteArray(buffer, 0, written - 1));
+    }
+
+    @Test
+    public void fromByteArray_existingByteArrayTooLarge() {
+        DynamicInt32 from = DynamicInt32.constant(CONSTANT_VALUE);
+        byte[] buffer = new byte[100];
+        int written = from.toDynamicInt32ByteArray(buffer);
+
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicInt32.fromByteArray(buffer, 0, written + 1));
+    }
+
+    @Test
+    public void toByteArray_existingByteArrayTooSmall() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () -> DynamicInt32.constant(CONSTANT_VALUE).toDynamicInt32ByteArray(new byte[1]));
+    }
+
+    @Test
+    public void toByteArray_existingByteArraySameSize() {
+        DynamicInt32 from = DynamicInt32.constant(CONSTANT_VALUE);
+
+        assertThat(from.toDynamicInt32ByteArray(new byte[100]))
+                .isEqualTo(from.toDynamicInt32ByteArray().length);
+    }
 }
diff --git a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicStringTest.java b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicStringTest.java
index b33df22..658664f 100644
--- a/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicStringTest.java
+++ b/wear/protolayout/protolayout-expression/src/test/java/androidx/wear/protolayout/expression/DynamicStringTest.java
@@ -120,7 +120,7 @@
   }
 
   @Test
-  public void validProto() {
+  public void fromByteArray_validProto() {
     DynamicString from = DynamicString.constant(CONSTANT_VALUE);
     DynamicString to = DynamicString.fromByteArray(from.toDynamicStringByteArray());
 
@@ -128,7 +128,55 @@
   }
 
   @Test
-  public void invalidProto() {
+  public void fromByteArray_invalidProto() {
     assertThrows(IllegalArgumentException.class, () -> DynamicString.fromByteArray(new byte[] {1}));
   }
+
+  @Test
+  public void fromByteArray_existingByteArray() {
+    DynamicString from = DynamicString.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicStringByteArray(buffer, 10, 50);
+
+    DynamicString to = DynamicString.fromByteArray(buffer, 10, written);
+
+    assertThat(to.toDynamicStringProto().getFixed().getValue()).isEqualTo(CONSTANT_VALUE);
+  }
+
+  @Test
+  public void fromByteArray_existingByteArrayTooSmall() {
+    DynamicString from = DynamicString.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicStringByteArray(buffer);
+
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicString.fromByteArray(buffer, 0, written - 1));
+  }
+
+  @Test
+  public void fromByteArray_existingByteArrayTooLarge() {
+    DynamicString from = DynamicString.constant(CONSTANT_VALUE);
+    byte[] buffer = new byte[100];
+    int written = from.toDynamicStringByteArray(buffer);
+
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicString.fromByteArray(buffer, 0, written + 1));
+  }
+
+  @Test
+  public void toByteArray_existingByteArrayTooSmall() {
+    assertThrows(
+            IllegalArgumentException.class,
+            () -> DynamicString.constant(CONSTANT_VALUE).toDynamicStringByteArray(new byte[1]));
+  }
+
+  @Test
+  public void toByteArray_existingByteArraySameSize() {
+    DynamicString from = DynamicString.constant(CONSTANT_VALUE);
+
+    assertThat(from.toDynamicStringByteArray(new byte[100]))
+            .isEqualTo(from.toDynamicStringByteArray().length);
+  }
 }
diff --git a/window/window-testing/api/current.txt b/window/window-testing/api/current.txt
index 28a4315..c5abe75 100644
--- a/window/window-testing/api/current.txt
+++ b/window/window-testing/api/current.txt
@@ -36,15 +36,15 @@
 package androidx.window.testing.layout {
 
   public final class DisplayFeatureTesting {
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds);
   }
 
diff --git a/window/window-testing/api/public_plus_experimental_current.txt b/window/window-testing/api/public_plus_experimental_current.txt
index 28a4315..c5abe75 100644
--- a/window/window-testing/api/public_plus_experimental_current.txt
+++ b/window/window-testing/api/public_plus_experimental_current.txt
@@ -36,15 +36,15 @@
 package androidx.window.testing.layout {
 
   public final class DisplayFeatureTesting {
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds);
   }
 
diff --git a/window/window-testing/api/restricted_current.txt b/window/window-testing/api/restricted_current.txt
index 28a4315..c5abe75 100644
--- a/window/window-testing/api/restricted_current.txt
+++ b/window/window-testing/api/restricted_current.txt
@@ -36,15 +36,15 @@
 package androidx.window.testing.layout {
 
   public final class DisplayFeatureTesting {
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.app.Activity activity);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center, optional int size);
-    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional int center);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state, optional androidx.window.layout.FoldingFeature.Orientation orientation);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size, optional androidx.window.layout.FoldingFeature.State state);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center, optional int size);
+    method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds, optional @IntRange(from=-1L) int center);
     method public static androidx.window.layout.FoldingFeature createFoldingFeature(android.graphics.Rect windowBounds);
   }
 
diff --git a/window/window-testing/src/main/java/androidx/window/testing/layout/DisplayFeatureTesting.kt b/window/window-testing/src/main/java/androidx/window/testing/layout/DisplayFeatureTesting.kt
index ee66c4f..802279b 100644
--- a/window/window-testing/src/main/java/androidx/window/testing/layout/DisplayFeatureTesting.kt
+++ b/window/window-testing/src/main/java/androidx/window/testing/layout/DisplayFeatureTesting.kt
@@ -19,6 +19,7 @@
 
 import android.app.Activity
 import android.graphics.Rect
+import androidx.annotation.IntRange
 import androidx.window.layout.FoldingFeature
 import androidx.window.layout.FoldingFeature.OcclusionType.Companion.FULL
 import androidx.window.layout.FoldingFeature.OcclusionType.Companion.NONE
@@ -41,9 +42,14 @@
  * ([size] / 2) and the bottom-left y-coordinate is center - ([size] / 2). The folding features
  * always cover the window in one dimension and that determines the other coordinates.
  *
+ * The [center] is bounded below by -1. For values greater than -1 it will be set as the center.
+ * For -1 it signals that the center should be calculated. The calculation is the center of the
+ * [Activity] window bounds.
+ *
  * @param activity that will house the [FoldingFeature].
  * @param center the center of the fold complementary to the orientation in px. For a
- * [HORIZONTAL] fold, this is the y-axis and for a [VERTICAL] fold this is the x-axis.
+ * [HORIZONTAL] fold, this is the y-axis and for a [VERTICAL] fold this is the x-axis. The default
+ * value will be calculated to be in the middle of the window.
  * @param size the smaller dimension of the fold in px. The larger dimension always covers the
  * entire window.
  * @param state [State] of the fold. The default value is [HALF_OPENED]
@@ -55,6 +61,7 @@
 @JvmName("createFoldingFeature")
 fun FoldingFeature(
     activity: Activity,
+    @IntRange(from = -1)
     center: Int = -1,
     size: Int = 0,
     state: State = HALF_OPENED,
@@ -83,9 +90,14 @@
  * ([size] / 2) and the bottom-left y-coordinate is center - ([size] / 2). The folding features
  * always cover the window in one dimension and that determines the other coordinates.
  *
+ * The [center] is bounded below by -1. For values greater than -1 it will be set as the center.
+ * For -1 it signals that the center should be calculated. The calculation is the center of the
+ * [Activity] window bounds.
+ *
  * @param windowBounds that will contain the [FoldingFeature].
  * @param center the center of the fold complementary to the orientation in px. For a
- * [HORIZONTAL] fold, this is the y-axis and for a [VERTICAL] fold this is the x-axis.
+ * [HORIZONTAL] fold, this is the y-axis and for a [VERTICAL] fold this is the x-axis. The default
+ * value will be calculated to be in the middle of the window.
  * @param size the smaller dimension of the fold in px. The larger dimension always covers the
  * entire window.
  * @param state [State] of the fold. The default value is [HALF_OPENED]
@@ -97,6 +109,7 @@
 @JvmName("createFoldingFeature")
 fun FoldingFeature(
     windowBounds: Rect,
+    @IntRange(from = -1)
     center: Int = -1,
     size: Int = 0,
     state: State = HALF_OPENED,