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,